diff --git a/lib/src/git_backend.rs b/lib/src/git_backend.rs index 85816e5b3..38cf285e7 100644 --- a/lib/src/git_backend.rs +++ b/lib/src/git_backend.rs @@ -75,14 +75,13 @@ impl GitBackend { } pub fn init_external(store_path: PathBuf, git_repo_path: PathBuf) -> Self { - let git_repo_path = std::fs::canonicalize(git_repo_path).unwrap(); let extra_path = store_path.join("extra"); std::fs::create_dir(&extra_path).unwrap(); let mut git_target_file = File::create(store_path.join("git_target")).unwrap(); git_target_file .write_all(git_repo_path.to_str().unwrap().as_bytes()) .unwrap(); - let repo = git2::Repository::open(git_repo_path).unwrap(); + let repo = git2::Repository::open(store_path.join(git_repo_path)).unwrap(); let extra_metadata_store = TableStore::init(extra_path, HASH_LENGTH); GitBackend::new(repo, extra_metadata_store) } diff --git a/src/commands.rs b/src/commands.rs index 5a7268bde..0b09e8870 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1731,12 +1731,22 @@ fn cmd_init(ui: &mut Ui, command: &CommandHelper, args: &ArgMatches) -> Result<( } else { fs::create_dir(&wc_path).unwrap(); } + let wc_path = std::fs::canonicalize(&wc_path).unwrap(); if let Some(git_store_str) = args.value_of("git-repo") { let mut git_store_path = ui.cwd().join(git_store_str); if !git_store_path.ends_with(".git") { git_store_path = git_store_path.join(".git"); } + git_store_path = std::fs::canonicalize(&git_store_path).unwrap(); + // If the git repo is inside the workspace, use a relative path to it so the + // whole workspace can be moved without breaking. + if let Ok(relative_path) = git_store_path.strip_prefix(&wc_path) { + git_store_path = PathBuf::from("..") + .join("..") + .join("..") + .join(relative_path.to_path_buf()); + } let (workspace, repo) = Workspace::init_external_git(ui.settings(), wc_path.clone(), git_store_path)?; let git_repo = repo.store().git_repo().unwrap(); diff --git a/tests/test_init_command.rs b/tests/test_init_command.rs index 521fb99f0..731892a4a 100644 --- a/tests/test_init_command.rs +++ b/tests/test_init_command.rs @@ -21,18 +21,18 @@ fn test_init_git_internal() { .jj_cmd(test_env.env_root(), &["init", "repo", "--git"]) .assert() .success(); - let workspace_root = test_env.env_root().join("repo"); + assert.stdout(format!( + "Initialized repo in \"{}\"\n", + workspace_root.to_str().unwrap() + )); + let jj_path = workspace_root.join(".jj"); let repo_path = jj_path.join("repo"); let store_path = repo_path.join("store"); assert!(workspace_root.is_dir()); assert!(jj_path.is_dir()); assert!(jj_path.join("working_copy").is_dir()); - assert.stdout(format!( - "Initialized repo in \"{}\"\n", - workspace_root.to_str().unwrap() - )); assert!(repo_path.is_dir()); assert!(store_path.is_dir()); assert!(store_path.join("git").is_dir()); @@ -45,7 +45,8 @@ fn test_init_git_internal() { fn test_init_git_external() { let test_env = TestEnvironment::default(); let git_repo_path = test_env.env_root().join("git-repo"); - git2::Repository::init(git_repo_path.clone()).unwrap(); + git2::Repository::init(&git_repo_path).unwrap(); + let assert = test_env .jj_cmd( test_env.env_root(), @@ -58,18 +59,18 @@ fn test_init_git_external() { ) .assert() .success(); - let workspace_root = test_env.env_root().join("repo"); + assert.stdout(format!( + "Initialized repo in \"{}\"\n", + workspace_root.display() + )); + let jj_path = workspace_root.join(".jj"); let repo_path = jj_path.join("repo"); let store_path = repo_path.join("store"); assert!(workspace_root.is_dir()); assert!(jj_path.is_dir()); assert!(jj_path.join("working_copy").is_dir()); - assert.stdout(format!( - "Initialized repo in \"{}\"\n", - workspace_root.display() - )); assert!(repo_path.is_dir()); assert!(store_path.is_dir()); let git_target_file_contents = std::fs::read_to_string(store_path.join("git_target")).unwrap(); @@ -79,24 +80,52 @@ fn test_init_git_external() { } #[test] -fn test_init_local() { +fn test_init_git_colocated() { let test_env = TestEnvironment::default(); + let workspace_root = test_env.env_root().join("repo"); + git2::Repository::init(&workspace_root).unwrap(); let assert = test_env - .jj_cmd(test_env.env_root(), &["init", "repo"]) + .jj_cmd(&workspace_root, &["init", "--git-repo", "."]) .assert() .success(); + assert.stdout(format!( + "Initialized repo in \"{}\"\n", + workspace_root.display() + )); - let workspace_root = test_env.env_root().join("repo"); let jj_path = workspace_root.join(".jj"); let repo_path = jj_path.join("repo"); let store_path = repo_path.join("store"); assert!(workspace_root.is_dir()); assert!(jj_path.is_dir()); assert!(jj_path.join("working_copy").is_dir()); + assert!(repo_path.is_dir()); + assert!(store_path.is_dir()); + let git_target_file_contents = std::fs::read_to_string(store_path.join("git_target")).unwrap(); + assert!(git_target_file_contents + .replace('\\', "/") + .ends_with("../../../.git")); +} + +#[test] +fn test_init_local() { + let test_env = TestEnvironment::default(); + let assert = test_env + .jj_cmd(test_env.env_root(), &["init", "repo"]) + .assert() + .success(); + let workspace_root = test_env.env_root().join("repo"); assert.stdout(format!( "Initialized repo in \"{}\"\n", workspace_root.display() )); + + let jj_path = workspace_root.join(".jj"); + let repo_path = jj_path.join("repo"); + let store_path = repo_path.join("store"); + assert!(workspace_root.is_dir()); + assert!(jj_path.is_dir()); + assert!(jj_path.join("working_copy").is_dir()); assert!(repo_path.is_dir()); assert!(store_path.is_dir()); assert!(store_path.join("commits").is_dir());