refs: add helper function to iterate local/remote ref pairs

This partially reverts the change in 30fb7995c2 "view: make local/remote
branches iterator yield RemoteRef instead of RefTarget." As I'm going to add
diff function for RemoteRef pairs, we'll need a generic version of merge-join
iterator anyway.
This commit is contained in:
Yuya Nishihara 2023-10-21 07:37:57 +09:00
parent baef7f1da2
commit 59eb03eec5
2 changed files with 41 additions and 36 deletions

View file

@ -28,23 +28,43 @@ pub fn diff_named_refs<'a, 'b, K: Ord>(
refs1: impl IntoIterator<Item = (K, &'a RefTarget)>,
refs2: impl IntoIterator<Item = (K, &'b RefTarget)>,
) -> impl Iterator<Item = (K, (&'a RefTarget, &'b RefTarget))> {
iter_named_ref_pairs(refs1, refs2).filter(|(_, (target1, target2))| target1 != target2)
iter_named_pairs(
refs1,
refs2,
|| RefTarget::absent_ref(),
|| RefTarget::absent_ref(),
)
.filter(|(_, (target1, target2))| target1 != target2)
}
/// Iterates `refs1` and `refs2` target pairs by name.
/// Iterates local `refs1` and remote `refs2` pairs by name.
///
/// `refs1` and `refs2` must be sorted by `K`.
fn iter_named_ref_pairs<'a, 'b, K: Ord>(
pub fn iter_named_local_remote_refs<'a, 'b, K: Ord>(
refs1: impl IntoIterator<Item = (K, &'a RefTarget)>,
refs2: impl IntoIterator<Item = (K, &'b RefTarget)>,
) -> impl Iterator<Item = (K, (&'a RefTarget, &'b RefTarget))> {
itertools::merge_join_by(refs1, refs2, |(name1, _), (name2, _)| name1.cmp(name2)).map(|entry| {
match entry {
refs2: impl IntoIterator<Item = (K, &'b RemoteRef)>,
) -> impl Iterator<Item = (K, (&'a RefTarget, &'b RemoteRef))> {
iter_named_pairs(
refs1,
refs2,
|| RefTarget::absent_ref(),
|| RemoteRef::absent_ref(),
)
}
fn iter_named_pairs<K: Ord, V1, V2>(
refs1: impl IntoIterator<Item = (K, V1)>,
refs2: impl IntoIterator<Item = (K, V2)>,
absent_ref1: impl Fn() -> V1,
absent_ref2: impl Fn() -> V2,
) -> impl Iterator<Item = (K, (V1, V2))> {
itertools::merge_join_by(refs1, refs2, |(name1, _), (name2, _)| name1.cmp(name2)).map(
move |entry| match entry {
EitherOrBoth::Both((name, target1), (_, target2)) => (name, (target1, target2)),
EitherOrBoth::Left((name, target1)) => (name, (target1, RefTarget::absent_ref())),
EitherOrBoth::Right((name, target2)) => (name, (RefTarget::absent_ref(), target2)),
}
})
EitherOrBoth::Left((name, target1)) => (name, (target1, absent_ref2())),
EitherOrBoth::Right((name, target2)) => (name, (absent_ref1(), target2)),
},
)
}
pub fn merge_ref_targets(

View file

@ -17,16 +17,16 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt;
use itertools::{EitherOrBoth, Itertools};
use itertools::Itertools;
use crate::backend::CommitId;
use crate::index::Index;
use crate::op_store;
use crate::op_store::{
BranchTarget, RefTarget, RefTargetOptionExt as _, RemoteRef, RemoteRefState, WorkspaceId,
};
use crate::refs::{merge_ref_targets, TrackingRefPair};
use crate::str_util::StringPattern;
use crate::{op_store, refs};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
pub enum RefName {
@ -302,29 +302,14 @@ impl View {
&'a self,
remote_name: &str,
) -> impl Iterator<Item = (&'a str, TrackingRefPair<'a>)> + 'a {
itertools::merge_join_by(
self.local_branches(),
self.remote_branches(remote_name),
|(name1, _), (name2, _)| name1.cmp(name2),
)
.map(|entry| match entry {
EitherOrBoth::Both((name, local_target), (_, remote_ref)) => {
(name, (local_target, remote_ref))
}
EitherOrBoth::Left((name, local_target)) => {
(name, (local_target, RemoteRef::absent_ref()))
}
EitherOrBoth::Right((name, remote_ref)) => {
(name, (RefTarget::absent_ref(), remote_ref))
}
})
.map(|(name, (local_target, remote_ref))| {
let targets = TrackingRefPair {
local_target,
remote_ref,
};
(name, targets)
})
refs::iter_named_local_remote_refs(self.local_branches(), self.remote_branches(remote_name))
.map(|(name, (local_target, remote_ref))| {
let targets = TrackingRefPair {
local_target,
remote_ref,
};
(name, targets)
})
}
pub fn remove_remote(&mut self, remote_name: &str) {