cli: on jj init --git-repo=., use relative path to .git/

When the backing Git repo is inside the workspace (typically directly
in `.git/`), let's point to it by a relative path so the whole
workspace can be moved without breaking the link.

Closes #72.
This commit is contained in:
Martin von Zweigbergk 2022-03-04 17:51:02 -08:00 committed by Martin von Zweigbergk
parent bbf4ba4118
commit 42252a2f00
3 changed files with 54 additions and 16 deletions

View file

@ -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)
}

View file

@ -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();

View file

@ -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());