view: add method to iterate local/remote pairs of certain remote

This is common operation, and we don't need a map of all remote targets
to calculate push action.
This commit is contained in:
Yuya Nishihara 2023-10-06 16:17:26 +09:00
parent 37f11c7d4e
commit 420bf79217
3 changed files with 36 additions and 6 deletions

View file

@ -563,11 +563,10 @@ fn copy_exportable_local_branches_to_remote_view(
) {
let new_local_branches = mut_repo
.view()
.branches()
.iter()
.filter_map(|(branch, branch_target)| {
let old_target = branch_target.remote_targets.get(remote_name).flatten();
let new_target = &branch_target.local_target;
.local_remote_branches(remote_name)
.filter_map(|(branch, targets)| {
let old_target = targets.remote_target;
let new_target = targets.local_target;
(!new_target.has_conflict() && old_target != new_target).then_some((branch, new_target))
})
.filter(|&(branch, _)| git_ref_filter(&RefName::LocalBranch(branch.to_owned())))

View file

@ -113,6 +113,13 @@ fn find_pair_to_remove(
None
}
/// Pair of local and remote targets which usually represents a tracking branch.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TrackingRefPair<'a> {
pub local_target: &'a RefTarget,
pub remote_target: &'a RefTarget,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct BranchPushUpdate {
pub old_target: Option<CommitId>,

View file

@ -23,7 +23,7 @@ use crate::backend::CommitId;
use crate::index::Index;
use crate::op_store;
use crate::op_store::{BranchTarget, RefTarget, RefTargetOptionExt as _, WorkspaceId};
use crate::refs::merge_ref_targets;
use crate::refs::{merge_ref_targets, TrackingRefPair};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
pub enum RefName {
@ -250,6 +250,30 @@ impl View {
}
}
/// Iterates local/remote branch `(name, targets)`s of the specified remote
/// in lexicographical order.
pub fn local_remote_branches<'a>(
&'a self,
remote_name: &'a str, // TODO: migrate to per-remote view and remove 'a
) -> impl Iterator<Item = (&'a str, TrackingRefPair<'a>)> + 'a {
// TODO: maybe untracked remote_target can be translated to absent, and rename
// the method accordingly.
self.data
.branches
.iter()
.filter_map(move |(name, branch_target)| {
let local_target = &branch_target.local_target;
let remote_target = branch_target.remote_targets.get(remote_name).flatten();
(local_target.is_present() || remote_target.is_present()).then_some((
name.as_ref(),
TrackingRefPair {
local_target,
remote_target,
},
))
})
}
pub fn rename_remote(&mut self, old: &str, new: &str) {
for branch in self.data.branches.values_mut() {
let target = branch.remote_targets.remove(old).flatten();