mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 02:04:19 +00:00
cli: on clone, turn local git remote to absolute path
Otherwise a subsequent git fetch would fail.
This commit is contained in:
parent
d530b34568
commit
a45e00179c
2 changed files with 28 additions and 3 deletions
|
@ -4193,6 +4193,23 @@ fn cmd_git_fetch(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn absolute_git_source(cwd: &Path, source: &str) -> String {
|
||||
// Git appears to turn URL-like source to absolute path if local git directory
|
||||
// exits, and fails because '$PWD/https' is unsupported protocol. Since it would
|
||||
// be tedious to copy the exact git (or libgit2) behavior, we simply assume a
|
||||
// source containing ':' is a URL, SSH remote, or absolute path with Windows
|
||||
// drive letter.
|
||||
if !source.contains(':') && Path::new(source).exists() {
|
||||
// It's less likely that cwd isn't utf-8, so just fall back to original source.
|
||||
cwd.join(source)
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.unwrap_or_else(|_| source.to_owned())
|
||||
} else {
|
||||
source.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_destination_for_source(source: &str) -> Option<&str> {
|
||||
let destination = source.strip_suffix(".git").unwrap_or(source);
|
||||
let destination = destination.strip_suffix('/').unwrap_or(destination);
|
||||
|
@ -4217,11 +4234,11 @@ fn cmd_git_clone(
|
|||
if command.global_args().repository.is_some() {
|
||||
return Err(user_error("'--repository' cannot be used with 'git clone'"));
|
||||
}
|
||||
let source = &args.source;
|
||||
let source = absolute_git_source(ui.cwd(), &args.source);
|
||||
let wc_path_str = args
|
||||
.destination
|
||||
.as_deref()
|
||||
.or_else(|| clone_destination_for_source(source))
|
||||
.or_else(|| clone_destination_for_source(&source))
|
||||
.ok_or_else(|| user_error("No destination specified and wasn't able to guess it"))?;
|
||||
let wc_path = ui.cwd().join(wc_path_str);
|
||||
let wc_path_existed = wc_path.exists();
|
||||
|
@ -4235,7 +4252,7 @@ fn cmd_git_clone(
|
|||
fs::create_dir(&wc_path).unwrap();
|
||||
}
|
||||
|
||||
let clone_result = do_git_clone(ui, command, source, &wc_path);
|
||||
let clone_result = do_git_clone(ui, command, &source, &wc_path);
|
||||
if clone_result.is_err() {
|
||||
// Canonicalize because fs::remove_dir_all() doesn't seem to like e.g.
|
||||
// `/some/path/.`
|
||||
|
|
|
@ -50,6 +50,8 @@ fn test_git_clone() {
|
|||
)
|
||||
.unwrap();
|
||||
git_repo.set_head("refs/heads/main").unwrap();
|
||||
|
||||
// Clone with relative source path
|
||||
let stdout = test_env.jj_cmd_success(test_env.env_root(), &["git", "clone", "source", "clone"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
Fetching into new repo in "$TEST_ENV/clone"
|
||||
|
@ -58,6 +60,12 @@ fn test_git_clone() {
|
|||
"###);
|
||||
assert!(test_env.env_root().join("clone").join("file").exists());
|
||||
|
||||
// Subsequent fetch should just work even if the source path was relative
|
||||
let stdout = test_env.jj_cmd_success(&test_env.env_root().join("clone"), &["git", "fetch"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
Nothing changed.
|
||||
"###);
|
||||
|
||||
// Try cloning into an existing workspace
|
||||
let stderr = test_env.jj_cmd_failure(test_env.env_root(), &["git", "clone", "source", "clone"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
|
|
Loading…
Reference in a new issue