diff --git a/lib/src/repo.rs b/lib/src/repo.rs index 0e1286e5d..90fe1c579 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -120,67 +120,48 @@ impl Debug for ReadonlyRepo { } } -#[derive(Error, Debug, PartialEq)] -pub enum RepoInitError { - #[error("The destination repo ({0}) already exists")] - DestinationExists(PathBuf), -} - impl ReadonlyRepo { - pub fn init_local( - settings: &UserSettings, - wc_path: PathBuf, - ) -> Result, RepoInitError> { - let repo_path = ReadonlyRepo::init_repo_dir(&wc_path)?; + pub fn init_local(settings: &UserSettings, repo_path: PathBuf) -> Arc { + ReadonlyRepo::init_repo_dir(&repo_path); let store = Store::init_local(repo_path.join("store")); - Ok(ReadonlyRepo::init(settings, repo_path, wc_path, store)) + ReadonlyRepo::init(settings, repo_path, store) } /// Initializes a repo with a new Git backend in .jj/git/ (bare Git repo) - pub fn init_internal_git( - settings: &UserSettings, - wc_path: PathBuf, - ) -> Result, RepoInitError> { - let repo_path = ReadonlyRepo::init_repo_dir(&wc_path)?; + pub fn init_internal_git(settings: &UserSettings, repo_path: PathBuf) -> Arc { + ReadonlyRepo::init_repo_dir(&repo_path); let store = Store::init_internal_git(repo_path.join("store")); - Ok(ReadonlyRepo::init(settings, repo_path, wc_path, store)) + ReadonlyRepo::init(settings, repo_path, store) } /// Initializes a repo with an existing Git backend at the specified path pub fn init_external_git( settings: &UserSettings, - wc_path: PathBuf, + repo_path: PathBuf, git_repo_path: PathBuf, - ) -> Result, RepoInitError> { - let repo_path = ReadonlyRepo::init_repo_dir(&wc_path)?; + ) -> Arc { + ReadonlyRepo::init_repo_dir(&repo_path); let store = Store::init_external_git(repo_path.join("store"), git_repo_path); - Ok(ReadonlyRepo::init(settings, repo_path, wc_path, store)) + ReadonlyRepo::init(settings, repo_path, store) } - fn init_repo_dir(wc_path: &Path) -> Result { - let repo_path = wc_path.join(".jj"); - if repo_path.exists() { - Err(RepoInitError::DestinationExists(repo_path)) - } else { - fs::create_dir(&repo_path).unwrap(); - fs::create_dir(repo_path.join("store")).unwrap(); - fs::create_dir(repo_path.join("working_copy")).unwrap(); - fs::create_dir(repo_path.join("view")).unwrap(); - fs::create_dir(repo_path.join("op_store")).unwrap(); - fs::create_dir(repo_path.join("op_heads")).unwrap(); - fs::create_dir(repo_path.join("index")).unwrap(); - Ok(repo_path) - } + fn init_repo_dir(repo_path: &Path) { + fs::create_dir(repo_path.join("store")).unwrap(); + fs::create_dir(repo_path.join("working_copy")).unwrap(); + fs::create_dir(repo_path.join("view")).unwrap(); + fs::create_dir(repo_path.join("op_store")).unwrap(); + fs::create_dir(repo_path.join("op_heads")).unwrap(); + fs::create_dir(repo_path.join("index")).unwrap(); } fn init( user_settings: &UserSettings, repo_path: PathBuf, - wc_path: PathBuf, store: Arc, ) -> Arc { let repo_settings = user_settings.with_repo(&repo_path).unwrap(); + let wc_path = repo_path.parent().unwrap().to_path_buf(); let mut working_copy = WorkingCopy::init( store.clone(), wc_path.clone(), diff --git a/lib/src/workspace.rs b/lib/src/workspace.rs index 72f8e95f4..3b47cf9b5 100644 --- a/lib/src/workspace.rs +++ b/lib/src/workspace.rs @@ -17,10 +17,16 @@ use std::sync::Arc; use thiserror::Error; -use crate::repo::{ReadonlyRepo, RepoInitError, RepoLoader}; +use crate::repo::{ReadonlyRepo, RepoLoader}; use crate::settings::UserSettings; use crate::working_copy::WorkingCopy; +#[derive(Error, Debug, PartialEq)] +pub enum WorkspaceInitError { + #[error("The destination repo ({0}) already exists")] + DestinationExists(PathBuf), +} + #[derive(Error, Debug, PartialEq)] pub enum WorkspaceLoadError { #[error("There is no Jujutsu repo in {0}")] @@ -37,12 +43,23 @@ pub struct Workspace { working_copy: WorkingCopy, } +fn create_jj_dir(workspace_root: &Path) -> Result { + let jj_dir = workspace_root.join(".jj"); + if jj_dir.exists() { + Err(WorkspaceInitError::DestinationExists(jj_dir)) + } else { + std::fs::create_dir(&jj_dir).unwrap(); + Ok(jj_dir) + } +} + impl Workspace { pub fn init_local( user_settings: &UserSettings, workspace_root: PathBuf, - ) -> Result<(Self, Arc), RepoInitError> { - let repo = ReadonlyRepo::init_local(user_settings, workspace_root.clone())?; + ) -> Result<(Self, Arc), WorkspaceInitError> { + let jj_dir = create_jj_dir(&workspace_root)?; + let repo = ReadonlyRepo::init_local(user_settings, jj_dir); let repo_loader = repo.loader(); let workspace = Self::from_repo_loader(workspace_root, repo_loader); Ok((workspace, repo)) @@ -51,8 +68,9 @@ impl Workspace { pub fn init_internal_git( user_settings: &UserSettings, workspace_root: PathBuf, - ) -> Result<(Self, Arc), RepoInitError> { - let repo = ReadonlyRepo::init_internal_git(user_settings, workspace_root.clone())?; + ) -> Result<(Self, Arc), WorkspaceInitError> { + let jj_dir = create_jj_dir(&workspace_root)?; + let repo = ReadonlyRepo::init_internal_git(user_settings, jj_dir); let repo_loader = repo.loader(); let workspace = Self::from_repo_loader(workspace_root, repo_loader); Ok((workspace, repo)) @@ -62,9 +80,9 @@ impl Workspace { user_settings: &UserSettings, workspace_root: PathBuf, git_repo_path: PathBuf, - ) -> Result<(Self, Arc), RepoInitError> { - let repo = - ReadonlyRepo::init_external_git(user_settings, workspace_root.clone(), git_repo_path)?; + ) -> Result<(Self, Arc), WorkspaceInitError> { + let jj_dir = create_jj_dir(&workspace_root)?; + let repo = ReadonlyRepo::init_external_git(user_settings, jj_dir, git_repo_path); let repo_loader = repo.loader(); let workspace = Self::from_repo_loader(workspace_root, repo_loader); Ok((workspace, repo)) diff --git a/lib/tests/test_git.rs b/lib/tests/test_git.rs index d1030d6db..c4ce9c5c0 100644 --- a/lib/tests/test_git.rs +++ b/lib/tests/test_git.rs @@ -250,7 +250,7 @@ fn test_import_refs_empty_git_repo() { let git_repo = git2::Repository::init_bare(&git_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir).unwrap(); + let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir); let heads_before = repo.view().heads().clone(); let mut tx = repo.start_transaction("test"); jujutsu_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap(); @@ -271,7 +271,7 @@ fn test_init() { let initial_git_commit = empty_git_commit(&git_repo, "refs/heads/main", &[]); let initial_commit_id = commit_id(&initial_git_commit); std::fs::create_dir(&jj_repo_dir).unwrap(); - let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir).unwrap(); + let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir); // The refs were *not* imported -- it's the caller's responsibility to import // any refs they care about. assert!(!repo.view().heads().contains(&initial_commit_id)); @@ -290,7 +290,7 @@ fn test_fetch_success() { let clone_git_repo = git2::Repository::clone(source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir).unwrap(); + let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir); let new_git_commit = empty_git_commit(&source_git_repo, "refs/heads/main", &[&initial_git_commit]); @@ -341,7 +341,7 @@ fn test_fetch_prune_deleted_ref() { let clone_git_repo = git2::Repository::clone(source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir).unwrap(); + let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir); let mut tx = jj_repo.start_transaction("test"); git::fetch(tx.mut_repo(), &clone_git_repo, "origin").unwrap(); @@ -372,7 +372,7 @@ fn test_fetch_no_default_branch() { let clone_git_repo = git2::Repository::clone(source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir).unwrap(); + let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir); empty_git_commit(&source_git_repo, "refs/heads/main", &[&initial_git_commit]); // It's actually not enough to have a detached HEAD, it also needs to point to a @@ -397,7 +397,7 @@ fn test_fetch_no_such_remote() { let jj_repo_dir = temp_dir.path().join("jj"); let git_repo = git2::Repository::init_bare(&source_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, source_repo_dir).unwrap(); + let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, source_repo_dir); let mut tx = jj_repo.start_transaction("test"); let result = git::fetch(tx.mut_repo(), &git_repo, "invalid-remote"); @@ -420,7 +420,7 @@ fn set_up_push_repos(settings: &UserSettings, temp_dir: &TempDir) -> PushTestSet let initial_commit_id = commit_id(&initial_git_commit); git2::Repository::clone(source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let jj_repo = ReadonlyRepo::init_external_git(settings, jj_repo_dir, clone_repo_dir).unwrap(); + let jj_repo = ReadonlyRepo::init_external_git(settings, jj_repo_dir, clone_repo_dir); let mut tx = jj_repo.start_transaction("test"); let new_commit = testutils::create_random_commit(settings, &jj_repo) .set_parents(vec![initial_commit_id]) diff --git a/src/commands.rs b/src/commands.rs index d91b85d3b..89d0fb41f 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -45,7 +45,7 @@ use jujutsu_lib::op_heads_store::OpHeadsStore; use jujutsu_lib::op_store::{OpStore, OpStoreError, OperationId, RefTarget}; use jujutsu_lib::operation::Operation; use jujutsu_lib::refs::{classify_branch_push_action, BranchPushAction}; -use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, RepoInitError, RepoRef}; +use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, RepoRef}; use jujutsu_lib::repo_path::RepoPath; use jujutsu_lib::revset::{RevsetError, RevsetExpression, RevsetParseError}; use jujutsu_lib::revset_graph_iterator::RevsetGraphEdgeType; @@ -55,7 +55,7 @@ use jujutsu_lib::store::Store; use jujutsu_lib::transaction::Transaction; use jujutsu_lib::tree::TreeDiffIterator; use jujutsu_lib::working_copy::{CheckoutStats, WorkingCopy}; -use jujutsu_lib::workspace::{Workspace, WorkspaceLoadError}; +use jujutsu_lib::workspace::{Workspace, WorkspaceInitError, WorkspaceLoadError}; use jujutsu_lib::{conflicts, diff, files, git, revset, tree}; use maplit::{hashmap, hashset}; use pest::Parser; @@ -92,8 +92,8 @@ impl From for CommandError { } } -impl From for CommandError { - fn from(_: RepoInitError) -> Self { +impl From for CommandError { + fn from(_: WorkspaceInitError) -> Self { CommandError::UserError("The target repo already exists".to_string()) } }