mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-27 06:27:43 +00:00
index: make CompositeIndex non-public and add new IndexRef enum instead
We're getting close to finally having a `RepoRef::index()` method.
This commit is contained in:
parent
face4d637f
commit
f05a12d301
2 changed files with 143 additions and 65 deletions
138
lib/src/index.rs
138
lib/src/index.rs
|
@ -36,6 +36,92 @@ use crate::store_wrapper::StoreWrapper;
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::Bound;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum IndexRef<'a> {
|
||||
Readonly(Arc<ReadonlyIndex>),
|
||||
Mutable(&'a MutableIndex),
|
||||
}
|
||||
|
||||
impl From<Arc<ReadonlyIndex>> for IndexRef<'_> {
|
||||
fn from(index: Arc<ReadonlyIndex>) -> Self {
|
||||
IndexRef::Readonly(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a MutableIndex> for IndexRef<'a> {
|
||||
fn from(index: &'a MutableIndex) -> Self {
|
||||
IndexRef::Mutable(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IndexRef<'a> {
|
||||
pub fn num_commits(&self) -> u32 {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.num_commits(),
|
||||
IndexRef::Mutable(index) => index.num_commits(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stats(&self) -> IndexStats {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.stats(),
|
||||
IndexRef::Mutable(index) => index.stats(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<u32> {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.commit_id_to_pos(commit_id),
|
||||
IndexRef::Mutable(index) => index.commit_id_to_pos(commit_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.resolve_prefix(prefix),
|
||||
IndexRef::Mutable(index) => index.resolve_prefix(prefix),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entry_by_id(&self, commit_id: &CommitId) -> Option<IndexEntry> {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.entry_by_id(commit_id),
|
||||
IndexRef::Mutable(index) => index.entry_by_id(commit_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_id(&self, commit_id: &CommitId) -> bool {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.has_id(commit_id),
|
||||
IndexRef::Mutable(index) => index.has_id(commit_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.is_ancestor(ancestor_id, descendant_id),
|
||||
IndexRef::Mutable(index) => index.is_ancestor(ancestor_id, descendant_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.walk_revs(wanted, unwanted),
|
||||
IndexRef::Mutable(index) => index.walk_revs(wanted, unwanted),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn heads<'candidates>(
|
||||
&self,
|
||||
candidates: impl IntoIterator<Item = &'candidates CommitId>,
|
||||
) -> Vec<CommitId> {
|
||||
match self {
|
||||
IndexRef::Readonly(index) => index.heads(candidates),
|
||||
IndexRef::Mutable(index) => index.heads(candidates),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CommitGraphEntry<'a> {
|
||||
data: &'a [u8],
|
||||
hash_length: usize,
|
||||
|
@ -273,7 +359,7 @@ impl MutableIndex {
|
|||
}
|
||||
}
|
||||
|
||||
fn incremental(parent_file: Arc<ReadonlyIndex>) -> Self {
|
||||
pub fn incremental(parent_file: Arc<ReadonlyIndex>) -> Self {
|
||||
let num_parent_commits = parent_file.num_parent_commits + parent_file.num_local_commits;
|
||||
let hash_length = parent_file.hash_length;
|
||||
Self {
|
||||
|
@ -285,8 +371,8 @@ impl MutableIndex {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_composite(&self) -> CompositeIndex {
|
||||
CompositeIndex(self)
|
||||
pub fn as_index_ref(&self) -> IndexRef {
|
||||
IndexRef::Mutable(self)
|
||||
}
|
||||
|
||||
fn add_commit(&mut self, commit: &Commit) {
|
||||
|
@ -437,10 +523,8 @@ trait IndexSegment {
|
|||
fn segment_entry_by_pos(&self, pos: u32, local_pos: u32) -> IndexEntry;
|
||||
}
|
||||
|
||||
// TODO: This is a weird name for a public type in this module. The callers
|
||||
// shouldn't need to know that it's composite. Rename.
|
||||
#[derive(Clone)]
|
||||
pub struct CompositeIndex<'a>(&'a dyn IndexSegment);
|
||||
struct CompositeIndex<'a>(&'a dyn IndexSegment);
|
||||
|
||||
impl<'a> CompositeIndex<'a> {
|
||||
pub fn num_commits(&self) -> u32 {
|
||||
|
@ -497,7 +581,7 @@ impl<'a> CompositeIndex<'a> {
|
|||
// The parent ReadonlyIndex outlives the child
|
||||
let parent_file: &'a ReadonlyIndex = unsafe { std::mem::transmute(parent_file) };
|
||||
|
||||
parent_file.as_composite().entry_by_pos(pos)
|
||||
CompositeIndex(parent_file).entry_by_pos(pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,7 +591,7 @@ impl<'a> CompositeIndex<'a> {
|
|||
self.0
|
||||
.segment_parent_file()
|
||||
.as_ref()
|
||||
.and_then(|file| file.as_composite().commit_id_to_pos(commit_id))
|
||||
.and_then(|file| IndexRef::Readonly(file.clone()).commit_id_to_pos(commit_id))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1106,10 +1190,6 @@ impl ReadonlyIndex {
|
|||
Ok(index_file)
|
||||
}
|
||||
|
||||
pub fn as_composite(&self) -> CompositeIndex {
|
||||
CompositeIndex(self)
|
||||
}
|
||||
|
||||
pub fn num_commits(&self) -> u32 {
|
||||
CompositeIndex(self).num_commits()
|
||||
}
|
||||
|
@ -1227,13 +1307,14 @@ mod tests {
|
|||
fn index_empty(use_file: bool) {
|
||||
let index = MutableIndex::full(3);
|
||||
let temp_dir;
|
||||
let source: Box<dyn IndexSegment> = if use_file {
|
||||
let index = if use_file {
|
||||
temp_dir = tempfile::tempdir().unwrap();
|
||||
Box::new(ReadonlyIndex::from_mutable(temp_dir.path(), index).unwrap())
|
||||
IndexRef::Readonly(Arc::new(
|
||||
ReadonlyIndex::from_mutable(temp_dir.path(), index).unwrap(),
|
||||
))
|
||||
} else {
|
||||
Box::new(index)
|
||||
IndexRef::Mutable(&index)
|
||||
};
|
||||
let index = CompositeIndex(source.as_ref());
|
||||
|
||||
// Stats are as expected
|
||||
let stats = index.stats();
|
||||
|
@ -1255,13 +1336,14 @@ mod tests {
|
|||
let id_0 = CommitId::from_hex("000000");
|
||||
index.add_commit_data(id_0.clone(), vec![]);
|
||||
let temp_dir;
|
||||
let source: Box<dyn IndexSegment> = if use_file {
|
||||
let index = if use_file {
|
||||
temp_dir = tempfile::tempdir().unwrap();
|
||||
Box::new(ReadonlyIndex::from_mutable(temp_dir.path(), index).unwrap())
|
||||
IndexRef::Readonly(Arc::new(
|
||||
ReadonlyIndex::from_mutable(temp_dir.path(), index).unwrap(),
|
||||
))
|
||||
} else {
|
||||
Box::new(index)
|
||||
IndexRef::Mutable(&index)
|
||||
};
|
||||
let index = CompositeIndex(source.as_ref());
|
||||
|
||||
// Stats are as expected
|
||||
let stats = index.stats();
|
||||
|
@ -1281,10 +1363,6 @@ mod tests {
|
|||
assert_eq!(entry.generation_number(), 0);
|
||||
assert_eq!(entry.num_parents(), 0);
|
||||
assert_eq!(entry.parents_positions(), Vec::<u32>::new());
|
||||
// Can get same entry by position
|
||||
let entry = index.entry_by_pos(0);
|
||||
assert_eq!(entry.pos, 0);
|
||||
assert_eq!(entry.commit_id(), id_0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1331,12 +1409,13 @@ mod tests {
|
|||
index.add_commit_data(id_3.clone(), vec![id_2.clone()]);
|
||||
index.add_commit_data(id_4.clone(), vec![id_1.clone()]);
|
||||
index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()]);
|
||||
let source: Box<dyn IndexSegment> = if use_file {
|
||||
Box::new(ReadonlyIndex::from_mutable(temp_dir.path(), index).unwrap())
|
||||
let index = if use_file {
|
||||
IndexRef::Readonly(Arc::new(
|
||||
ReadonlyIndex::from_mutable(temp_dir.path(), index).unwrap(),
|
||||
))
|
||||
} else {
|
||||
Box::new(index)
|
||||
IndexRef::Mutable(&index)
|
||||
};
|
||||
let index = CompositeIndex(source.as_ref());
|
||||
|
||||
// Stats are as expected
|
||||
let stats = index.stats();
|
||||
|
@ -1435,7 +1514,6 @@ mod tests {
|
|||
index.add_commit_data(id_3.clone(), vec![id_2.clone()]);
|
||||
index.add_commit_data(id_4.clone(), vec![id_1.clone()]);
|
||||
index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()]);
|
||||
let index = CompositeIndex(&index);
|
||||
|
||||
assert!(index.is_ancestor(&id_0, &id_0));
|
||||
assert!(index.is_ancestor(&id_0, &id_1));
|
||||
|
@ -1472,7 +1550,6 @@ mod tests {
|
|||
index.add_commit_data(id_3.clone(), vec![id_2.clone()]);
|
||||
index.add_commit_data(id_4.clone(), vec![id_1.clone()]);
|
||||
index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()]);
|
||||
let index = CompositeIndex(&index);
|
||||
|
||||
// No wanted commits
|
||||
let revs: Vec<CommitId> = index.walk_revs(&[], &[]).collect();
|
||||
|
@ -1540,7 +1617,6 @@ mod tests {
|
|||
index.add_commit_data(id_3.clone(), vec![id_2.clone()]);
|
||||
index.add_commit_data(id_4.clone(), vec![id_1.clone()]);
|
||||
index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()]);
|
||||
let index = CompositeIndex(&index);
|
||||
|
||||
// Empty input
|
||||
assert!(index.heads(&[]).is_empty());
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
use jujube_lib::commit::Commit;
|
||||
use jujube_lib::commit_builder::CommitBuilder;
|
||||
use jujube_lib::index::CompositeIndex;
|
||||
use jujube_lib::index::IndexRef;
|
||||
use jujube_lib::repo::ReadonlyRepo;
|
||||
use jujube_lib::settings::UserSettings;
|
||||
use jujube_lib::store::CommitId;
|
||||
|
@ -28,8 +28,12 @@ fn child_commit(settings: &UserSettings, repo: &ReadonlyRepo, commit: &Commit) -
|
|||
}
|
||||
|
||||
// Helper just to reduce line wrapping
|
||||
fn generation_number(index: &CompositeIndex, commit_id: &CommitId) -> u32 {
|
||||
index.entry_by_id(commit_id).unwrap().generation_number()
|
||||
fn generation_number<'a>(index: impl Into<IndexRef<'a>>, commit_id: &CommitId) -> u32 {
|
||||
index
|
||||
.into()
|
||||
.entry_by_id(commit_id)
|
||||
.unwrap()
|
||||
.generation_number()
|
||||
}
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
|
@ -39,14 +43,19 @@ fn test_index_commits_empty_repo(use_git: bool) {
|
|||
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
||||
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit
|
||||
assert_eq!(index.num_commits(), 2);
|
||||
|
||||
// Check the generation numbers of the root and the working copy
|
||||
assert_eq!(generation_number(&index, repo.store().root_commit_id()), 0);
|
||||
assert_eq!(
|
||||
generation_number(&index, &repo.working_copy_locked().current_commit_id()),
|
||||
generation_number(index.clone(), repo.store().root_commit_id()),
|
||||
0
|
||||
);
|
||||
assert_eq!(
|
||||
generation_number(
|
||||
index.clone(),
|
||||
&repo.working_copy_locked().current_commit_id()
|
||||
),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
@ -88,7 +97,6 @@ fn test_index_commits_standard_cases(use_git: bool) {
|
|||
Arc::get_mut(&mut repo).unwrap().reload();
|
||||
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit, plus
|
||||
// 8 more
|
||||
assert_eq!(index.num_commits(), 2 + 8);
|
||||
|
@ -98,16 +106,16 @@ fn test_index_commits_standard_cases(use_git: bool) {
|
|||
assert_eq!(stats.num_merges, 1);
|
||||
assert_eq!(stats.max_generation_number, 6);
|
||||
|
||||
assert_eq!(generation_number(&index, root_commit.id()), 0);
|
||||
assert_eq!(generation_number(&index, wc_commit.id()), 1);
|
||||
assert_eq!(generation_number(&index, commit_a.id()), 1);
|
||||
assert_eq!(generation_number(&index, commit_b.id()), 2);
|
||||
assert_eq!(generation_number(&index, commit_c.id()), 2);
|
||||
assert_eq!(generation_number(&index, commit_d.id()), 3);
|
||||
assert_eq!(generation_number(&index, commit_e.id()), 4);
|
||||
assert_eq!(generation_number(&index, commit_f.id()), 5);
|
||||
assert_eq!(generation_number(&index, commit_g.id()), 6);
|
||||
assert_eq!(generation_number(&index, commit_h.id()), 5);
|
||||
assert_eq!(generation_number(index.clone(), root_commit.id()), 0);
|
||||
assert_eq!(generation_number(index.clone(), wc_commit.id()), 1);
|
||||
assert_eq!(generation_number(index.clone(), commit_a.id()), 1);
|
||||
assert_eq!(generation_number(index.clone(), commit_b.id()), 2);
|
||||
assert_eq!(generation_number(index.clone(), commit_c.id()), 2);
|
||||
assert_eq!(generation_number(index.clone(), commit_d.id()), 3);
|
||||
assert_eq!(generation_number(index.clone(), commit_e.id()), 4);
|
||||
assert_eq!(generation_number(index.clone(), commit_f.id()), 5);
|
||||
assert_eq!(generation_number(index.clone(), commit_g.id()), 6);
|
||||
assert_eq!(generation_number(index.clone(), commit_h.id()), 5);
|
||||
|
||||
assert!(index.is_ancestor(root_commit.id(), commit_a.id()));
|
||||
assert!(!index.is_ancestor(commit_a.id(), root_commit.id()));
|
||||
|
@ -161,7 +169,6 @@ fn test_index_commits_criss_cross(use_git: bool) {
|
|||
Arc::get_mut(&mut repo).unwrap().reload();
|
||||
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should the root commit and the working copy commit, plus 2 for each
|
||||
// generation
|
||||
assert_eq!(index.num_commits(), 2 + 2 * (num_generations as u32));
|
||||
|
@ -175,11 +182,11 @@ fn test_index_commits_criss_cross(use_git: bool) {
|
|||
// Check generation numbers
|
||||
for gen in 0..num_generations {
|
||||
assert_eq!(
|
||||
generation_number(&index, left_commits[gen].id()),
|
||||
generation_number(index.clone(), left_commits[gen].id()),
|
||||
(gen as u32) + 1
|
||||
);
|
||||
assert_eq!(
|
||||
generation_number(&index, right_commits[gen].id()),
|
||||
generation_number(index.clone(), right_commits[gen].id()),
|
||||
(gen as u32) + 1
|
||||
);
|
||||
}
|
||||
|
@ -276,7 +283,6 @@ fn test_index_commits_previous_operations(use_git: bool) {
|
|||
|
||||
let repo = ReadonlyRepo::load(&settings, repo.working_copy_path().clone()).unwrap();
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit, plus
|
||||
// 3 more
|
||||
assert_eq!(index.num_commits(), 2 + 3);
|
||||
|
@ -286,9 +292,9 @@ fn test_index_commits_previous_operations(use_git: bool) {
|
|||
assert_eq!(stats.num_merges, 0);
|
||||
assert_eq!(stats.max_generation_number, 3);
|
||||
|
||||
assert_eq!(generation_number(&index, commit_a.id()), 1);
|
||||
assert_eq!(generation_number(&index, commit_b.id()), 2);
|
||||
assert_eq!(generation_number(&index, commit_c.id()), 3);
|
||||
assert_eq!(generation_number(index.clone(), commit_a.id()), 1);
|
||||
assert_eq!(generation_number(index.clone(), commit_b.id()), 2);
|
||||
assert_eq!(generation_number(index.clone(), commit_c.id()), 3);
|
||||
}
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
|
@ -312,7 +318,6 @@ fn test_index_commits_incremental(use_git: bool) {
|
|||
Arc::get_mut(&mut repo).unwrap().reload();
|
||||
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit, plus
|
||||
// 1 more
|
||||
assert_eq!(index.num_commits(), 2 + 1);
|
||||
|
@ -324,7 +329,6 @@ fn test_index_commits_incremental(use_git: bool) {
|
|||
|
||||
let repo = ReadonlyRepo::load(&settings, repo.working_copy_path().clone()).unwrap();
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit, plus
|
||||
// 3 more
|
||||
assert_eq!(index.num_commits(), 2 + 3);
|
||||
|
@ -338,10 +342,10 @@ fn test_index_commits_incremental(use_git: bool) {
|
|||
assert_eq!(stats.levels[1].num_commits, 3);
|
||||
assert_ne!(stats.levels[1].name, stats.levels[0].name);
|
||||
|
||||
assert_eq!(generation_number(&index, root_commit.id()), 0);
|
||||
assert_eq!(generation_number(&index, commit_a.id()), 1);
|
||||
assert_eq!(generation_number(&index, commit_b.id()), 2);
|
||||
assert_eq!(generation_number(&index, commit_c.id()), 3);
|
||||
assert_eq!(generation_number(index.clone(), root_commit.id()), 0);
|
||||
assert_eq!(generation_number(index.clone(), commit_a.id()), 1);
|
||||
assert_eq!(generation_number(index.clone(), commit_b.id()), 2);
|
||||
assert_eq!(generation_number(index.clone(), commit_c.id()), 3);
|
||||
}
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
|
@ -363,7 +367,6 @@ fn test_index_commits_incremental_empty_transaction(use_git: bool) {
|
|||
Arc::get_mut(&mut repo).unwrap().reload();
|
||||
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit, plus
|
||||
// 1 more
|
||||
assert_eq!(index.num_commits(), 2 + 1);
|
||||
|
@ -372,7 +375,6 @@ fn test_index_commits_incremental_empty_transaction(use_git: bool) {
|
|||
|
||||
let repo = ReadonlyRepo::load(&settings, repo.working_copy_path().clone()).unwrap();
|
||||
let index = repo.index();
|
||||
let index = index.as_composite();
|
||||
// There should be the root commit and the working copy commit, plus
|
||||
// 1 more
|
||||
assert_eq!(index.num_commits(), 2 + 1);
|
||||
|
@ -385,6 +387,6 @@ fn test_index_commits_incremental_empty_transaction(use_git: bool) {
|
|||
assert_eq!(stats.levels[0].num_commits, 0);
|
||||
assert_eq!(stats.levels[1].num_commits, 3);
|
||||
|
||||
assert_eq!(generation_number(&index, root_commit.id()), 0);
|
||||
assert_eq!(generation_number(&index, commit_a.id()), 1);
|
||||
assert_eq!(generation_number(index.clone(), root_commit.id()), 0);
|
||||
assert_eq!(generation_number(index.clone(), commit_a.id()), 1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue