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:
parent
e7d93e5bf1
commit
ab1a6e2f71
12 changed files with 104 additions and 84 deletions
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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)],
|
||||
},
|
||||
)],
|
||||
);
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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),
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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<_, _>>(),
|
||||
|
|
Loading…
Reference in a new issue