mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 10:07:28 +00:00
view: let MutableRepo enforce view invariants
`MutableRepo` has more information needed for taking fast-paths, and it will have to make the same decision for doing incremental updates of the evolution state anyway.
This commit is contained in:
parent
b9fe944e76
commit
b4b1de3ddc
2 changed files with 31 additions and 28 deletions
|
@ -37,7 +37,7 @@ use crate::simple_op_store::SimpleOpStore;
|
|||
use crate::store::{CommitId, Store, StoreError};
|
||||
use crate::store_wrapper::StoreWrapper;
|
||||
use crate::transaction::Transaction;
|
||||
use crate::view::{merge_views, MutableView, ReadonlyView, ViewRef};
|
||||
use crate::view::{heads_of_set, merge_views, MutableView, ReadonlyView, ViewRef};
|
||||
use crate::working_copy::WorkingCopy;
|
||||
use crate::{conflicts, op_store, store};
|
||||
|
||||
|
@ -221,7 +221,7 @@ impl ReadonlyRepo {
|
|||
fs::create_dir(repo_path.join("index")).unwrap();
|
||||
let index_store = Arc::new(IndexStore::init(repo_path.join("index")));
|
||||
|
||||
let view = ReadonlyView::new(store.clone(), root_view);
|
||||
let view = ReadonlyView::new(root_view);
|
||||
|
||||
let repo = ReadonlyRepo {
|
||||
repo_path,
|
||||
|
@ -358,14 +358,14 @@ impl ReadonlyRepo {
|
|||
.get_single_op_head(&repo_loader)
|
||||
.unwrap();
|
||||
self.op_id = operation.id().clone();
|
||||
self.view = ReadonlyView::new(self.store.clone(), operation.view().take_store_view());
|
||||
self.view = ReadonlyView::new(operation.view().take_store_view());
|
||||
self.index.lock().unwrap().take();
|
||||
self.evolution.lock().unwrap().take();
|
||||
}
|
||||
|
||||
pub fn reload_at(&mut self, operation: &Operation) {
|
||||
self.op_id = operation.id().clone();
|
||||
self.view = ReadonlyView::new(self.store.clone(), operation.view().take_store_view());
|
||||
self.view = ReadonlyView::new(operation.view().take_store_view());
|
||||
self.index.lock().unwrap().take();
|
||||
self.evolution.lock().unwrap().take();
|
||||
}
|
||||
|
@ -442,12 +442,12 @@ impl RepoLoader {
|
|||
|
||||
pub fn load_at_head(&self) -> Result<Arc<ReadonlyRepo>, RepoLoadError> {
|
||||
let op = self.op_heads_store.get_single_op_head(&self).unwrap();
|
||||
let view = ReadonlyView::new(self.store.clone(), op.view().take_store_view());
|
||||
let view = ReadonlyView::new(op.view().take_store_view());
|
||||
self._finish_load(op.id().clone(), view)
|
||||
}
|
||||
|
||||
pub fn load_at(&self, op: &Operation) -> Result<Arc<ReadonlyRepo>, RepoLoadError> {
|
||||
let view = ReadonlyView::new(self.store.clone(), op.view().take_store_view());
|
||||
let view = ReadonlyView::new(op.view().take_store_view());
|
||||
self._finish_load(op.id().clone(), view)
|
||||
}
|
||||
|
||||
|
@ -548,7 +548,7 @@ impl<'r> MutableRepo<'r> {
|
|||
let mut locked_evolution = self.evolution.lock().unwrap();
|
||||
let maybe_evolution = locked_evolution.as_mut();
|
||||
// Extend lifetime from lifetime of MutexGuard to lifetime of self. Safe because
|
||||
// the value won't change again except for by invalidate_evolution(), which
|
||||
// the value won't change again except for by invalidate_evolution(), which
|
||||
// requires a mutable reference.
|
||||
unsafe { std::mem::transmute(maybe_evolution) }
|
||||
}
|
||||
|
@ -611,6 +611,18 @@ impl<'r> MutableRepo<'r> {
|
|||
open_commit
|
||||
}
|
||||
|
||||
fn enforce_view_invariants(&mut self) {
|
||||
// TODO: This is surely terribly slow on large repos, at least in its current
|
||||
// form. We should make it faster (using the index) and avoid calling it in
|
||||
// most cases (avoid adding a head that's already reachable in the view).
|
||||
let store = self.store().clone();
|
||||
let view = self.view.store_view_mut();
|
||||
view.public_head_ids = heads_of_set(&store, view.public_head_ids.iter().cloned());
|
||||
view.head_ids.extend(view.public_head_ids.iter().cloned());
|
||||
view.head_ids.extend(view.git_refs.values().cloned());
|
||||
view.head_ids = heads_of_set(&store, view.head_ids.iter().cloned());
|
||||
}
|
||||
|
||||
pub fn add_head(&mut self, head: &Commit) {
|
||||
let current_heads = self.view.heads();
|
||||
// Use incremental update for common case of adding a single commit on top a
|
||||
|
@ -623,6 +635,7 @@ impl<'r> MutableRepo<'r> {
|
|||
{
|
||||
self.index.add_commit(head);
|
||||
self.view.add_head(head);
|
||||
self.enforce_view_invariants();
|
||||
if let Some(evolution) = self.evolution_mut() {
|
||||
evolution.add_commit(head)
|
||||
}
|
||||
|
@ -642,17 +655,20 @@ impl<'r> MutableRepo<'r> {
|
|||
self.index.add_commit(missing_commit);
|
||||
}
|
||||
self.view.add_head(head);
|
||||
self.enforce_view_invariants();
|
||||
self.invalidate_evolution();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_head(&mut self, head: &Commit) {
|
||||
self.view.remove_head(head);
|
||||
self.enforce_view_invariants();
|
||||
self.invalidate_evolution();
|
||||
}
|
||||
|
||||
pub fn add_public_head(&mut self, head: &Commit) {
|
||||
self.view.add_public_head(head);
|
||||
self.enforce_view_invariants();
|
||||
if let Some(evolution) = self.evolution_mut() {
|
||||
evolution.add_commit(head)
|
||||
}
|
||||
|
@ -673,6 +689,7 @@ impl<'r> MutableRepo<'r> {
|
|||
|
||||
pub fn set_view(&mut self, data: op_store::View) {
|
||||
self.view.set_view(data);
|
||||
self.enforce_view_invariants();
|
||||
self.invalidate_evolution();
|
||||
}
|
||||
|
||||
|
@ -690,6 +707,7 @@ impl<'r> MutableRepo<'r> {
|
|||
other_repo.view.store_view(),
|
||||
);
|
||||
self.view.set_view(merged_view);
|
||||
self.enforce_view_invariants();
|
||||
|
||||
self.invalidate_evolution();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
use std::cmp::min;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::commit::Commit;
|
||||
use crate::op_store;
|
||||
|
@ -57,26 +56,14 @@ impl<'a> ViewRef<'a> {
|
|||
}
|
||||
|
||||
pub struct ReadonlyView {
|
||||
store: Arc<StoreWrapper>,
|
||||
data: op_store::View,
|
||||
}
|
||||
|
||||
pub struct MutableView {
|
||||
store: Arc<StoreWrapper>,
|
||||
data: op_store::View,
|
||||
}
|
||||
|
||||
fn enforce_invariants(store: &StoreWrapper, view: &mut op_store::View) {
|
||||
// TODO: This is surely terribly slow on large repos, at least in its current
|
||||
// form. We should make it faster (using the index) and avoid calling it in
|
||||
// most cases (avoid adding a head that's already reachable in the view).
|
||||
view.public_head_ids = heads_of_set(store, view.public_head_ids.iter().cloned());
|
||||
view.head_ids.extend(view.public_head_ids.iter().cloned());
|
||||
view.head_ids.extend(view.git_refs.values().cloned());
|
||||
view.head_ids = heads_of_set(store, view.head_ids.iter().cloned());
|
||||
}
|
||||
|
||||
fn heads_of_set(
|
||||
pub(crate) fn heads_of_set(
|
||||
store: &StoreWrapper,
|
||||
commit_ids: impl Iterator<Item = CommitId>,
|
||||
) -> HashSet<CommitId> {
|
||||
|
@ -176,9 +163,8 @@ pub(crate) fn merge_views(
|
|||
}
|
||||
|
||||
impl ReadonlyView {
|
||||
pub fn new(store: Arc<StoreWrapper>, op_store_view: op_store::View) -> Self {
|
||||
pub fn new(op_store_view: op_store::View) -> Self {
|
||||
ReadonlyView {
|
||||
store,
|
||||
data: op_store_view,
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +172,6 @@ impl ReadonlyView {
|
|||
pub fn start_modification(&self) -> MutableView {
|
||||
// TODO: Avoid the cloning of the sets here.
|
||||
MutableView {
|
||||
store: self.store.clone(),
|
||||
data: self.data.clone(),
|
||||
}
|
||||
}
|
||||
|
@ -243,17 +228,14 @@ impl MutableView {
|
|||
|
||||
pub fn add_head(&mut self, head: &Commit) {
|
||||
self.data.head_ids.insert(head.id().clone());
|
||||
enforce_invariants(&self.store, &mut self.data);
|
||||
}
|
||||
|
||||
pub fn remove_head(&mut self, head: &Commit) {
|
||||
self.data.head_ids.remove(head.id());
|
||||
enforce_invariants(&self.store, &mut self.data);
|
||||
}
|
||||
|
||||
pub fn add_public_head(&mut self, head: &Commit) {
|
||||
self.data.public_head_ids.insert(head.id().clone());
|
||||
enforce_invariants(&self.store, &mut self.data);
|
||||
}
|
||||
|
||||
pub fn remove_public_head(&mut self, head: &Commit) {
|
||||
|
@ -270,10 +252,13 @@ impl MutableView {
|
|||
|
||||
pub fn set_view(&mut self, data: op_store::View) {
|
||||
self.data = data;
|
||||
enforce_invariants(&self.store, &mut self.data);
|
||||
}
|
||||
|
||||
pub fn store_view(&self) -> &op_store::View {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn store_view_mut(&mut self) -> &mut op_store::View {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue