mirror of
https://github.com/martinvonz/jj.git
synced 2024-11-11 13:46:02 +03:00
index: implement Index for CompositeIndex
We can't get rid of the other "impl Index"es because .as_composite() must return a real reference type. Maybe we could turn CompositeIndex into an owned wrapper, but I don't know if that would be worth the effort.
This commit is contained in:
parent
5989bdf781
commit
cf5cb380bb
@ -896,20 +896,6 @@ impl<'a> CompositeIndex<'a> {
|
||||
.find_map(|segment| segment.segment_commit_id_to_pos(commit_id))
|
||||
}
|
||||
|
||||
/// Suppose the given `commit_id` exists, returns the minimum prefix length
|
||||
/// to disambiguate it. The length to be returned is a number of hexadecimal
|
||||
/// digits.
|
||||
///
|
||||
/// If the given `commit_id` doesn't exist, this will return the prefix
|
||||
/// length that never matches with any commit ids.
|
||||
pub fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize {
|
||||
let (prev_id, next_id) = self.resolve_neighbor_commit_ids(commit_id);
|
||||
itertools::chain(prev_id, next_id)
|
||||
.map(|id| backend::common_hex_len(commit_id.as_bytes(), id.as_bytes()) + 1)
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Suppose the given `commit_id` exists, returns the previous and next
|
||||
/// commit ids in lexicographical order.
|
||||
fn resolve_neighbor_commit_ids(
|
||||
@ -936,33 +922,11 @@ impl<'a> CompositeIndex<'a> {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution<CommitId> {
|
||||
self.ancestor_index_segments()
|
||||
.fold(PrefixResolution::NoMatch, |acc_match, segment| {
|
||||
if acc_match == PrefixResolution::AmbiguousMatch {
|
||||
acc_match // avoid checking the parent file(s)
|
||||
} else {
|
||||
let local_match = segment.segment_resolve_prefix(prefix);
|
||||
acc_match.plus(&local_match)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn entry_by_id(&self, commit_id: &CommitId) -> Option<IndexEntry<'a>> {
|
||||
self.commit_id_to_pos(commit_id)
|
||||
.map(|pos| self.entry_by_pos(pos))
|
||||
}
|
||||
|
||||
pub fn has_id(&self, commit_id: &CommitId) -> bool {
|
||||
self.commit_id_to_pos(commit_id).is_some()
|
||||
}
|
||||
|
||||
pub fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool {
|
||||
let ancestor_pos = self.commit_id_to_pos(ancestor_id).unwrap();
|
||||
let descendant_pos = self.commit_id_to_pos(descendant_id).unwrap();
|
||||
self.is_ancestor_pos(ancestor_pos, descendant_pos)
|
||||
}
|
||||
|
||||
fn is_ancestor_pos(&self, ancestor_pos: IndexPosition, descendant_pos: IndexPosition) -> bool {
|
||||
let ancestor_generation = self.entry_by_pos(ancestor_pos).generation_number();
|
||||
let mut work = vec![descendant_pos];
|
||||
@ -983,21 +947,6 @@ impl<'a> CompositeIndex<'a> {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec<CommitId> {
|
||||
let pos1 = set1
|
||||
.iter()
|
||||
.map(|id| self.commit_id_to_pos(id).unwrap())
|
||||
.collect_vec();
|
||||
let pos2 = set2
|
||||
.iter()
|
||||
.map(|id| self.commit_id_to_pos(id).unwrap())
|
||||
.collect_vec();
|
||||
self.common_ancestors_pos(&pos1, &pos2)
|
||||
.iter()
|
||||
.map(|pos| self.entry_by_pos(*pos).commit_id())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn common_ancestors_pos(
|
||||
&self,
|
||||
set1: &[IndexPosition],
|
||||
@ -1056,20 +1005,6 @@ impl<'a> CompositeIndex<'a> {
|
||||
rev_walk
|
||||
}
|
||||
|
||||
pub(crate) fn heads(
|
||||
&self,
|
||||
candidate_ids: &mut dyn Iterator<Item = &CommitId>,
|
||||
) -> Vec<CommitId> {
|
||||
let candidate_positions: BTreeSet<_> = candidate_ids
|
||||
.map(|id| self.commit_id_to_pos(id).unwrap())
|
||||
.collect();
|
||||
|
||||
self.heads_pos(candidate_positions)
|
||||
.iter()
|
||||
.map(|pos| self.entry_by_pos(*pos).commit_id())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn heads_pos(
|
||||
&self,
|
||||
mut candidate_positions: BTreeSet<IndexPosition>,
|
||||
@ -1105,13 +1040,86 @@ impl<'a> CompositeIndex<'a> {
|
||||
}
|
||||
candidate_positions
|
||||
}
|
||||
}
|
||||
|
||||
impl Index for CompositeIndex<'_> {
|
||||
/// Suppose the given `commit_id` exists, returns the minimum prefix length
|
||||
/// to disambiguate it. The length to be returned is a number of hexadecimal
|
||||
/// digits.
|
||||
///
|
||||
/// If the given `commit_id` doesn't exist, this will return the prefix
|
||||
/// length that never matches with any commit ids.
|
||||
fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize {
|
||||
let (prev_id, next_id) = self.resolve_neighbor_commit_ids(commit_id);
|
||||
itertools::chain(prev_id, next_id)
|
||||
.map(|id| backend::common_hex_len(commit_id.as_bytes(), id.as_bytes()) + 1)
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution<CommitId> {
|
||||
self.ancestor_index_segments()
|
||||
.fold(PrefixResolution::NoMatch, |acc_match, segment| {
|
||||
if acc_match == PrefixResolution::AmbiguousMatch {
|
||||
acc_match // avoid checking the parent file(s)
|
||||
} else {
|
||||
let local_match = segment.segment_resolve_prefix(prefix);
|
||||
acc_match.plus(&local_match)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn has_id(&self, commit_id: &CommitId) -> bool {
|
||||
self.commit_id_to_pos(commit_id).is_some()
|
||||
}
|
||||
|
||||
fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool {
|
||||
let ancestor_pos = self.commit_id_to_pos(ancestor_id).unwrap();
|
||||
let descendant_pos = self.commit_id_to_pos(descendant_id).unwrap();
|
||||
self.is_ancestor_pos(ancestor_pos, descendant_pos)
|
||||
}
|
||||
|
||||
fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec<CommitId> {
|
||||
let pos1 = set1
|
||||
.iter()
|
||||
.map(|id| self.commit_id_to_pos(id).unwrap())
|
||||
.collect_vec();
|
||||
let pos2 = set2
|
||||
.iter()
|
||||
.map(|id| self.commit_id_to_pos(id).unwrap())
|
||||
.collect_vec();
|
||||
self.common_ancestors_pos(&pos1, &pos2)
|
||||
.iter()
|
||||
.map(|pos| self.entry_by_pos(*pos).commit_id())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn heads(&self, candidate_ids: &mut dyn Iterator<Item = &CommitId>) -> Vec<CommitId> {
|
||||
let candidate_positions: BTreeSet<_> = candidate_ids
|
||||
.map(|id| self.commit_id_to_pos(id).unwrap())
|
||||
.collect();
|
||||
|
||||
self.heads_pos(candidate_positions)
|
||||
.iter()
|
||||
.map(|pos| self.entry_by_pos(*pos).commit_id())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Parents before children
|
||||
pub fn topo_order(&self, input: &mut dyn Iterator<Item = &CommitId>) -> Vec<CommitId> {
|
||||
fn topo_order(&self, input: &mut dyn Iterator<Item = &CommitId>) -> Vec<CommitId> {
|
||||
let mut ids = input.cloned().collect_vec();
|
||||
ids.sort_by_cached_key(|id| self.commit_id_to_pos(id).unwrap());
|
||||
ids
|
||||
}
|
||||
|
||||
fn evaluate_revset<'index>(
|
||||
&'index self,
|
||||
expression: &ResolvedExpression,
|
||||
store: &Arc<Store>,
|
||||
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetEvaluationError> {
|
||||
let revset_impl = default_revset_engine::evaluate(expression, store, self, *self)?;
|
||||
Ok(Box::new(revset_impl))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IndexLevelStats {
|
||||
|
@ -18,6 +18,7 @@ use jujutsu_lib::backend::CommitId;
|
||||
use jujutsu_lib::commit::Commit;
|
||||
use jujutsu_lib::commit_builder::CommitBuilder;
|
||||
use jujutsu_lib::default_index_store::{CompositeIndex, MutableIndexImpl, ReadonlyIndexWrapper};
|
||||
use jujutsu_lib::index::Index as _;
|
||||
use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, Repo};
|
||||
use jujutsu_lib::settings::UserSettings;
|
||||
use test_case::test_case;
|
||||
|
Loading…
Reference in New Issue
Block a user