view: replace View trait by enum with Readonly and Mutable variants

This commit is contained in:
Martin von Zweigbergk 2021-01-31 23:41:59 -08:00
parent d1e5f46969
commit 72aebc9da3
12 changed files with 104 additions and 68 deletions

View file

@ -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());
}
}

View file

@ -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()
};

View file

@ -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()
}

View file

@ -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<CommitId>;
fn public_heads(&self) -> &HashSet<CommitId>;
fn git_refs(&self) -> &BTreeMap<String, CommitId>;
fn op_store(&self) -> Arc<dyn OpStore>;
fn base_op_head_id(&self) -> &OperationId;
pub enum ViewRef<'a> {
Readonly(&'a ReadonlyView),
Mutable(&'a MutableView),
}
fn get_operation(&self, id: &OperationId) -> OpStoreResult<Operation> {
// 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<CommitId> {
match self {
ViewRef::Readonly(view) => view.heads(),
ViewRef::Mutable(view) => view.heads(),
}
}
pub fn public_heads(&self) -> &'a HashSet<CommitId> {
match self {
ViewRef::Readonly(view) => view.public_heads(),
ViewRef::Mutable(view) => view.public_heads(),
}
}
pub fn git_refs(&self) -> &'a BTreeMap<String, CommitId> {
match self {
ViewRef::Readonly(view) => view.git_refs(),
ViewRef::Mutable(view) => view.git_refs(),
}
}
pub fn op_store(&self) -> Arc<dyn OpStore> {
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<Operation> {
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<CommitId> {
&self.data.head_ids
}
fn public_heads(&self) -> &HashSet<CommitId> {
&self.data.public_head_ids
}
fn git_refs(&self) -> &BTreeMap<String, CommitId> {
&self.data.git_refs
}
fn op_store(&self) -> Arc<dyn OpStore> {
self.op_store.clone()
}
fn base_op_head_id(&self) -> &OperationId {
&self.op_id
}
}
impl ReadonlyView {
pub fn init(store: Arc<StoreWrapper>, 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<CommitId> {
pub fn heads(&self) -> &HashSet<CommitId> {
&self.data.head_ids
}
fn public_heads(&self) -> &HashSet<CommitId> {
pub fn public_heads(&self) -> &HashSet<CommitId> {
&self.data.public_head_ids
}
fn git_refs(&self) -> &BTreeMap<String, CommitId> {
pub fn git_refs(&self) -> &BTreeMap<String, CommitId> {
&self.data.git_refs
}
fn op_store(&self) -> Arc<dyn OpStore> {
pub fn op_store(&self) -> Arc<dyn OpStore> {
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<CommitId> {
&self.data.head_ids
}
pub fn public_heads(&self) -> &HashSet<CommitId> {
&self.data.public_head_ids
}
pub fn git_refs(&self) -> &BTreeMap<String, CommitId> {
&self.data.git_refs
}
pub fn op_store(&self) -> Arc<dyn OpStore> {
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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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<Operation, CommandError> {
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(),