mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 18:27:38 +00:00
repo: get change id index from revset instead of building it in repo
This replaces the direct use of `IdIndex` in `ReadonlyRepo` by use of `Revset::change_id_index()`. I made the `Index` trait require `Send` and `Sync` in order to be able to store an instance of it in `ReadonlyRepo` (via `ChangeIdIndex`) and still have that be `Send` and `Sync`. We could alternatively store the `ChangeIdIndex` in a `Mutex`. Now that will be up to the `ChangeIdIndex` instead.
This commit is contained in:
parent
27a7fccefa
commit
68cff2fa22
4 changed files with 30 additions and 24 deletions
|
@ -799,7 +799,7 @@ impl MutableIndex for MutableIndexImpl {
|
|||
}
|
||||
}
|
||||
|
||||
trait IndexSegment {
|
||||
trait IndexSegment: Send + Sync {
|
||||
fn segment_num_parent_commits(&self) -> u32;
|
||||
|
||||
fn segment_num_commits(&self) -> u32;
|
||||
|
|
|
@ -47,7 +47,7 @@ pub trait IndexStore: Send + Sync + Debug {
|
|||
) -> Result<Box<dyn ReadonlyIndex>, IndexWriteError>;
|
||||
}
|
||||
|
||||
pub trait Index {
|
||||
pub trait Index: Send + Sync {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition>;
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::io::ErrorKind;
|
||||
use std::ops::Deref;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::{fs, io};
|
||||
|
||||
|
@ -28,7 +30,7 @@ use crate::backend::{Backend, BackendError, BackendResult, ChangeId, CommitId, O
|
|||
use crate::commit::Commit;
|
||||
use crate::commit_builder::CommitBuilder;
|
||||
use crate::dag_walk::topo_order_reverse;
|
||||
use crate::default_index_store::{DefaultIndexStore, IndexPosition};
|
||||
use crate::default_index_store::DefaultIndexStore;
|
||||
use crate::git_backend::GitBackend;
|
||||
use crate::index::{HexPrefix, Index, IndexStore, MutableIndex, PrefixResolution, ReadonlyIndex};
|
||||
use crate::local_backend::LocalBackend;
|
||||
|
@ -36,6 +38,7 @@ use crate::op_heads_store::{self, OpHeadResolutionError, OpHeadsStore};
|
|||
use crate::op_store::{BranchTarget, OpStore, OperationId, RefTarget, WorkspaceId};
|
||||
use crate::operation::Operation;
|
||||
use crate::refs::merge_ref_targets;
|
||||
use crate::revset::{ChangeIdIndex, Revset, RevsetExpression};
|
||||
use crate::rewrite::DescendantRebaser;
|
||||
use crate::settings::{RepoSettings, UserSettings};
|
||||
use crate::simple_op_heads_store::SimpleOpHeadsStore;
|
||||
|
@ -77,9 +80,10 @@ pub struct ReadonlyRepo {
|
|||
operation: Operation,
|
||||
settings: RepoSettings,
|
||||
index_store: Arc<dyn IndexStore>,
|
||||
index: OnceCell<Box<dyn ReadonlyIndex>>,
|
||||
index: OnceCell<Pin<Box<dyn ReadonlyIndex>>>,
|
||||
// Declared after `change_id_index` since it must outlive it on drop.
|
||||
change_id_index: OnceCell<Box<dyn ChangeIdIndex>>,
|
||||
// TODO: This should eventually become part of the index and not be stored fully in memory.
|
||||
change_id_index: OnceCell<ChangeIdIndex>,
|
||||
view: View,
|
||||
}
|
||||
|
||||
|
@ -209,21 +213,27 @@ impl ReadonlyRepo {
|
|||
pub fn readonly_index(&self) -> &dyn ReadonlyIndex {
|
||||
self.index
|
||||
.get_or_init(|| {
|
||||
self.index_store
|
||||
.get_index_at_op(&self.operation, &self.store)
|
||||
Box::into_pin(
|
||||
self.index_store
|
||||
.get_index_at_op(&self.operation, &self.store),
|
||||
)
|
||||
})
|
||||
.as_ref()
|
||||
.deref()
|
||||
}
|
||||
|
||||
fn change_id_index(&self) -> &ChangeIdIndex {
|
||||
self.change_id_index.get_or_init(|| {
|
||||
let heads = self.view().heads().iter().cloned().collect_vec();
|
||||
let walk = self.readonly_index().as_index().walk_revs(&heads, &[]);
|
||||
IdIndex::from_vec(
|
||||
walk.map(|entry| (entry.change_id(), entry.position()))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
fn change_id_index<'a>(&'a self) -> &'a (dyn ChangeIdIndex + 'a) {
|
||||
let change_id_index: &'a (dyn ChangeIdIndex + 'a) = self
|
||||
.change_id_index
|
||||
.get_or_init(|| {
|
||||
let revset: Box<dyn Revset<'a>> = RevsetExpression::all().evaluate(self).unwrap();
|
||||
let change_id_index: Box<dyn ChangeIdIndex + 'a> = revset.change_id_index();
|
||||
// evaluate() above only borrows the index, not the whole repo
|
||||
let change_id_index: Box<dyn ChangeIdIndex> =
|
||||
unsafe { std::mem::transmute(change_id_index) };
|
||||
change_id_index
|
||||
})
|
||||
.as_ref();
|
||||
change_id_index
|
||||
}
|
||||
|
||||
pub fn op_heads_store(&self) -> &Arc<dyn OpHeadsStore> {
|
||||
|
@ -277,9 +287,7 @@ impl Repo for ReadonlyRepo {
|
|||
}
|
||||
|
||||
fn resolve_change_id_prefix(&self, prefix: &HexPrefix) -> PrefixResolution<Vec<CommitId>> {
|
||||
let index = self.index();
|
||||
self.change_id_index()
|
||||
.resolve_prefix_with(prefix, |&pos| index.entry_by_pos(pos).commit_id())
|
||||
self.change_id_index().resolve_prefix(prefix)
|
||||
}
|
||||
|
||||
fn shortest_unique_change_id_prefix_len(&self, target_id: &ChangeId) -> usize {
|
||||
|
@ -578,7 +586,7 @@ impl RepoLoader {
|
|||
operation,
|
||||
settings: self.repo_settings.clone(),
|
||||
index_store: self.index_store.clone(),
|
||||
index: OnceCell::with_value(index),
|
||||
index: OnceCell::with_value(Box::into_pin(index)),
|
||||
change_id_index: OnceCell::new(),
|
||||
view,
|
||||
};
|
||||
|
@ -1272,8 +1280,6 @@ mod dirty_cell {
|
|||
}
|
||||
}
|
||||
|
||||
type ChangeIdIndex = IdIndex<ChangeId, IndexPosition>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IdIndex<K, V>(Vec<(K, V)>);
|
||||
|
||||
|
|
|
@ -1582,7 +1582,7 @@ pub trait Revset<'index> {
|
|||
fn is_empty(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait ChangeIdIndex {
|
||||
pub trait ChangeIdIndex: Send + Sync {
|
||||
/// Resolve an unambiguous change ID prefix to the commit IDs in the revset.
|
||||
fn resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution<Vec<CommitId>>;
|
||||
|
||||
|
|
Loading…
Reference in a new issue