From 420bf79217796b2bcc97a0e86d9e897f638aa325 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Fri, 6 Oct 2023 16:17:26 +0900 Subject: [PATCH] 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. --- lib/src/git.rs | 9 ++++----- lib/src/refs.rs | 7 +++++++ lib/src/view.rs | 26 +++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/src/git.rs b/lib/src/git.rs index 94ced79f7..a73786e15 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -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()))) diff --git a/lib/src/refs.rs b/lib/src/refs.rs index c18308668..3c41bde4d 100644 --- a/lib/src/refs.rs +++ b/lib/src/refs.rs @@ -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, diff --git a/lib/src/view.rs b/lib/src/view.rs index 9d90f3cf7..13e450667 100644 --- a/lib/src/view.rs +++ b/lib/src/view.rs @@ -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)> + '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();