diff --git a/lib/src/git.rs b/lib/src/git.rs index 13943d30f..19f400329 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -23,6 +23,7 @@ use thiserror::Error; use crate::backend::{CommitId, ObjectId}; use crate::commit::Commit; use crate::git_backend::NO_GC_REF_NAMESPACE; +use crate::index::Index; use crate::op_store::RefTarget; use crate::repo::MutableRepo; use crate::settings::GitSettings; diff --git a/lib/src/index.rs b/lib/src/index.rs index 5ec307383..38bc487b2 100644 --- a/lib/src/index.rs +++ b/lib/src/index.rs @@ -45,6 +45,34 @@ impl IndexPosition { pub const MAX: Self = IndexPosition(u32::MAX); } +pub trait Index { + fn num_commits(&self) -> u32; + + fn stats(&self) -> IndexStats; + + fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option; + + fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize; + + fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution; + + fn entry_by_id(&self, commit_id: &CommitId) -> Option; + + fn entry_by_pos(&self, pos: IndexPosition) -> IndexEntry; + + fn has_id(&self, commit_id: &CommitId) -> bool; + + fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool; + + fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec; + + fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk; + + fn heads(&self, candidates: &mut dyn Iterator) -> Vec; + + fn topo_order(&self, input: &mut dyn Iterator) -> Vec; +} + #[derive(Clone, Copy)] pub enum IndexRef<'a> { Readonly(&'a ReadonlyIndex), @@ -629,56 +657,58 @@ impl MutableIndex { IndexLoadError::IoError(err) => err, }) } +} - pub fn num_commits(&self) -> u32 { +impl Index for MutableIndex { + fn num_commits(&self) -> u32 { CompositeIndex(self).num_commits() } - pub fn stats(&self) -> IndexStats { + fn stats(&self) -> IndexStats { CompositeIndex(self).stats() } - pub fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option { + fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option { CompositeIndex(self).commit_id_to_pos(commit_id) } - pub fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize { + fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize { CompositeIndex(self).shortest_unique_commit_id_prefix_len(commit_id) } - pub fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution { + fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution { CompositeIndex(self).resolve_prefix(prefix) } - pub fn entry_by_id(&self, commit_id: &CommitId) -> Option { + fn entry_by_id(&self, commit_id: &CommitId) -> Option { CompositeIndex(self).entry_by_id(commit_id) } - pub fn entry_by_pos(&self, pos: IndexPosition) -> IndexEntry { + fn entry_by_pos(&self, pos: IndexPosition) -> IndexEntry { CompositeIndex(self).entry_by_pos(pos) } - pub fn has_id(&self, commit_id: &CommitId) -> bool { + fn has_id(&self, commit_id: &CommitId) -> bool { CompositeIndex(self).has_id(commit_id) } - pub fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool { + fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool { CompositeIndex(self).is_ancestor(ancestor_id, descendant_id) } - pub fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec { + fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec { CompositeIndex(self).common_ancestors(set1, set2) } - pub fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk { + fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk { CompositeIndex(self).walk_revs(wanted, unwanted) } - pub fn heads(&self, candidates: &mut dyn Iterator) -> Vec { + fn heads(&self, candidates: &mut dyn Iterator) -> Vec { CompositeIndex(self).heads(candidates) } - pub fn topo_order(&self, input: &mut dyn Iterator) -> Vec { + fn topo_order(&self, input: &mut dyn Iterator) -> Vec { CompositeIndex(self).topo_order(input) } } @@ -1598,62 +1628,10 @@ impl ReadonlyIndex { IndexRef::Readonly(self) } - pub fn num_commits(&self) -> u32 { - CompositeIndex(self).num_commits() - } - pub fn name(&self) -> &str { &self.name } - pub fn stats(&self) -> IndexStats { - CompositeIndex(self).stats() - } - - pub fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option { - CompositeIndex(self).commit_id_to_pos(commit_id) - } - - pub fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize { - CompositeIndex(self).shortest_unique_commit_id_prefix_len(commit_id) - } - - pub fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution { - CompositeIndex(self).resolve_prefix(prefix) - } - - pub fn entry_by_id(&self, commit_id: &CommitId) -> Option { - CompositeIndex(self).entry_by_id(commit_id) - } - - pub fn entry_by_pos(&self, pos: IndexPosition) -> IndexEntry { - CompositeIndex(self).entry_by_pos(pos) - } - - pub fn has_id(&self, commit_id: &CommitId) -> bool { - CompositeIndex(self).has_id(commit_id) - } - - pub fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool { - CompositeIndex(self).is_ancestor(ancestor_id, descendant_id) - } - - pub fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec { - CompositeIndex(self).common_ancestors(set1, set2) - } - - pub fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk { - CompositeIndex(self).walk_revs(wanted, unwanted) - } - - pub fn heads(&self, candidates: &mut dyn Iterator) -> Vec { - CompositeIndex(self).heads(candidates) - } - - pub fn topo_order(&self, input: &mut dyn Iterator) -> Vec { - CompositeIndex(self).topo_order(input) - } - fn graph_entry(&self, local_pos: u32) -> CommitGraphEntry { let offset = (local_pos as usize) * self.commit_graph_entry_size; CommitGraphEntry { @@ -1704,11 +1682,66 @@ impl ReadonlyIndex { } } +impl Index for ReadonlyIndex { + fn num_commits(&self) -> u32 { + CompositeIndex(self).num_commits() + } + + fn stats(&self) -> IndexStats { + CompositeIndex(self).stats() + } + + fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option { + CompositeIndex(self).commit_id_to_pos(commit_id) + } + + fn shortest_unique_commit_id_prefix_len(&self, commit_id: &CommitId) -> usize { + CompositeIndex(self).shortest_unique_commit_id_prefix_len(commit_id) + } + + fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution { + CompositeIndex(self).resolve_prefix(prefix) + } + + fn entry_by_id(&self, commit_id: &CommitId) -> Option { + CompositeIndex(self).entry_by_id(commit_id) + } + + fn entry_by_pos(&self, pos: IndexPosition) -> IndexEntry { + CompositeIndex(self).entry_by_pos(pos) + } + + fn has_id(&self, commit_id: &CommitId) -> bool { + CompositeIndex(self).has_id(commit_id) + } + + fn is_ancestor(&self, ancestor_id: &CommitId, descendant_id: &CommitId) -> bool { + CompositeIndex(self).is_ancestor(ancestor_id, descendant_id) + } + + fn common_ancestors(&self, set1: &[CommitId], set2: &[CommitId]) -> Vec { + CompositeIndex(self).common_ancestors(set1, set2) + } + + fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk { + CompositeIndex(self).walk_revs(wanted, unwanted) + } + + fn heads(&self, candidates: &mut dyn Iterator) -> Vec { + CompositeIndex(self).heads(candidates) + } + + fn topo_order(&self, input: &mut dyn Iterator) -> Vec { + CompositeIndex(self).topo_order(input) + } +} + #[cfg(test)] mod tests { use test_case::test_case; use super::*; + use crate::index::Index; /// Generator of unique 16-byte ChangeId excluding root id fn change_id_generator() -> impl FnMut() -> ChangeId { @@ -1721,12 +1754,11 @@ mod tests { fn index_empty(on_disk: bool) { let temp_dir = testutils::new_temp_dir(); let index = MutableIndex::full(3, 16); - let mut _saved_index = None; - let index = if on_disk { - _saved_index = Some(index.save_in(temp_dir.path().to_owned()).unwrap()); - IndexRef::Readonly(_saved_index.as_ref().unwrap()) + let index: Box = if on_disk { + let saved_index = index.save_in(temp_dir.path().to_owned()).unwrap(); + Box::new(Arc::try_unwrap(saved_index).unwrap()) } else { - IndexRef::Mutable(&index) + Box::new(index) }; // Stats are as expected @@ -1752,12 +1784,11 @@ mod tests { let id_0 = CommitId::from_hex("000000"); let change_id0 = new_change_id(); index.add_commit_data(id_0.clone(), change_id0.clone(), &[]); - let mut _saved_index = None; - let index = if on_disk { - _saved_index = Some(index.save_in(temp_dir.path().to_owned()).unwrap()); - IndexRef::Readonly(_saved_index.as_ref().unwrap()) + let index: Box = if on_disk { + let saved_index = index.save_in(temp_dir.path().to_owned()).unwrap(); + Box::new(Arc::try_unwrap(saved_index).unwrap()) } else { - IndexRef::Mutable(&index) + Box::new(index) }; // Stats are as expected @@ -1834,12 +1865,11 @@ mod tests { index.add_commit_data(id_3.clone(), change_id3.clone(), &[id_2.clone()]); index.add_commit_data(id_4.clone(), change_id4, &[id_1.clone()]); index.add_commit_data(id_5.clone(), change_id5, &[id_4.clone(), id_2.clone()]); - let mut _saved_index = None; - let index = if on_disk { - _saved_index = Some(index.save_in(temp_dir.path().to_owned()).unwrap()); - IndexRef::Readonly(_saved_index.as_ref().unwrap()) + let index: Box = if on_disk { + let saved_index = index.save_in(temp_dir.path().to_owned()).unwrap(); + Box::new(Arc::try_unwrap(saved_index).unwrap()) } else { - IndexRef::Mutable(&index) + Box::new(index) }; // Stats are as expected @@ -1925,12 +1955,11 @@ mod tests { new_change_id(), &[id_1, id_2, id_3, id_4, id_5], ); - let mut _saved_index = None; - let index = if on_disk { - _saved_index = Some(index.save_in(temp_dir.path().to_owned()).unwrap()); - IndexRef::Readonly(_saved_index.as_ref().unwrap()) + let index: Box = if on_disk { + let saved_index = index.save_in(temp_dir.path().to_owned()).unwrap(); + Box::new(Arc::try_unwrap(saved_index).unwrap()) } else { - IndexRef::Mutable(&index) + Box::new(index) }; // Stats are as expected diff --git a/lib/src/index_store.rs b/lib/src/index_store.rs index 41ee20154..97c4b50c5 100644 --- a/lib/src/index_store.rs +++ b/lib/src/index_store.rs @@ -26,7 +26,7 @@ use crate::backend::CommitId; use crate::commit::Commit; use crate::dag_walk; use crate::file_util::persist_content_addressed_temp_file; -use crate::index::{IndexLoadError, MutableIndex, ReadonlyIndex}; +use crate::index::{Index, IndexLoadError, MutableIndex, ReadonlyIndex}; use crate::op_store::OperationId; use crate::operation::Operation; use crate::store::Store; diff --git a/lib/src/repo.rs b/lib/src/repo.rs index ff534edf1..ca81642d2 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -30,7 +30,8 @@ use crate::commit_builder::CommitBuilder; use crate::dag_walk::topo_order_reverse; use crate::git_backend::GitBackend; use crate::index::{ - HexPrefix, IndexEntry, IndexPosition, IndexRef, MutableIndex, PrefixResolution, ReadonlyIndex, + HexPrefix, Index, IndexEntry, IndexPosition, IndexRef, MutableIndex, PrefixResolution, + ReadonlyIndex, }; use crate::index_store::IndexStore; use crate::local_backend::LocalBackend; diff --git a/lib/src/revset.rs b/lib/src/revset.rs index bfcc41be3..b4cf5a6d4 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -2234,7 +2234,7 @@ fn has_diff_from_parent(repo: RepoRef<'_>, entry: &IndexEntry<'_>, matcher: &dyn mod tests { use super::*; use crate::backend::ChangeId; - use crate::index::MutableIndex; + use crate::index::{Index, MutableIndex}; /// Generator of unique 16-byte ChangeId excluding root id fn change_id_generator() -> impl FnMut() -> ChangeId { diff --git a/lib/src/rewrite.rs b/lib/src/rewrite.rs index 90a484eb3..19ee5364f 100644 --- a/lib/src/rewrite.rs +++ b/lib/src/rewrite.rs @@ -19,6 +19,7 @@ use itertools::{process_results, Itertools}; use crate::backend::{BackendError, BackendResult, CommitId, ObjectId}; use crate::commit::Commit; use crate::dag_walk; +use crate::index::Index; use crate::op_store::RefTarget; use crate::repo::{MutableRepo, RepoRef}; use crate::repo_path::RepoPath; diff --git a/lib/tests/test_index.rs b/lib/tests/test_index.rs index 8403a7d1a..8d3b5f956 100644 --- a/lib/tests/test_index.rs +++ b/lib/tests/test_index.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use jujutsu_lib::backend::CommitId; use jujutsu_lib::commit::Commit; use jujutsu_lib::commit_builder::CommitBuilder; -use jujutsu_lib::index::ReadonlyIndex; +use jujutsu_lib::index::{Index, ReadonlyIndex}; use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, StoreFactories}; use jujutsu_lib::settings::UserSettings; use test_case::test_case; diff --git a/lib/tests/test_mut_repo.rs b/lib/tests/test_mut_repo.rs index d23f955ab..c9a0acd60 100644 --- a/lib/tests/test_mut_repo.rs +++ b/lib/tests/test_mut_repo.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use jujutsu_lib::index::Index; use jujutsu_lib::op_store::{RefTarget, WorkspaceId}; use maplit::hashset; use test_case::test_case; diff --git a/lib/tests/test_revset_graph_iterator.rs b/lib/tests/test_revset_graph_iterator.rs index e706cc981..6ab11b4fe 100644 --- a/lib/tests/test_revset_graph_iterator.rs +++ b/lib/tests/test_revset_graph_iterator.rs @@ -13,6 +13,7 @@ // limitations under the License. use itertools::Itertools; +use jujutsu_lib::index::Index; use jujutsu_lib::revset::revset_for_commits; use jujutsu_lib::revset_graph_iterator::RevsetGraphEdge; use test_case::test_case; diff --git a/src/cli_util.rs b/src/cli_util.rs index 56d7f8831..1557758ab 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -33,6 +33,7 @@ use jujutsu_lib::commit::Commit; use jujutsu_lib::git::{GitExportError, GitImportError}; use jujutsu_lib::gitignore::GitIgnoreFile; use jujutsu_lib::hex_util::to_reverse_hex; +use jujutsu_lib::index::Index; use jujutsu_lib::matchers::{EverythingMatcher, Matcher, PrefixMatcher, Visit}; use jujutsu_lib::op_heads_store::{self, OpHeadResolutionError, OpHeadsStore}; use jujutsu_lib::op_store::{OpStore, OpStoreError, OperationId, RefTarget, WorkspaceId}; diff --git a/src/commands/branch.rs b/src/commands/branch.rs index af456085e..858420bd0 100644 --- a/src/commands/branch.rs +++ b/src/commands/branch.rs @@ -3,6 +3,7 @@ use std::collections::BTreeSet; use clap::builder::NonEmptyStringValueParser; use itertools::Itertools; use jujutsu_lib::backend::{CommitId, ObjectId}; +use jujutsu_lib::index::Index; use jujutsu_lib::op_store::RefTarget; use jujutsu_lib::repo::RepoRef; use jujutsu_lib::view::View; diff --git a/src/commands/git.rs b/src/commands/git.rs index 1c33a1dad..056750cc7 100644 --- a/src/commands/git.rs +++ b/src/commands/git.rs @@ -10,6 +10,7 @@ use clap::{ArgGroup, Subcommand}; use itertools::Itertools; use jujutsu_lib::backend::ObjectId; use jujutsu_lib::git::{self, GitFetchError, GitRefUpdate}; +use jujutsu_lib::index::Index; use jujutsu_lib::op_store::{BranchTarget, RefTarget}; use jujutsu_lib::refs::{classify_branch_push_action, BranchPushAction, BranchPushUpdate}; use jujutsu_lib::repo::RepoRef; diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e602c9c8b..52aecbba3 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -29,7 +29,7 @@ use itertools::Itertools; use jujutsu_lib::backend::{CommitId, ObjectId, TreeValue}; use jujutsu_lib::commit::Commit; use jujutsu_lib::dag_walk::topo_order_reverse; -use jujutsu_lib::index::IndexEntry; +use jujutsu_lib::index::{Index, IndexEntry}; use jujutsu_lib::matchers::EverythingMatcher; use jujutsu_lib::op_store::{RefTarget, WorkspaceId}; use jujutsu_lib::repo::ReadonlyRepo;