ok/jj
1
0
Fork 0
forked from mirrors/jj

view: make remote branches iterator yield RemoteRef instead of RefTarget

git::import_refs() will need to read RemoteRef's tracking state.
This commit is contained in:
Yuya Nishihara 2023-10-12 19:00:55 +09:00
parent e7d93e5bf1
commit ab1a6e2f71
12 changed files with 104 additions and 84 deletions

View file

@ -396,15 +396,15 @@ fn cmd_branch_list(
writeln!(formatter, " (deleted)")?;
}
for &(remote, remote_target) in &branch_target.remote_targets {
if remote_target == branch_target.local_target {
for &(remote, remote_ref) in &branch_target.remote_refs {
if remote_ref.target == *branch_target.local_target {
continue;
}
write!(formatter, " ")?;
write!(formatter.labeled("branch"), "@{remote}")?;
let local_target = branch_target.local_target;
if local_target.is_present() {
let remote_added_ids = remote_target.added_ids().cloned().collect_vec();
let remote_added_ids = remote_ref.target.added_ids().cloned().collect_vec();
let local_added_ids = local_target.added_ids().cloned().collect_vec();
let remote_ahead_count =
revset::walk_revs(repo.as_ref(), &remote_added_ids, &local_added_ids)?.count();
@ -422,12 +422,12 @@ fn cmd_branch_list(
)?;
}
}
print_branch_target(formatter, remote_target)?;
print_branch_target(formatter, &remote_ref.target)?;
}
if branch_target.local_target.is_absent() {
let found_non_git_remote = branch_target
.remote_targets
.remote_refs
.iter()
.any(|&(remote, _)| remote != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO);
if found_non_git_remote {

View file

@ -896,7 +896,7 @@ fn cmd_git_push(
let mut old_heads = repo
.view()
.remote_branches(&remote)
.flat_map(|(_, old_head)| old_head.added_ids())
.flat_map(|(_, old_head)| old_head.target.added_ids())
.cloned()
.collect_vec();
if old_heads.is_empty() {

View file

@ -1649,7 +1649,7 @@ fn cmd_status(
let conflicted_remote_branches = repo
.view()
.all_remote_branches()
.filter(|(_, target)| target.has_conflict())
.filter(|(_, remote_ref)| remote_ref.target.has_conflict())
.map(|(full_name, _)| full_name)
.collect_vec();
if !conflicted_local_branches.is_empty() {

View file

@ -361,9 +361,9 @@ fn build_branches_index(repo: &dyn Repo) -> RefNamesIndex {
for (branch_name, branch_target) in repo.view().branches() {
let local_target = branch_target.local_target;
let mut unsynced_remote_targets = branch_target
.remote_targets
.remote_refs
.iter()
.filter(|&&(_, target)| target != local_target)
.filter(|&&(_, remote_ref)| remote_ref.target != *local_target)
.peekable();
if local_target.is_present() {
let decorated_name = if local_target.has_conflict() {
@ -375,13 +375,13 @@ fn build_branches_index(repo: &dyn Repo) -> RefNamesIndex {
};
index.insert(local_target.added_ids(), decorated_name);
}
for &(remote_name, target) in unsynced_remote_targets {
let decorated_name = if target.has_conflict() {
for &(remote_name, remote_ref) in unsynced_remote_targets {
let decorated_name = if remote_ref.target.has_conflict() {
format!("{branch_name}@{remote_name}?")
} else {
format!("{branch_name}@{remote_name}")
};
index.insert(target.added_ids(), decorated_name);
index.insert(remote_ref.target.added_ids(), decorated_name);
}
}
index

View file

@ -342,7 +342,7 @@ fn diff_refs_to_import(
.collect();
let mut known_remote_refs: HashMap<RefName, &RefTarget> = itertools::chain(
view.all_remote_branches()
.map(|((branch, remote), target)| {
.map(|((branch, remote), remote_ref)| {
// TODO: want to abstract local ref as "git" tracking remote, but
// we'll probably need to refactor the git_ref_filter API first.
let ref_name = if remote == REMOTE_NAME_FOR_LOCAL_GIT_REPO {
@ -353,7 +353,7 @@ fn diff_refs_to_import(
remote: remote.to_owned(),
}
};
(ref_name, target)
(ref_name, &remote_ref.target)
}),
// TODO: compare to tags stored in the "git" remote view. Since tags should never
// be moved locally in jj, we can consider local tags as merge base.
@ -591,12 +591,12 @@ fn diff_refs_to_export(
.map(|(branch, target)| (RefName::LocalBranch(branch.to_owned()), target)),
view.all_remote_branches()
.filter(|&((_, remote), _)| remote != REMOTE_NAME_FOR_LOCAL_GIT_REPO)
.map(|((branch, remote), target)| {
.map(|((branch, remote), remote_ref)| {
let ref_name = RefName::RemoteBranch {
branch: branch.to_owned(),
remote: remote.to_owned(),
};
(ref_name, target)
(ref_name, &remote_ref.target)
}),
)
.map(|(ref_name, new_target)| (ref_name, (RefTarget::absent_ref(), new_target)))

View file

@ -171,8 +171,8 @@ impl<'a> RefTargetOptionExt for Option<&'a RefTarget> {
pub struct BranchTarget<'a> {
/// The commit the branch points to locally.
pub local_target: &'a RefTarget,
/// `(remote_name, target)` pairs in lexicographical order.
pub remote_targets: Vec<(&'a str, &'a RefTarget)>,
/// `(remote_name, remote_ref)` pairs in lexicographical order.
pub remote_refs: Vec<(&'a str, &'a RemoteRef)>,
}
content_hash! {
@ -233,22 +233,23 @@ pub(crate) fn merge_join_branch_views<'a>(
} else {
local_branches_iter.next()?
};
let remote_targets = remote_branches_iter
let remote_refs = remote_branches_iter
.peeking_take_while(|&((remote_branch_name, _), _)| remote_branch_name == branch_name)
.map(|((_, remote_name), target)| (remote_name, target))
.map(|((_, remote_name), remote_ref)| (remote_name, remote_ref))
.collect();
let branch_target = BranchTarget {
local_target,
remote_targets,
remote_refs,
};
Some((branch_name, branch_target))
})
}
/// Iterates branch `((name, remote_name), target)`s in lexicographical order.
/// Iterates branch `((name, remote_name), remote_ref)`s in lexicographical
/// order.
pub(crate) fn flatten_remote_branches(
remote_views: &BTreeMap<String, RemoteView>,
) -> impl Iterator<Item = ((&str, &str), &RefTarget)> {
) -> impl Iterator<Item = ((&str, &str), &RemoteRef)> {
remote_views
.iter()
.map(|(remote_name, remote_view)| {
@ -257,7 +258,7 @@ pub(crate) fn flatten_remote_branches(
.iter()
.map(move |(branch_name, remote_ref)| {
let full_name = (branch_name.as_str(), remote_name.as_str());
(full_name, &remote_ref.target)
(full_name, remote_ref)
})
})
.kmerge_by(|(full_name1, _), (full_name2, _)| full_name1 < full_name2)
@ -343,10 +344,12 @@ mod tests {
};
let local_branch1_target = RefTarget::normal(CommitId::from_hex("111111"));
let local_branch2_target = RefTarget::normal(CommitId::from_hex("222222"));
let git_branch1_target = RefTarget::normal(CommitId::from_hex("333333"));
let git_branch2_target = RefTarget::normal(CommitId::from_hex("444444"));
let remote1_branch1_target = RefTarget::normal(CommitId::from_hex("555555"));
let remote2_branch2_target = RefTarget::normal(CommitId::from_hex("666666"));
let git_branch1_remote_ref = remote_ref(&RefTarget::normal(CommitId::from_hex("333333")));
let git_branch2_remote_ref = remote_ref(&RefTarget::normal(CommitId::from_hex("444444")));
let remote1_branch1_remote_ref =
remote_ref(&RefTarget::normal(CommitId::from_hex("555555")));
let remote2_branch2_remote_ref =
remote_ref(&RefTarget::normal(CommitId::from_hex("666666")));
let local_branches = btreemap! {
"branch1".to_owned() => local_branch1_target.clone(),
@ -355,18 +358,18 @@ mod tests {
let remote_views = btreemap! {
"git".to_owned() => RemoteView {
branches: btreemap! {
"branch1".to_owned() => remote_ref(&git_branch1_target),
"branch2".to_owned() => remote_ref(&git_branch2_target),
"branch1".to_owned() => git_branch1_remote_ref.clone(),
"branch2".to_owned() => git_branch2_remote_ref.clone(),
},
},
"remote1".to_owned() => RemoteView {
branches: btreemap! {
"branch1".to_owned() => remote_ref(&remote1_branch1_target),
"branch1".to_owned() => remote1_branch1_remote_ref.clone(),
},
},
"remote2".to_owned() => RemoteView {
branches: btreemap! {
"branch2".to_owned() => remote_ref(&remote2_branch2_target),
"branch2".to_owned() => remote2_branch2_remote_ref.clone(),
},
},
};
@ -377,19 +380,19 @@ mod tests {
"branch1",
BranchTarget {
local_target: &local_branch1_target,
remote_targets: vec![
("git", &git_branch1_target),
("remote1", &remote1_branch1_target),
remote_refs: vec![
("git", &git_branch1_remote_ref),
("remote1", &remote1_branch1_remote_ref),
],
},
),
(
"branch2",
BranchTarget {
local_target: &local_branch2_target,
remote_targets: vec![
("git", &git_branch2_target),
("remote2", &remote2_branch2_target),
local_target: &local_branch2_target.clone(),
remote_refs: vec![
("git", &git_branch2_remote_ref),
("remote2", &remote2_branch2_remote_ref),
],
},
),
@ -407,7 +410,7 @@ mod tests {
"branch1",
BranchTarget {
local_target: &local_branch1_target,
remote_targets: vec![],
remote_refs: vec![],
},
)],
);
@ -417,7 +420,7 @@ mod tests {
let remote_views = btreemap! {
"remote1".to_owned() => RemoteView {
branches: btreemap! {
"branch1".to_owned() => remote_ref(&remote1_branch1_target),
"branch1".to_owned() => remote1_branch1_remote_ref.clone(),
},
},
};
@ -427,7 +430,7 @@ mod tests {
"branch1",
BranchTarget {
local_target: RefTarget::absent_ref(),
remote_targets: vec![("remote1", &remote1_branch1_target)],
remote_refs: vec![("remote1", &remote1_branch1_remote_ref)],
},
)],
);

View file

@ -1108,15 +1108,20 @@ impl MutableRepo {
let changed_refs = itertools::chain!(
diff_named_refs(base.local_branches(), other.local_branches())
.map(|(name, diff)| (RefName::LocalBranch(name.to_owned()), diff)),
diff_named_refs(base.all_remote_branches(), other.all_remote_branches()).map(
|((branch, remote), diff)| {
let ref_name = RefName::RemoteBranch {
branch: branch.to_owned(),
remote: remote.to_owned(),
};
(ref_name, diff)
}
),
diff_named_refs(
base.all_remote_branches()
.map(|(full_name, remote_ref)| (full_name, &remote_ref.target)),
other
.all_remote_branches()
.map(|(full_name, remote_ref)| (full_name, &remote_ref.target)),
)
.map(|((branch, remote), diff)| {
let ref_name = RefName::RemoteBranch {
branch: branch.to_owned(),
remote: remote.to_owned(),
};
(ref_name, diff)
}),
diff_named_refs(base.tags(), other.tags())
.map(|(name, diff)| (RefName::Tag(name.to_owned()), diff)),
diff_named_refs(base.git_refs(), other.git_refs())

View file

@ -2032,9 +2032,11 @@ fn collect_branch_symbols(repo: &dyn Repo, include_synced_remotes: bool) -> Vec<
let local_target = branch_target.local_target;
let local_symbol = local_target.is_present().then(|| name.to_owned());
let remote_symbols = branch_target
.remote_targets
.remote_refs
.into_iter()
.filter(move |&(_, target)| include_synced_remotes || target != local_target)
.filter(move |&(_, remote_ref)| {
include_synced_remotes || remote_ref.target != *local_target
})
.map(move |(remote_name, _)| format!("{name}@{remote_name}"));
local_symbol.into_iter().chain(remote_symbols)
})

View file

@ -346,12 +346,12 @@ fn branch_views_to_proto_legacy(
.map(|(name, branch_target)| {
let local_target = ref_target_to_proto(branch_target.local_target);
let remote_branches = branch_target
.remote_targets
.remote_refs
.iter()
.map(
|&(remote_name, target)| crate::protos::op_store::RemoteBranch {
|&(remote_name, remote_ref)| crate::protos::op_store::RemoteBranch {
remote_name: remote_name.to_owned(),
target: ref_target_to_proto(target),
target: ref_target_to_proto(&remote_ref.target),
},
)
.collect();

View file

@ -190,24 +190,22 @@ impl View {
}
}
/// Iterates remote branch `((name, remote_name), target)`s in
/// Iterates remote branch `((name, remote_name), remote_ref)`s in
/// lexicographical order.
pub fn all_remote_branches(&self) -> impl Iterator<Item = ((&str, &str), &RefTarget)> {
// TODO: maybe yield RemoteRef instead of RefTarget?
pub fn all_remote_branches(&self) -> impl Iterator<Item = ((&str, &str), &RemoteRef)> {
op_store::flatten_remote_branches(&self.data.remote_views)
}
/// Iterates branch `(name, target)`s of the specified remote in
/// Iterates branch `(name, remote_ref)`s of the specified remote in
/// lexicographical order.
pub fn remote_branches(&self, remote_name: &str) -> impl Iterator<Item = (&str, &RefTarget)> {
// TODO: maybe yield RemoteRef instead of RefTarget?
pub fn remote_branches(&self, remote_name: &str) -> impl Iterator<Item = (&str, &RemoteRef)> {
let maybe_remote_view = self.data.remote_views.get(remote_name);
maybe_remote_view
.map(|remote_view| {
remote_view
.branches
.iter()
.map(|(name, remote_ref)| (name.as_ref(), &remote_ref.target))
.map(|(name, remote_ref)| (name.as_ref(), remote_ref))
})
.into_iter()
.flatten()
@ -250,15 +248,18 @@ impl View {
) -> impl Iterator<Item = (&'a str, TrackingRefPair<'a>)> + 'a {
// TODO: maybe untracked remote target can be translated to absent, and rename
// the method accordingly.
iter_named_ref_pairs(self.local_branches(), self.remote_branches(remote_name)).map(
|(name, (local_target, remote_target))| {
let targets = TrackingRefPair {
local_target,
remote_target,
};
(name, targets)
},
iter_named_ref_pairs(
self.local_branches(),
self.remote_branches(remote_name)
.map(|(name, remote_ref)| (name, &remote_ref.target)),
)
.map(|(name, (local_target, remote_target))| {
let targets = TrackingRefPair {
local_target,
remote_target,
};
(name, targets)
})
}
pub fn remove_remote(&mut self, remote_name: &str) {

View file

@ -31,7 +31,7 @@ use jj_lib::git::{
GitRefUpdate, SubmoduleConfig,
};
use jj_lib::git_backend::GitBackend;
use jj_lib::op_store::{BranchTarget, RefTarget};
use jj_lib::op_store::{BranchTarget, RefTarget, RemoteRef};
use jj_lib::repo::{MutableRepo, ReadonlyRepo, Repo};
use jj_lib::settings::{GitSettings, UserSettings};
use jj_lib::view::RefName;
@ -1786,6 +1786,9 @@ fn test_fetch_initial_commit() {
let view = repo.view();
assert!(view.heads().contains(&jj_id(&initial_git_commit)));
let initial_commit_target = RefTarget::normal(jj_id(&initial_git_commit));
let initial_commit_remote_ref = RemoteRef {
target: initial_commit_target.clone(),
};
assert_eq!(
*view.git_refs(),
btreemap! {
@ -1797,8 +1800,8 @@ fn test_fetch_initial_commit() {
btreemap! {
"main" => BranchTarget {
local_target: &initial_commit_target,
remote_targets: vec![
("origin", &initial_commit_target),
remote_refs: vec![
("origin", &initial_commit_remote_ref),
],
},
}
@ -1856,6 +1859,9 @@ fn test_fetch_success() {
let view = repo.view();
assert!(view.heads().contains(&jj_id(&new_git_commit)));
let new_commit_target = RefTarget::normal(jj_id(&new_git_commit));
let new_commit_remote_ref = RemoteRef {
target: new_commit_target.clone(),
};
assert_eq!(
*view.git_refs(),
btreemap! {
@ -1868,8 +1874,8 @@ fn test_fetch_success() {
btreemap! {
"main" => BranchTarget {
local_target: &new_commit_target,
remote_targets: vec![
("origin", &new_commit_target),
remote_refs: vec![
("origin", &new_commit_remote_ref),
],
},
}

View file

@ -14,7 +14,7 @@
use std::collections::BTreeMap;
use jj_lib::op_store::{BranchTarget, RefTarget, WorkspaceId};
use jj_lib::op_store::{BranchTarget, RefTarget, RemoteRef, WorkspaceId};
use jj_lib::repo::Repo;
use maplit::{btreemap, hashset};
use test_case::test_case;
@ -289,9 +289,12 @@ fn test_merge_views_branches() {
);
let repo = commit_transactions(&settings, vec![tx1, tx2]);
let main_branch_origin_tx1_target = RefTarget::normal(main_branch_origin_tx1.id().clone());
let main_branch_alternate_tx0_target =
RefTarget::normal(main_branch_alternate_tx0.id().clone());
let main_branch_origin_tx1_remote_ref = RemoteRef {
target: RefTarget::normal(main_branch_origin_tx1.id().clone()),
};
let main_branch_alternate_tx0_remote_ref = RemoteRef {
target: RefTarget::normal(main_branch_alternate_tx0.id().clone()),
};
let expected_main_branch = BranchTarget {
local_target: &RefTarget::from_legacy_form(
[main_branch_local_tx0.id().clone()],
@ -300,14 +303,14 @@ fn test_merge_views_branches() {
main_branch_local_tx2.id().clone(),
],
),
remote_targets: vec![
("alternate", &main_branch_alternate_tx0_target),
("origin", &main_branch_origin_tx1_target),
remote_refs: vec![
("alternate", &main_branch_alternate_tx0_remote_ref),
("origin", &main_branch_origin_tx1_remote_ref),
],
};
let expected_feature_branch = BranchTarget {
local_target: &RefTarget::normal(feature_branch_tx1.id().clone()),
remote_targets: vec![],
remote_refs: vec![],
};
assert_eq!(
repo.view().branches().collect::<BTreeMap<_, _>>(),