ok/jj
1
0
Fork 0
forked from mirrors/jj

repo: define types for backend initializer functions

`ReadonlyRepo::init()` takes callbacks for initializing each kind of
backend. We called these things like `op_store_initializer`. I found
that confusing because it is not a `OpStoreFactory` (which is for
loading an existing backend). This patch tries to clarify that by
renaming the arguments and adding types for each kind of callback
function.
This commit is contained in:
Martin von Zweigbergk 2023-10-16 08:01:33 -07:00 committed by Martin von Zweigbergk
parent 940e2438ee
commit 7c8a0a18f9
5 changed files with 78 additions and 74 deletions

View file

@ -54,7 +54,7 @@ fn run_custom_command(
CustomCommands::InitJit => {
let wc_path = command_helper.cwd();
// Initialize a workspace with the custom backend
Workspace::init_with_backend(command_helper.settings(), wc_path, |store_path| {
Workspace::init_with_backend(command_helper.settings(), wc_path, &|store_path| {
Ok(Box::new(JitBackend::init(store_path)?))
})?;
Ok(())

View file

@ -119,39 +119,39 @@ pub enum RepoInitError {
}
impl ReadonlyRepo {
pub fn default_op_store_factory() -> impl FnOnce(&Path) -> Box<dyn OpStore> {
|store_path| Box::new(SimpleOpStore::init(store_path))
pub fn default_op_store_initializer() -> &'static OpStoreInitializer {
&|store_path| Box::new(SimpleOpStore::init(store_path))
}
pub fn default_op_heads_store_factory() -> impl FnOnce(&Path) -> Box<dyn OpHeadsStore> {
|store_path| {
pub fn default_op_heads_store_initializer() -> &'static OpHeadsStoreInitializer {
&|store_path| {
let store = SimpleOpHeadsStore::init(store_path);
Box::new(store)
}
}
pub fn default_index_store_factory() -> impl FnOnce(&Path) -> Box<dyn IndexStore> {
|store_path| Box::new(DefaultIndexStore::init(store_path))
pub fn default_index_store_initializer() -> &'static IndexStoreInitializer {
&|store_path| Box::new(DefaultIndexStore::init(store_path))
}
pub fn default_submodule_store_factory() -> impl FnOnce(&Path) -> Box<dyn SubmoduleStore> {
|store_path| Box::new(DefaultSubmoduleStore::init(store_path))
pub fn default_submodule_store_initializer() -> &'static SubmoduleStoreInitializer {
&|store_path| Box::new(DefaultSubmoduleStore::init(store_path))
}
pub fn init(
user_settings: &UserSettings,
repo_path: &Path,
backend_factory: impl FnOnce(&Path) -> Result<Box<dyn Backend>, BackendInitError>,
op_store_factory: impl FnOnce(&Path) -> Box<dyn OpStore>,
op_heads_store_factory: impl FnOnce(&Path) -> Box<dyn OpHeadsStore>,
index_store_factory: impl FnOnce(&Path) -> Box<dyn IndexStore>,
submodule_store_factory: impl FnOnce(&Path) -> Box<dyn SubmoduleStore>,
backend_initializer: &BackendInitializer,
op_store_initializer: &OpStoreInitializer,
op_heads_store_initializer: &OpHeadsStoreInitializer,
index_store_initializer: &IndexStoreInitializer,
submodule_store_initializer: &SubmoduleStoreInitializer,
) -> Result<Arc<ReadonlyRepo>, RepoInitError> {
let repo_path = repo_path.canonicalize().context(repo_path)?;
let store_path = repo_path.join("store");
fs::create_dir(&store_path).context(&store_path)?;
let backend = backend_factory(&store_path)?;
let backend = backend_initializer(&store_path)?;
let backend_path = store_path.join("type");
fs::write(&backend_path, backend.name()).context(&backend_path)?;
let store = Store::new(backend, user_settings.use_tree_conflict_format());
@ -159,7 +159,7 @@ impl ReadonlyRepo {
let op_store_path = repo_path.join("op_store");
fs::create_dir(&op_store_path).context(&op_store_path)?;
let op_store = op_store_factory(&op_store_path);
let op_store = op_store_initializer(&op_store_path);
let op_store_type_path = op_store_path.join("type");
fs::write(&op_store_type_path, op_store.name()).context(&op_store_type_path)?;
let op_store: Arc<dyn OpStore> = Arc::from(op_store);
@ -182,7 +182,7 @@ impl ReadonlyRepo {
};
let init_operation_id = op_store.write_operation(&init_operation).unwrap();
let init_operation = Operation::new(op_store.clone(), init_operation_id, init_operation);
let op_heads_store = op_heads_store_factory(&op_heads_path);
let op_heads_store = op_heads_store_initializer(&op_heads_path);
op_heads_store.add_op_head(init_operation.id());
let op_heads_type_path = op_heads_path.join("type");
fs::write(&op_heads_type_path, op_heads_store.name()).context(&op_heads_type_path)?;
@ -190,14 +190,14 @@ impl ReadonlyRepo {
let index_path = repo_path.join("index");
fs::create_dir(&index_path).context(&index_path)?;
let index_store = index_store_factory(&index_path);
let index_store = index_store_initializer(&index_path);
let index_type_path = index_path.join("type");
fs::write(&index_type_path, index_store.name()).context(&index_type_path)?;
let index_store = Arc::from(index_store);
let submodule_store_path = repo_path.join("submodule_store");
fs::create_dir(&submodule_store_path).context(&submodule_store_path)?;
let submodule_store = submodule_store_factory(&submodule_store_path);
let submodule_store = submodule_store_initializer(&submodule_store_path);
let submodule_store_type_path = submodule_store_path.join("type");
fs::write(&submodule_store_type_path, submodule_store.name())
.context(&submodule_store_type_path)?;
@ -341,6 +341,12 @@ impl Repo for ReadonlyRepo {
}
}
pub type BackendInitializer = dyn Fn(&Path) -> Result<Box<dyn Backend>, BackendInitError>;
pub type OpStoreInitializer = dyn Fn(&Path) -> Box<dyn OpStore>;
pub type OpHeadsStoreInitializer = dyn Fn(&Path) -> Box<dyn OpHeadsStore>;
pub type IndexStoreInitializer = dyn Fn(&Path) -> Box<dyn IndexStore>;
pub type SubmoduleStoreInitializer = dyn Fn(&Path) -> Box<dyn SubmoduleStore>;
type BackendFactory = Box<dyn Fn(&Path) -> Result<Box<dyn Backend>, BackendLoadError>>;
type OpStoreFactory = Box<dyn Fn(&Path) -> Box<dyn OpStore>>;
type OpHeadsStoreFactory = Box<dyn Fn(&Path) -> Box<dyn OpHeadsStore>>;

View file

@ -25,18 +25,16 @@ use thiserror::Error;
use crate::backend::{Backend, BackendInitError, MergedTreeId};
use crate::file_util::{self, IoResultExt as _, PathError};
use crate::git_backend::GitBackend;
use crate::index::IndexStore;
use crate::local_backend::LocalBackend;
use crate::local_working_copy::LocalWorkingCopy;
use crate::merged_tree::MergedTree;
use crate::op_heads_store::OpHeadsStore;
use crate::op_store::{OpStore, OperationId, WorkspaceId};
use crate::op_store::{OperationId, WorkspaceId};
use crate::repo::{
CheckOutCommitError, ReadonlyRepo, Repo, RepoInitError, RepoLoader, StoreFactories,
StoreLoadError,
BackendInitializer, CheckOutCommitError, IndexStoreInitializer, OpHeadsStoreInitializer,
OpStoreInitializer, ReadonlyRepo, Repo, RepoInitError, RepoLoader, StoreFactories,
StoreLoadError, SubmoduleStoreInitializer,
};
use crate::settings::UserSettings;
use crate::submodule_store::SubmoduleStore;
use crate::working_copy::{
CheckoutError, CheckoutStats, LockedWorkingCopy, WorkingCopy, WorkingCopyStateError,
};
@ -141,9 +139,9 @@ impl Workspace {
user_settings: &UserSettings,
workspace_root: &Path,
) -> Result<(Self, Arc<ReadonlyRepo>), WorkspaceInitError> {
Self::init_with_backend(user_settings, workspace_root, |store_path| {
Ok(Box::new(LocalBackend::init(store_path)))
})
let backend_initializer: &'static BackendInitializer =
&|store_path| Ok(Box::new(LocalBackend::init(store_path)));
Self::init_with_backend(user_settings, workspace_root, backend_initializer)
}
/// Initializes a workspace with a new Git backend in .jj/git/ (bare Git
@ -152,9 +150,9 @@ impl Workspace {
user_settings: &UserSettings,
workspace_root: &Path,
) -> Result<(Self, Arc<ReadonlyRepo>), WorkspaceInitError> {
Self::init_with_backend(user_settings, workspace_root, |store_path| {
Ok(Box::new(GitBackend::init_internal(store_path)?))
})
let backend_initializer: &'static BackendInitializer =
&|store_path| Ok(Box::new(GitBackend::init_internal(store_path)?));
Self::init_with_backend(user_settings, workspace_root, backend_initializer)
}
/// Initializes a workspace with an existing Git backend at the specified
@ -164,7 +162,9 @@ impl Workspace {
workspace_root: &Path,
git_repo_path: &Path,
) -> Result<(Self, Arc<ReadonlyRepo>), WorkspaceInitError> {
Self::init_with_backend(user_settings, workspace_root, |store_path| {
let workspace_root = workspace_root.to_owned();
let git_repo_path = git_repo_path.to_owned();
Self::init_with_backend(user_settings, &workspace_root.clone(), &move |store_path| {
// If the git repo is inside the workspace, use a relative path to it so the
// whole workspace can be moved without breaking.
// TODO: Clean up path normalization. store_path is canonicalized by
@ -179,10 +179,8 @@ impl Workspace {
}
_ => git_repo_path.to_owned(),
};
Ok(Box::new(GitBackend::init_external(
store_path,
&store_relative_git_repo_path,
)?))
let backend = GitBackend::init_external(store_path, &store_relative_git_repo_path)?;
Ok(Box::new(backend) as Box<dyn Backend>)
})
}
@ -190,11 +188,11 @@ impl Workspace {
pub fn init_with_factories(
user_settings: &UserSettings,
workspace_root: &Path,
backend_factory: impl FnOnce(&Path) -> Result<Box<dyn Backend>, BackendInitError>,
op_store_factory: impl FnOnce(&Path) -> Box<dyn OpStore>,
op_heads_store_factory: impl FnOnce(&Path) -> Box<dyn OpHeadsStore>,
index_store_factory: impl FnOnce(&Path) -> Box<dyn IndexStore>,
submodule_store_factory: impl FnOnce(&Path) -> Box<dyn SubmoduleStore>,
backend_initializer: &BackendInitializer,
op_store_initializer: &OpStoreInitializer,
op_heads_store_initializer: &OpHeadsStoreInitializer,
index_store_initializer: &IndexStoreInitializer,
submodule_store_initializer: &SubmoduleStoreInitializer,
workspace_id: WorkspaceId,
) -> Result<(Self, Arc<ReadonlyRepo>), WorkspaceInitError> {
let jj_dir = create_jj_dir(workspace_root)?;
@ -204,11 +202,11 @@ impl Workspace {
let repo = ReadonlyRepo::init(
user_settings,
&repo_dir,
backend_factory,
op_store_factory,
op_heads_store_factory,
index_store_factory,
submodule_store_factory,
backend_initializer,
op_store_initializer,
op_heads_store_initializer,
index_store_initializer,
submodule_store_initializer,
)
.map_err(|repo_init_err| match repo_init_err {
RepoInitError::Backend(err) => WorkspaceInitError::Backend(err),
@ -229,16 +227,16 @@ impl Workspace {
pub fn init_with_backend(
user_settings: &UserSettings,
workspace_root: &Path,
backend_factory: impl FnOnce(&Path) -> Result<Box<dyn Backend>, BackendInitError>,
backend_initializer: &BackendInitializer,
) -> Result<(Self, Arc<ReadonlyRepo>), WorkspaceInitError> {
Self::init_with_factories(
user_settings,
workspace_root,
backend_factory,
ReadonlyRepo::default_op_store_factory(),
ReadonlyRepo::default_op_heads_store_factory(),
ReadonlyRepo::default_index_store_factory(),
ReadonlyRepo::default_submodule_store_factory(),
backend_initializer,
ReadonlyRepo::default_op_store_initializer(),
ReadonlyRepo::default_op_heads_store_initializer(),
ReadonlyRepo::default_index_store_initializer(),
ReadonlyRepo::default_submodule_store_initializer(),
WorkspaceId::default(),
)
}

View file

@ -1032,16 +1032,16 @@ impl GitRepoData {
let repo = ReadonlyRepo::init(
&settings,
&jj_repo_dir,
|store_path| {
&move |store_path| {
Ok(Box::new(GitBackend::init_external(
store_path,
&git_repo_dir,
)?))
},
ReadonlyRepo::default_op_store_factory(),
ReadonlyRepo::default_op_heads_store_factory(),
ReadonlyRepo::default_index_store_factory(),
ReadonlyRepo::default_submodule_store_factory(),
ReadonlyRepo::default_op_store_initializer(),
ReadonlyRepo::default_op_heads_store_initializer(),
ReadonlyRepo::default_index_store_initializer(),
ReadonlyRepo::default_submodule_store_initializer(),
)
.unwrap();
Self {
@ -1878,19 +1878,19 @@ fn test_init() {
let git_repo = git2::Repository::init_bare(&git_repo_dir).unwrap();
let initial_git_commit = empty_git_commit(&git_repo, "refs/heads/main", &[]);
std::fs::create_dir(&jj_repo_dir).unwrap();
let repo = ReadonlyRepo::init(
let repo = &ReadonlyRepo::init(
&settings,
&jj_repo_dir,
|store_path| {
&move |store_path| {
Ok(Box::new(GitBackend::init_external(
store_path,
&git_repo_dir,
)?))
},
ReadonlyRepo::default_op_store_factory(),
ReadonlyRepo::default_op_heads_store_factory(),
ReadonlyRepo::default_index_store_factory(),
ReadonlyRepo::default_submodule_store_factory(),
ReadonlyRepo::default_op_store_initializer(),
ReadonlyRepo::default_op_heads_store_initializer(),
ReadonlyRepo::default_index_store_initializer(),
ReadonlyRepo::default_submodule_store_initializer(),
)
.unwrap();
// The refs were *not* imported -- it's the caller's responsibility to import
@ -2173,16 +2173,16 @@ fn set_up_push_repos(settings: &UserSettings, temp_dir: &TempDir) -> PushTestSet
let jj_repo = ReadonlyRepo::init(
settings,
&jj_repo_dir,
|store_path| {
&move |store_path| {
Ok(Box::new(GitBackend::init_external(
store_path,
&clone_repo_dir,
)?))
},
ReadonlyRepo::default_op_store_factory(),
ReadonlyRepo::default_op_heads_store_factory(),
ReadonlyRepo::default_index_store_factory(),
ReadonlyRepo::default_submodule_store_factory(),
ReadonlyRepo::default_op_store_initializer(),
ReadonlyRepo::default_op_heads_store_initializer(),
ReadonlyRepo::default_index_store_initializer(),
ReadonlyRepo::default_submodule_store_initializer(),
)
.unwrap();
get_git_backend(&jj_repo)

View file

@ -120,13 +120,13 @@ impl TestRepo {
let repo = ReadonlyRepo::init(
&settings,
&repo_dir,
|store_path| -> Result<Box<dyn Backend>, BackendInitError> {
&move |store_path| -> Result<Box<dyn Backend>, BackendInitError> {
backend.init_backend(store_path)
},
ReadonlyRepo::default_op_store_factory(),
ReadonlyRepo::default_op_heads_store_factory(),
ReadonlyRepo::default_index_store_factory(),
ReadonlyRepo::default_submodule_store_factory(),
ReadonlyRepo::default_op_store_initializer(),
ReadonlyRepo::default_op_heads_store_initializer(),
ReadonlyRepo::default_index_store_initializer(),
ReadonlyRepo::default_submodule_store_initializer(),
)
.unwrap();
@ -165,7 +165,7 @@ impl TestWorkspace {
fs::create_dir(&workspace_root).unwrap();
let (workspace, repo) =
Workspace::init_with_backend(settings, &workspace_root, |store_path| {
Workspace::init_with_backend(settings, &workspace_root, &move |store_path| {
backend.init_backend(store_path)
})
.unwrap();