diff --git a/lib/src/evolution.rs b/lib/src/evolution.rs index f285acee0..17fc46af1 100644 --- a/lib/src/evolution.rs +++ b/lib/src/evolution.rs @@ -26,7 +26,7 @@ use crate::store::{ChangeId, CommitId}; use crate::store_wrapper::StoreWrapper; use crate::transaction::Transaction; use crate::trees::merge_trees; -use crate::view::View; +use crate::view::ViewRef; // TODO: Combine some maps/sets and use a struct as value instead. // TODO: Move some of this into the index? @@ -46,7 +46,7 @@ struct State { } impl State { - fn calculate(store: &StoreWrapper, view: &dyn View) -> State { + fn calculate(store: &StoreWrapper, view: ViewRef) -> State { let mut state = State::default(); let mut heads = vec![]; for commit_id in view.heads() { @@ -398,7 +398,7 @@ impl<'r> ReadonlyEvolution<'r> { if locked_state.is_none() { locked_state.replace(Arc::new(State::calculate( self.repo.store(), - self.repo.view(), + self.repo.view().as_view_ref(), ))); } locked_state.as_ref().unwrap().clone() @@ -464,7 +464,7 @@ impl MutableEvolution<'_, '_> { } pub fn invalidate(&mut self) { - self.state = State::calculate(self.repo.store(), self.repo.view()); + self.state = State::calculate(self.repo.store(), self.repo.view().as_view_ref()); } } diff --git a/lib/src/index.rs b/lib/src/index.rs index d9134af75..13fa625d6 100644 --- a/lib/src/index.rs +++ b/lib/src/index.rs @@ -33,7 +33,6 @@ use crate::operation::Operation; use crate::repo::ReadonlyRepo; use crate::store::CommitId; use crate::store_wrapper::StoreWrapper; -use crate::view::View; use std::fmt::{Debug, Formatter}; use std::ops::Bound; @@ -925,7 +924,7 @@ impl ReadonlyIndex { let op_id = OperationId(hex::decode(op_id_hex).unwrap()); ReadonlyIndex::load_at_operation(&dir, repo.store().hash_length(), &op_id).unwrap() } else { - let op = repo.view().get_operation(&op_id).unwrap(); + let op = repo.view().as_view_ref().get_operation(&op_id).unwrap(); ReadonlyIndex::index(repo.store(), &dir, &op).unwrap() }; diff --git a/lib/src/repo.rs b/lib/src/repo.rs index 5e36ec56c..e353c147e 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -32,7 +32,7 @@ use crate::store; use crate::store::{Store, StoreError}; use crate::store_wrapper::StoreWrapper; use crate::transaction::Transaction; -use crate::view::{MutableView, ReadonlyView, View}; +use crate::view::{MutableView, ReadonlyView, ViewRef}; use crate::working_copy::WorkingCopy; #[derive(Debug, Error, PartialEq, Eq)] @@ -70,14 +70,14 @@ impl<'a, 'r> RepoRef<'a, 'r> { } } - pub fn view(&self) -> &'a dyn View { + pub fn view(&self) -> ViewRef<'a> { match self { - RepoRef::Readonly(repo) => repo.view(), - RepoRef::Mutable(repo) => repo.view(), + RepoRef::Readonly(repo) => ViewRef::Readonly(repo.view()), + RepoRef::Mutable(repo) => ViewRef::Mutable(repo.view()), } } - pub fn evolution(&self) -> EvolutionRef { + pub fn evolution(&self) -> EvolutionRef<'a, 'a, 'r> { match self { RepoRef::Readonly(repo) => EvolutionRef::Readonly(repo.evolution()), RepoRef::Mutable(repo) => EvolutionRef::Mutable(repo.evolution()), @@ -394,7 +394,7 @@ impl<'r> MutableRepo<'r> { self.repo } - pub fn view(&self) -> &dyn View { + pub fn view(&self) -> &MutableView { self.view.as_ref().unwrap() } diff --git a/lib/src/view.rs b/lib/src/view.rs index 8e75e9431..fdae0b4eb 100644 --- a/lib/src/view.rs +++ b/lib/src/view.rs @@ -29,20 +29,61 @@ use crate::simple_op_store::SimpleOpStore; use crate::store::{CommitId, Timestamp}; use crate::store_wrapper::StoreWrapper; -pub trait View { - fn checkout(&self) -> &CommitId; - fn heads(&self) -> &HashSet; - fn public_heads(&self) -> &HashSet; - fn git_refs(&self) -> &BTreeMap; - fn op_store(&self) -> Arc; - fn base_op_head_id(&self) -> &OperationId; +pub enum ViewRef<'a> { + Readonly(&'a ReadonlyView), + Mutable(&'a MutableView), +} - fn get_operation(&self, id: &OperationId) -> OpStoreResult { +// TODO: Move OpStore out of View? +impl<'a> ViewRef<'a> { + pub fn checkout(&self) -> &'a CommitId { + match self { + ViewRef::Readonly(view) => view.checkout(), + ViewRef::Mutable(view) => view.checkout(), + } + } + + pub fn heads(&self) -> &'a HashSet { + match self { + ViewRef::Readonly(view) => view.heads(), + ViewRef::Mutable(view) => view.heads(), + } + } + + pub fn public_heads(&self) -> &'a HashSet { + match self { + ViewRef::Readonly(view) => view.public_heads(), + ViewRef::Mutable(view) => view.public_heads(), + } + } + + pub fn git_refs(&self) -> &'a BTreeMap { + match self { + ViewRef::Readonly(view) => view.git_refs(), + ViewRef::Mutable(view) => view.git_refs(), + } + } + + pub fn op_store(&self) -> Arc { + match self { + ViewRef::Readonly(view) => view.op_store(), + ViewRef::Mutable(view) => view.op_store(), + } + } + + pub fn base_op_head_id(&self) -> &'a OperationId { + match self { + ViewRef::Readonly(view) => view.base_op_head_id(), + ViewRef::Mutable(view) => view.base_op_head_id(), + } + } + + pub fn get_operation(&self, id: &OperationId) -> OpStoreResult { let data = self.op_store().read_operation(id)?; Ok(Operation::new(self.op_store().clone(), id.clone(), data)) } - fn base_op_head(&self) -> Operation { + pub fn base_op_head(&self) -> Operation { self.get_operation(self.base_op_head_id()).unwrap() } } @@ -318,32 +359,6 @@ fn merge_op_heads( Ok((merge_operation_id, merge_operation, merged_view)) } -impl View for ReadonlyView { - fn checkout(&self) -> &CommitId { - &self.data.checkout - } - - fn heads(&self) -> &HashSet { - &self.data.head_ids - } - - fn public_heads(&self) -> &HashSet { - &self.data.public_head_ids - } - - fn git_refs(&self) -> &BTreeMap { - &self.data.git_refs - } - - fn op_store(&self) -> Arc { - self.op_store.clone() - } - - fn base_op_head_id(&self) -> &OperationId { - &self.op_id - } -} - impl ReadonlyView { pub fn init(store: Arc, path: PathBuf, checkout: CommitId) -> Self { std::fs::create_dir(path.join("op_store")).unwrap(); @@ -411,35 +426,65 @@ impl ReadonlyView { data: self.data.clone(), } } -} -impl View for MutableView { - fn checkout(&self) -> &CommitId { + pub fn as_view_ref(&self) -> ViewRef { + ViewRef::Readonly(self) + } + + pub fn checkout(&self) -> &CommitId { &self.data.checkout } - fn heads(&self) -> &HashSet { + pub fn heads(&self) -> &HashSet { &self.data.head_ids } - fn public_heads(&self) -> &HashSet { + pub fn public_heads(&self) -> &HashSet { &self.data.public_head_ids } - fn git_refs(&self) -> &BTreeMap { + pub fn git_refs(&self) -> &BTreeMap { &self.data.git_refs } - fn op_store(&self) -> Arc { + pub fn op_store(&self) -> Arc { self.op_store.clone() } - fn base_op_head_id(&self) -> &OperationId { - &self.base_op_head_id + pub fn base_op_head_id(&self) -> &OperationId { + &self.op_id } } impl MutableView { + pub fn as_view_ref(&self) -> ViewRef { + ViewRef::Mutable(self) + } + + pub fn checkout(&self) -> &CommitId { + &self.data.checkout + } + + pub fn heads(&self) -> &HashSet { + &self.data.head_ids + } + + pub fn public_heads(&self) -> &HashSet { + &self.data.public_head_ids + } + + pub fn git_refs(&self) -> &BTreeMap { + &self.data.git_refs + } + + pub fn op_store(&self) -> Arc { + self.op_store.clone() + } + + pub fn base_op_head_id(&self) -> &OperationId { + &self.base_op_head_id + } + pub fn set_checkout(&mut self, id: CommitId) { self.data.checkout = id; } diff --git a/lib/tests/test_bad_locking.rs b/lib/tests/test_bad_locking.rs index 439022971..064e44d21 100644 --- a/lib/tests/test_bad_locking.rs +++ b/lib/tests/test_bad_locking.rs @@ -18,7 +18,6 @@ use tempfile::TempDir; use jujube_lib::repo::ReadonlyRepo; use jujube_lib::testutils; -use jujube_lib::view::View; use std::sync::Arc; use test_case::test_case; diff --git a/lib/tests/test_commit_concurrent.rs b/lib/tests/test_commit_concurrent.rs index 06725272a..4420e4635 100644 --- a/lib/tests/test_commit_concurrent.rs +++ b/lib/tests/test_commit_concurrent.rs @@ -17,7 +17,6 @@ use std::thread; use jujube_lib::dag_walk; use jujube_lib::repo::ReadonlyRepo; use jujube_lib::testutils; -use jujube_lib::view::View; use std::sync::Arc; use test_case::test_case; diff --git a/lib/tests/test_git.rs b/lib/tests/test_git.rs index 4fcdfcc3d..268074ec8 100644 --- a/lib/tests/test_git.rs +++ b/lib/tests/test_git.rs @@ -20,7 +20,6 @@ use jujube_lib::repo::ReadonlyRepo; use jujube_lib::settings::UserSettings; use jujube_lib::store::CommitId; use jujube_lib::testutils; -use jujube_lib::view::View; use maplit::hashset; use std::collections::HashSet; use std::path::PathBuf; diff --git a/lib/tests/test_operations.rs b/lib/tests/test_operations.rs index a66da40a3..2d824867f 100644 --- a/lib/tests/test_operations.rs +++ b/lib/tests/test_operations.rs @@ -16,7 +16,6 @@ use jujube_lib::commit_builder::CommitBuilder; use jujube_lib::repo::RepoRef; use jujube_lib::store::CommitId; use jujube_lib::testutils; -use jujube_lib::view::View; use std::path::Path; use std::sync::Arc; use test_case::test_case; diff --git a/lib/tests/test_transaction.rs b/lib/tests/test_transaction.rs index c7ef79626..68da09606 100644 --- a/lib/tests/test_transaction.rs +++ b/lib/tests/test_transaction.rs @@ -17,7 +17,6 @@ use jujube_lib::repo_path::FileRepoPath; use jujube_lib::store::{Conflict, ConflictId, ConflictPart, TreeValue}; use jujube_lib::store_wrapper::StoreWrapper; use jujube_lib::testutils; -use jujube_lib::view::View; use std::sync::Arc; use test_case::test_case; diff --git a/lib/tests/test_view.rs b/lib/tests/test_view.rs index 79bb6c18a..8179fbc08 100644 --- a/lib/tests/test_view.rs +++ b/lib/tests/test_view.rs @@ -13,7 +13,6 @@ // limitations under the License. use jujube_lib::testutils; -use jujube_lib::view::View; use maplit::hashset; use test_case::test_case; diff --git a/lib/tests/test_working_copy.rs b/lib/tests/test_working_copy.rs index 442239dd5..db8f1cc80 100644 --- a/lib/tests/test_working_copy.rs +++ b/lib/tests/test_working_copy.rs @@ -22,7 +22,6 @@ use jujube_lib::settings::UserSettings; use jujube_lib::store::TreeValue; use jujube_lib::testutils; use jujube_lib::tree_builder::TreeBuilder; -use jujube_lib::view::View; use std::fs::OpenOptions; use std::io::Write; use std::sync::Arc; diff --git a/src/commands.rs b/src/commands.rs index a601b3b90..f7322e920 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -49,7 +49,6 @@ use jujube_lib::store::{CommitId, Timestamp}; use jujube_lib::store::{StoreError, TreeValue}; use jujube_lib::tree::Tree; use jujube_lib::trees::TreeValueDiff; -use jujube_lib::view::View; use jujube_lib::working_copy::{CheckoutStats, WorkingCopy}; use self::chrono::{FixedOffset, TimeZone, Utc}; @@ -204,10 +203,10 @@ fn op_arg<'a, 'b>() -> Arg<'a, 'b> { fn resolve_single_op(repo: &ReadonlyRepo, op_str: &str) -> Result { let view = repo.view(); if op_str == "@" { - Ok(view.base_op_head()) + Ok(view.as_view_ref().base_op_head()) } else if let Ok(binary_op_id) = hex::decode(op_str) { let op_id = OperationId(binary_op_id); - match view.get_operation(&op_id) { + match view.as_view_ref().get_operation(&op_id) { Ok(operation) => Ok(operation), Err(OpStoreError::NotFound) => Err(CommandError::UserError(format!( "Operation id not found: {}", @@ -1886,7 +1885,7 @@ fn cmd_op_log( ) -> Result<(), CommandError> { let repo = get_repo(ui, &matches)?; let view = repo.view(); - let head_op = view.base_op_head(); + let head_op = view.as_view_ref().base_op_head(); let mut styler = ui.styler(); let mut styler = styler.as_mut(); struct OpTemplate; @@ -1974,7 +1973,7 @@ fn cmd_op_undo( let view = repo.view(); let parent_view = parent_ops[0].view(); let bad_view = bad_op.view(); - let current_view = view.base_op_head().view(); + let current_view = view.as_view_ref().base_op_head().view(); merge_views( repo.store(), current_view.store_view(),