forked from mirrors/jj
view: turn BranchTarget into borrowed type
This isn't important, but I'm going to change remote_targets to store RemoteRef instead of RefTarget, so I went ahead and change the other field types as well.
This commit is contained in:
parent
92facbf21a
commit
e7d93e5bf1
8 changed files with 69 additions and 77 deletions
|
@ -389,28 +389,20 @@ fn cmd_branch_list(
|
|||
.map_or(true, |branch_names| branch_names.contains(name))
|
||||
});
|
||||
for (name, branch_target) in branches_to_list {
|
||||
let found_non_git_remote = {
|
||||
let pseudo_remote_count = branch_target
|
||||
.remote_targets
|
||||
.contains_key(git::REMOTE_NAME_FOR_LOCAL_GIT_REPO)
|
||||
as usize;
|
||||
branch_target.remote_targets.len() - pseudo_remote_count > 0
|
||||
};
|
||||
|
||||
write!(formatter.labeled("branch"), "{name}")?;
|
||||
if branch_target.local_target.is_present() {
|
||||
print_branch_target(formatter, &branch_target.local_target)?;
|
||||
print_branch_target(formatter, branch_target.local_target)?;
|
||||
} else {
|
||||
writeln!(formatter, " (deleted)")?;
|
||||
}
|
||||
|
||||
for (remote, remote_target) in branch_target.remote_targets.iter() {
|
||||
if remote_target == &branch_target.local_target {
|
||||
for &(remote, remote_target) in &branch_target.remote_targets {
|
||||
if remote_target == branch_target.local_target {
|
||||
continue;
|
||||
}
|
||||
write!(formatter, " ")?;
|
||||
write!(formatter.labeled("branch"), "@{remote}")?;
|
||||
let local_target = &branch_target.local_target;
|
||||
let local_target = branch_target.local_target;
|
||||
if local_target.is_present() {
|
||||
let remote_added_ids = remote_target.added_ids().cloned().collect_vec();
|
||||
let local_added_ids = local_target.added_ids().cloned().collect_vec();
|
||||
|
@ -434,6 +426,10 @@ fn cmd_branch_list(
|
|||
}
|
||||
|
||||
if branch_target.local_target.is_absent() {
|
||||
let found_non_git_remote = branch_target
|
||||
.remote_targets
|
||||
.iter()
|
||||
.any(|&(remote, _)| remote != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO);
|
||||
if found_non_git_remote {
|
||||
writeln!(
|
||||
formatter,
|
||||
|
|
|
@ -359,11 +359,11 @@ impl RefNamesIndex {
|
|||
fn build_branches_index(repo: &dyn Repo) -> RefNamesIndex {
|
||||
let mut index = RefNamesIndex::default();
|
||||
for (branch_name, branch_target) in repo.view().branches() {
|
||||
let local_target = &branch_target.local_target;
|
||||
let local_target = branch_target.local_target;
|
||||
let mut unsynced_remote_targets = branch_target
|
||||
.remote_targets
|
||||
.iter()
|
||||
.filter(|&(_, target)| target != local_target)
|
||||
.filter(|&&(_, target)| target != local_target)
|
||||
.peekable();
|
||||
if local_target.is_present() {
|
||||
let decorated_name = if local_target.has_conflict() {
|
||||
|
@ -375,7 +375,7 @@ fn build_branches_index(repo: &dyn Repo) -> RefNamesIndex {
|
|||
};
|
||||
index.insert(local_target.added_ids(), decorated_name);
|
||||
}
|
||||
for (remote_name, target) in unsynced_remote_targets {
|
||||
for &(remote_name, target) in unsynced_remote_targets {
|
||||
let decorated_name = if target.has_conflict() {
|
||||
format!("{branch_name}@{remote_name}?")
|
||||
} else {
|
||||
|
|
|
@ -166,18 +166,13 @@ impl<'a> RefTargetOptionExt for Option<&'a RefTarget> {
|
|||
}
|
||||
}
|
||||
|
||||
content_hash! {
|
||||
#[derive(Default, PartialEq, Eq, Clone, Debug)]
|
||||
pub struct BranchTarget {
|
||||
/// The commit the branch points to locally. `None` if the branch has been
|
||||
/// deleted locally.
|
||||
pub local_target: RefTarget,
|
||||
// TODO: Do we need to support tombstones for remote branches? For example, if the branch
|
||||
// has been deleted locally and you pull from a remote, maybe it should make a difference
|
||||
// whether the branch is known to have existed on the remote. We may not want to resurrect
|
||||
// the branch if the branch's state on the remote was just not known.
|
||||
pub remote_targets: BTreeMap<String, RefTarget>,
|
||||
}
|
||||
/// Local and remote branches of the same branch name.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
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)>,
|
||||
}
|
||||
|
||||
content_hash! {
|
||||
|
@ -208,6 +203,10 @@ content_hash! {
|
|||
/// Represents the state of the remote repo.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct RemoteView {
|
||||
// TODO: Do we need to support tombstones for remote branches? For example, if the branch
|
||||
// has been deleted locally and you pull from a remote, maybe it should make a difference
|
||||
// whether the branch is known to have existed on the remote. We may not want to resurrect
|
||||
// the branch if the branch's state on the remote was just not known.
|
||||
pub branches: BTreeMap<String, RemoteRef>,
|
||||
// TODO: pub tags: BTreeMap<String, RemoteRef>,
|
||||
}
|
||||
|
@ -217,7 +216,7 @@ content_hash! {
|
|||
pub(crate) fn merge_join_branch_views<'a>(
|
||||
local_branches: &'a BTreeMap<String, RefTarget>,
|
||||
remote_views: &'a BTreeMap<String, RemoteView>,
|
||||
) -> impl Iterator<Item = (&'a str, BranchTarget)> {
|
||||
) -> impl Iterator<Item = (&'a str, BranchTarget<'a>)> {
|
||||
let mut local_branches_iter = local_branches
|
||||
.iter()
|
||||
.map(|(branch_name, target)| (branch_name.as_str(), target))
|
||||
|
@ -234,18 +233,14 @@ pub(crate) fn merge_join_branch_views<'a>(
|
|||
} else {
|
||||
local_branches_iter.next()?
|
||||
};
|
||||
// TODO: add borrowed version of BranchTarget?
|
||||
let mut branch_target = BranchTarget {
|
||||
local_target: local_target.clone(),
|
||||
..Default::default()
|
||||
let remote_targets = remote_branches_iter
|
||||
.peeking_take_while(|&((remote_branch_name, _), _)| remote_branch_name == branch_name)
|
||||
.map(|((_, remote_name), target)| (remote_name, target))
|
||||
.collect();
|
||||
let branch_target = BranchTarget {
|
||||
local_target,
|
||||
remote_targets,
|
||||
};
|
||||
while let Some(((_, remote_name), target)) = remote_branches_iter
|
||||
.next_if(|&((remote_branch_name, _), _)| remote_branch_name == branch_name)
|
||||
{
|
||||
branch_target
|
||||
.remote_targets
|
||||
.insert(remote_name.to_owned(), target.clone());
|
||||
}
|
||||
Some((branch_name, branch_target))
|
||||
})
|
||||
}
|
||||
|
@ -381,21 +376,21 @@ mod tests {
|
|||
(
|
||||
"branch1",
|
||||
BranchTarget {
|
||||
local_target: local_branch1_target.clone(),
|
||||
remote_targets: btreemap! {
|
||||
"git".to_owned() => git_branch1_target.clone(),
|
||||
"remote1".to_owned() => remote1_branch1_target.clone(),
|
||||
},
|
||||
local_target: &local_branch1_target,
|
||||
remote_targets: vec![
|
||||
("git", &git_branch1_target),
|
||||
("remote1", &remote1_branch1_target),
|
||||
],
|
||||
},
|
||||
),
|
||||
(
|
||||
"branch2",
|
||||
BranchTarget {
|
||||
local_target: local_branch2_target.clone(),
|
||||
remote_targets: btreemap! {
|
||||
"git".to_owned() => git_branch2_target.clone(),
|
||||
"remote2".to_owned() => remote2_branch2_target.clone(),
|
||||
},
|
||||
local_target: &local_branch2_target,
|
||||
remote_targets: vec![
|
||||
("git", &git_branch2_target),
|
||||
("remote2", &remote2_branch2_target),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -411,8 +406,8 @@ mod tests {
|
|||
vec![(
|
||||
"branch1",
|
||||
BranchTarget {
|
||||
local_target: local_branch1_target.clone(),
|
||||
remote_targets: btreemap! {},
|
||||
local_target: &local_branch1_target,
|
||||
remote_targets: vec![],
|
||||
},
|
||||
)],
|
||||
);
|
||||
|
@ -431,10 +426,8 @@ mod tests {
|
|||
vec![(
|
||||
"branch1",
|
||||
BranchTarget {
|
||||
local_target: RefTarget::absent(),
|
||||
remote_targets: btreemap! {
|
||||
"remote1".to_owned() => remote1_branch1_target.clone(),
|
||||
},
|
||||
local_target: RefTarget::absent_ref(),
|
||||
remote_targets: vec![("remote1", &remote1_branch1_target)],
|
||||
},
|
||||
)],
|
||||
);
|
||||
|
|
|
@ -2034,7 +2034,7 @@ fn collect_branch_symbols(repo: &dyn Repo, include_synced_remotes: bool) -> Vec<
|
|||
let remote_symbols = branch_target
|
||||
.remote_targets
|
||||
.into_iter()
|
||||
.filter(move |(_, target)| include_synced_remotes || *target != local_target)
|
||||
.filter(move |&(_, target)| include_synced_remotes || target != local_target)
|
||||
.map(move |(remote_name, _)| format!("{name}@{remote_name}"));
|
||||
local_symbol.into_iter().chain(remote_symbols)
|
||||
})
|
||||
|
|
|
@ -344,14 +344,14 @@ fn branch_views_to_proto_legacy(
|
|||
) -> Vec<crate::protos::op_store::Branch> {
|
||||
op_store::merge_join_branch_views(local_branches, remote_views)
|
||||
.map(|(name, branch_target)| {
|
||||
let local_target = ref_target_to_proto(&branch_target.local_target);
|
||||
let local_target = ref_target_to_proto(branch_target.local_target);
|
||||
let remote_branches = branch_target
|
||||
.remote_targets
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(
|
||||
|(remote_name, target)| crate::protos::op_store::RemoteBranch {
|
||||
remote_name,
|
||||
target: ref_target_to_proto(&target),
|
||||
|&(remote_name, target)| crate::protos::op_store::RemoteBranch {
|
||||
remote_name: remote_name.to_owned(),
|
||||
target: ref_target_to_proto(target),
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
|
|
|
@ -87,7 +87,7 @@ impl View {
|
|||
}
|
||||
|
||||
/// Iterates pair of local and remote branches by branch name.
|
||||
pub fn branches(&self) -> impl Iterator<Item = (&str, BranchTarget)> {
|
||||
pub fn branches(&self) -> impl Iterator<Item = (&str, BranchTarget<'_>)> {
|
||||
op_store::merge_join_branch_views(&self.data.local_branches, &self.data.remote_views)
|
||||
}
|
||||
|
||||
|
|
|
@ -1796,10 +1796,10 @@ fn test_fetch_initial_commit() {
|
|||
view.branches().collect::<BTreeMap<_, _>>(),
|
||||
btreemap! {
|
||||
"main" => BranchTarget {
|
||||
local_target: initial_commit_target.clone(),
|
||||
remote_targets: btreemap! {
|
||||
"origin".to_string() => initial_commit_target,
|
||||
},
|
||||
local_target: &initial_commit_target,
|
||||
remote_targets: vec![
|
||||
("origin", &initial_commit_target),
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -1867,10 +1867,10 @@ fn test_fetch_success() {
|
|||
view.branches().collect::<BTreeMap<_, _>>(),
|
||||
btreemap! {
|
||||
"main" => BranchTarget {
|
||||
local_target: new_commit_target.clone(),
|
||||
remote_targets: btreemap! {
|
||||
"origin".to_string() => new_commit_target.clone(),
|
||||
},
|
||||
local_target: &new_commit_target,
|
||||
remote_targets: vec![
|
||||
("origin", &new_commit_target),
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
@ -289,22 +289,25 @@ 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 expected_main_branch = BranchTarget {
|
||||
local_target: RefTarget::from_legacy_form(
|
||||
local_target: &RefTarget::from_legacy_form(
|
||||
[main_branch_local_tx0.id().clone()],
|
||||
[
|
||||
main_branch_local_tx1.id().clone(),
|
||||
main_branch_local_tx2.id().clone(),
|
||||
],
|
||||
),
|
||||
remote_targets: btreemap! {
|
||||
"origin".to_string() => RefTarget::normal(main_branch_origin_tx1.id().clone()),
|
||||
"alternate".to_string() => RefTarget::normal(main_branch_alternate_tx0.id().clone()),
|
||||
},
|
||||
remote_targets: vec![
|
||||
("alternate", &main_branch_alternate_tx0_target),
|
||||
("origin", &main_branch_origin_tx1_target),
|
||||
],
|
||||
};
|
||||
let expected_feature_branch = BranchTarget {
|
||||
local_target: RefTarget::normal(feature_branch_tx1.id().clone()),
|
||||
remote_targets: btreemap! {},
|
||||
local_target: &RefTarget::normal(feature_branch_tx1.id().clone()),
|
||||
remote_targets: vec![],
|
||||
};
|
||||
assert_eq!(
|
||||
repo.view().branches().collect::<BTreeMap<_, _>>(),
|
||||
|
|
Loading…
Reference in a new issue