mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-08 05:39:20 +00:00
workspace: add function that initializes colocated git repository
One less git2 API use in CLI. The function name GitBackend::init_colocated() is a bit odd, but we need to specify the work-tree path, not the ".git" repo path. So we can't eliminate the notion of the working copy path anyway.
This commit is contained in:
parent
77e16243d6
commit
602b44258e
4 changed files with 75 additions and 2 deletions
|
@ -519,8 +519,7 @@ fn do_git_clone(
|
|||
wc_path: &Path,
|
||||
) -> Result<(WorkspaceCommandHelper, GitFetchStats), CommandError> {
|
||||
let (workspace, repo) = if colocate {
|
||||
let git_repo = git2::Repository::init(wc_path)?;
|
||||
Workspace::init_external_git(command.settings(), wc_path, git_repo.path())?
|
||||
Workspace::init_colocated_git(command.settings(), wc_path)?
|
||||
} else {
|
||||
Workspace::init_internal_git(command.settings(), wc_path)?
|
||||
};
|
||||
|
|
|
@ -136,6 +136,29 @@ impl GitBackend {
|
|||
Self::init_with_repo(store_path, git_repo_path, git_repo)
|
||||
}
|
||||
|
||||
/// Initializes backend by creating a new Git repo at the specified
|
||||
/// workspace path. The workspace directory must exist.
|
||||
pub fn init_colocated(
|
||||
store_path: &Path,
|
||||
workspace_root: &Path,
|
||||
) -> Result<Self, Box<GitBackendInitError>> {
|
||||
let canonical_workspace_root = {
|
||||
let path = store_path.join(workspace_root);
|
||||
path.canonicalize()
|
||||
.context(&path)
|
||||
.map_err(GitBackendInitError::Path)?
|
||||
};
|
||||
let git_repo = gix::ThreadSafeRepository::init(
|
||||
canonical_workspace_root,
|
||||
gix::create::Kind::WithWorktree,
|
||||
gix::create::Options::default(),
|
||||
)
|
||||
.map_err(GitBackendInitError::InitRepository)?;
|
||||
let git_repo_path = workspace_root.join(".git");
|
||||
Self::init_with_repo(store_path, &git_repo_path, git_repo)
|
||||
}
|
||||
|
||||
/// Initializes backend with an existing Git repo at the specified path.
|
||||
pub fn init_external(
|
||||
store_path: &Path,
|
||||
git_repo_path: &Path,
|
||||
|
|
|
@ -160,6 +160,32 @@ impl Workspace {
|
|||
Self::init_with_backend(user_settings, workspace_root, backend_initializer)
|
||||
}
|
||||
|
||||
/// Initializes a workspace with a new Git backend and Git repo that shares
|
||||
/// the same working copy.
|
||||
pub fn init_colocated_git(
|
||||
user_settings: &UserSettings,
|
||||
workspace_root: &Path,
|
||||
) -> Result<(Self, Arc<ReadonlyRepo>), WorkspaceInitError> {
|
||||
let backend_initializer = {
|
||||
let workspace_root = workspace_root.to_owned();
|
||||
move |store_path: &Path| -> Result<Box<dyn Backend>, BackendInitError> {
|
||||
// TODO: Clean up path normalization. store_path is canonicalized by
|
||||
// ReadonlyRepo::init(). workspace_root will be canonicalized by
|
||||
// Workspace::new(), but it's not yet here.
|
||||
let store_relative_workspace_root =
|
||||
if let Ok(workspace_root) = workspace_root.canonicalize() {
|
||||
file_util::relative_path(store_path, &workspace_root)
|
||||
} else {
|
||||
workspace_root.to_owned()
|
||||
};
|
||||
let backend =
|
||||
GitBackend::init_colocated(store_path, &store_relative_workspace_root)?;
|
||||
Ok(Box::new(backend))
|
||||
}
|
||||
};
|
||||
Self::init_with_backend(user_settings, workspace_root, &backend_initializer)
|
||||
}
|
||||
|
||||
/// Initializes a workspace with an existing Git repo at the specified path.
|
||||
pub fn init_external_git(
|
||||
user_settings: &UserSettings,
|
||||
|
|
|
@ -75,6 +75,31 @@ fn test_init_internal_git() {
|
|||
write_random_commit(tx.mut_repo(), &settings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_init_colocated_git() {
|
||||
let settings = testutils::user_settings();
|
||||
let temp_dir = testutils::new_temp_dir();
|
||||
let (canonical, uncanonical) = canonicalize(temp_dir.path());
|
||||
let (workspace, repo) = Workspace::init_colocated_git(&settings, &uncanonical).unwrap();
|
||||
let git_backend = repo
|
||||
.store()
|
||||
.backend_impl()
|
||||
.downcast_ref::<GitBackend>()
|
||||
.unwrap();
|
||||
assert_eq!(repo.repo_path(), &canonical.join(".jj").join("repo"));
|
||||
assert_eq!(workspace.workspace_root(), &canonical);
|
||||
assert_eq!(git_backend.git_repo_path(), canonical.join(".git"));
|
||||
assert_eq!(git_backend.git_workdir(), Some(canonical.as_ref()));
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(repo.repo_path().join("store").join("git_target")).unwrap(),
|
||||
"../../../.git"
|
||||
);
|
||||
|
||||
// Just test that we can write a commit to the store
|
||||
let mut tx = repo.start_transaction(&settings, "test");
|
||||
write_random_commit(tx.mut_repo(), &settings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_init_external_git() {
|
||||
let settings = testutils::user_settings();
|
||||
|
|
Loading…
Reference in a new issue