mirror of
https://github.com/martinvonz/jj.git
synced 2024-11-28 17:41:14 +00:00
index_store: extract trait
This is a step towards making the index storage pluggable. The interface will probably change a bit soon, but let's start with functions that match the current implementation. I called the current implementation the `DefaultIndexStore`. Calling it `SimpleIndexStore` (like `SimpleOpStore` and `SimpleOpHeadsStore`) didn't seem accurate.
This commit is contained in:
parent
904e9c5520
commit
3e4e0dc916
3 changed files with 76 additions and 61 deletions
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
|
@ -38,64 +39,33 @@ pub enum IndexWriteError {
|
|||
Other(String),
|
||||
}
|
||||
|
||||
pub struct IndexStore {
|
||||
dir: PathBuf,
|
||||
}
|
||||
pub trait IndexStore: Send + Sync + Debug {
|
||||
fn get_index_at_op(&self, op: &Operation, store: &Arc<Store>) -> Arc<ReadonlyIndex>;
|
||||
|
||||
impl IndexStore {
|
||||
pub fn init(dir: &Path) -> Self {
|
||||
std::fs::create_dir(dir.join("operations")).unwrap();
|
||||
IndexStore {
|
||||
dir: dir.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(dir: &Path) -> IndexStore {
|
||||
IndexStore {
|
||||
dir: dir.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_index_at_op(&self, op: &Operation, store: &Arc<Store>) -> Arc<ReadonlyIndex> {
|
||||
let op_id_hex = op.id().hex();
|
||||
let op_id_file = self.dir.join("operations").join(op_id_hex);
|
||||
if op_id_file.exists() {
|
||||
match self.load_index_at_operation(
|
||||
store.commit_id_length(),
|
||||
store.change_id_length(),
|
||||
op.id(),
|
||||
) {
|
||||
Err(IndexLoadError::IndexCorrupt(_)) => {
|
||||
// If the index was corrupt (maybe it was written in a different format),
|
||||
// we just reindex.
|
||||
// TODO: Move this message to a callback or something.
|
||||
println!("The index was corrupt (maybe the format has changed). Reindexing...");
|
||||
std::fs::remove_dir_all(self.dir.join("operations")).unwrap();
|
||||
std::fs::create_dir(self.dir.join("operations")).unwrap();
|
||||
self.index_at_operation(store, op).unwrap()
|
||||
}
|
||||
result => result.unwrap(),
|
||||
}
|
||||
} else {
|
||||
self.index_at_operation(store, op).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_index(
|
||||
fn write_index(
|
||||
&self,
|
||||
index: MutableIndex,
|
||||
op_id: &OperationId,
|
||||
) -> Result<Arc<ReadonlyIndex>, IndexWriteError> {
|
||||
let index = index.save_in(self.dir.clone()).map_err(|err| {
|
||||
IndexWriteError::Other(format!("Failed to write commit index file: {err:?}"))
|
||||
})?;
|
||||
self.associate_file_with_operation(&index, op_id)
|
||||
.map_err(|err| {
|
||||
IndexWriteError::Other(format!(
|
||||
"Failed to associate commit index file with a operation {op_id:?}: {err:?}"
|
||||
))
|
||||
})?;
|
||||
Ok(index)
|
||||
) -> Result<Arc<ReadonlyIndex>, IndexWriteError>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DefaultIndexStore {
|
||||
dir: PathBuf,
|
||||
}
|
||||
|
||||
impl DefaultIndexStore {
|
||||
pub fn init(dir: &Path) -> Self {
|
||||
std::fs::create_dir(dir.join("operations")).unwrap();
|
||||
DefaultIndexStore {
|
||||
dir: dir.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(dir: &Path) -> DefaultIndexStore {
|
||||
DefaultIndexStore {
|
||||
dir: dir.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_index_at_operation(
|
||||
|
@ -196,6 +166,50 @@ impl IndexStore {
|
|||
}
|
||||
}
|
||||
|
||||
impl IndexStore for DefaultIndexStore {
|
||||
fn get_index_at_op(&self, op: &Operation, store: &Arc<Store>) -> Arc<ReadonlyIndex> {
|
||||
let op_id_hex = op.id().hex();
|
||||
let op_id_file = self.dir.join("operations").join(op_id_hex);
|
||||
if op_id_file.exists() {
|
||||
match self.load_index_at_operation(
|
||||
store.commit_id_length(),
|
||||
store.change_id_length(),
|
||||
op.id(),
|
||||
) {
|
||||
Err(IndexLoadError::IndexCorrupt(_)) => {
|
||||
// If the index was corrupt (maybe it was written in a different format),
|
||||
// we just reindex.
|
||||
// TODO: Move this message to a callback or something.
|
||||
println!("The index was corrupt (maybe the format has changed). Reindexing...");
|
||||
std::fs::remove_dir_all(self.dir.join("operations")).unwrap();
|
||||
std::fs::create_dir(self.dir.join("operations")).unwrap();
|
||||
self.index_at_operation(store, op).unwrap()
|
||||
}
|
||||
result => result.unwrap(),
|
||||
}
|
||||
} else {
|
||||
self.index_at_operation(store, op).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn write_index(
|
||||
&self,
|
||||
index: MutableIndex,
|
||||
op_id: &OperationId,
|
||||
) -> Result<Arc<ReadonlyIndex>, IndexWriteError> {
|
||||
let index = index.save_in(self.dir.clone()).map_err(|err| {
|
||||
IndexWriteError::Other(format!("Failed to write commit index file: {err:?}"))
|
||||
})?;
|
||||
self.associate_file_with_operation(&index, op_id)
|
||||
.map_err(|err| {
|
||||
IndexWriteError::Other(format!(
|
||||
"Failed to associate commit index file with a operation {op_id:?}: {err:?}"
|
||||
))
|
||||
})?;
|
||||
Ok(index)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the ancestors of heads with parents and predecessors come before the
|
||||
// commit itself
|
||||
fn topo_order_earlier_first(
|
||||
|
|
|
@ -32,7 +32,7 @@ use crate::git_backend::GitBackend;
|
|||
use crate::index::{
|
||||
HexPrefix, Index, IndexEntry, IndexPosition, MutableIndex, PrefixResolution, ReadonlyIndex,
|
||||
};
|
||||
use crate::index_store::IndexStore;
|
||||
use crate::index_store::{DefaultIndexStore, IndexStore};
|
||||
use crate::local_backend::LocalBackend;
|
||||
use crate::op_heads_store::{self, OpHeadResolutionError, OpHeadsStore};
|
||||
use crate::op_store::{BranchTarget, OpStore, OperationId, RefTarget, WorkspaceId};
|
||||
|
@ -80,7 +80,7 @@ pub struct ReadonlyRepo {
|
|||
op_heads_store: Arc<dyn OpHeadsStore>,
|
||||
operation: Operation,
|
||||
settings: RepoSettings,
|
||||
index_store: Arc<IndexStore>,
|
||||
index_store: Arc<DefaultIndexStore>,
|
||||
index: OnceCell<Arc<ReadonlyIndex>>,
|
||||
// TODO: This should eventually become part of the index and not be stored fully in memory.
|
||||
change_id_index: OnceCell<ChangeIdIndex>,
|
||||
|
@ -158,7 +158,7 @@ impl ReadonlyRepo {
|
|||
|
||||
let index_path = repo_path.join("index");
|
||||
fs::create_dir(&index_path).context(&index_path)?;
|
||||
let index_store = Arc::new(IndexStore::init(&index_path));
|
||||
let index_store = Arc::new(DefaultIndexStore::init(&index_path));
|
||||
|
||||
let view = View::new(root_view);
|
||||
Ok(Arc::new(ReadonlyRepo {
|
||||
|
@ -224,7 +224,7 @@ impl ReadonlyRepo {
|
|||
&self.op_heads_store
|
||||
}
|
||||
|
||||
pub fn index_store(&self) -> &Arc<IndexStore> {
|
||||
pub fn index_store(&self) -> &Arc<DefaultIndexStore> {
|
||||
&self.index_store
|
||||
}
|
||||
|
||||
|
@ -457,7 +457,7 @@ pub struct RepoLoader {
|
|||
store: Arc<Store>,
|
||||
op_store: Arc<dyn OpStore>,
|
||||
op_heads_store: Arc<dyn OpHeadsStore>,
|
||||
index_store: Arc<IndexStore>,
|
||||
index_store: Arc<DefaultIndexStore>,
|
||||
}
|
||||
|
||||
impl RepoLoader {
|
||||
|
@ -471,7 +471,7 @@ impl RepoLoader {
|
|||
let op_store = Arc::from(store_factories.load_op_store(&repo_path.join("op_store"))?);
|
||||
let op_heads_store =
|
||||
Arc::from(store_factories.load_op_heads_store(&repo_path.join("op_heads"))?);
|
||||
let index_store = Arc::new(IndexStore::load(&repo_path.join("index")));
|
||||
let index_store = Arc::new(DefaultIndexStore::load(&repo_path.join("index")));
|
||||
Ok(Self {
|
||||
repo_path: repo_path.to_path_buf(),
|
||||
repo_settings,
|
||||
|
@ -490,7 +490,7 @@ impl RepoLoader {
|
|||
&self.store
|
||||
}
|
||||
|
||||
pub fn index_store(&self) -> &Arc<IndexStore> {
|
||||
pub fn index_store(&self) -> &Arc<DefaultIndexStore> {
|
||||
&self.index_store
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ use std::sync::Arc;
|
|||
use crate::backend::Timestamp;
|
||||
use crate::dag_walk::closest_common_node;
|
||||
use crate::index::ReadonlyIndex;
|
||||
use crate::index_store::IndexStore;
|
||||
use crate::op_store;
|
||||
use crate::op_store::OperationMetadata;
|
||||
use crate::operation::Operation;
|
||||
|
|
Loading…
Reference in a new issue