cli: recursively create clone destination path

This commit is contained in:
Vladimir Petrzhikovskii 2024-07-07 15:19:47 +02:00 committed by Vladimir
parent cd41bc3584
commit 802d2f5327
4 changed files with 50 additions and 12 deletions

View file

@ -38,6 +38,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
* `jj backout` can now back out multiple commits at once.
* `jj git clone some/nested/path` now creates the full directory tree for
nested destination paths if they don't exist.
### Fixed bugs
## [0.19.0] - 2024-07-03

View file

@ -36,7 +36,10 @@ pub struct GitCloneArgs {
/// URL or path of the Git repo to clone
#[arg(value_hint = clap::ValueHint::DirPath)]
source: String,
/// The directory to write the Jujutsu repo to
/// Specifies the target directory for the Jujutsu repository clone.
/// If not provided, defaults to a directory named after the last component
/// of the source URL. The full directory path will be created if it
/// doesn't exist.
#[arg(value_hint = clap::ValueHint::DirPath)]
destination: Option<String>,
/// Whether or not to colocate the Jujutsu repo with the git repo
@ -90,22 +93,18 @@ pub fn cmd_git_clone(
.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 = command.cwd().join(wc_path_str);
let wc_path_existed = match fs::create_dir(&wc_path) {
Ok(()) => false,
Err(err) if err.kind() == io::ErrorKind::AlreadyExists => true,
Err(err) => {
return Err(user_error_with_message(
format!("Failed to create {wc_path_str}"),
err,
));
}
};
let wc_path_existed = wc_path.exists();
if wc_path_existed && !is_empty_dir(&wc_path) {
return Err(user_error(
"Destination path exists and is not an empty directory",
));
}
// will create a tree dir in case if was deleted after last check
fs::create_dir_all(&wc_path)
.map_err(|err| user_error_with_message(format!("Failed to create {wc_path_str}"), err))?;
// Canonicalize because fs::remove_dir_all() doesn't seem to like e.g.
// `/some/path/.`
let canonical_wc_path: PathBuf = wc_path

View file

@ -840,7 +840,7 @@ The Git repo will be a bare git repo stored inside the `.jj/` directory.
###### **Arguments:**
* `<SOURCE>` — URL or path of the Git repo to clone
* `<DESTINATION>` — The directory to write the Jujutsu repo to
* `<DESTINATION>` — Specifies the target directory for the Jujutsu repository clone. If not provided, defaults to a directory named after the last component of the source URL. The full directory path will be created if it doesn't exist
###### **Options:**

View file

@ -136,6 +136,21 @@ fn test_git_clone() {
insta::assert_snapshot!(stderr, @r###"
Error: Destination path exists and is not an empty directory
"###);
// Clone into a nested path
let (stdout, stderr) = test_env.jj_cmd_ok(
test_env.env_root(),
&["git", "clone", "source", "nested/path/to/repo"],
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Fetching into new repo in "$TEST_ENV/nested/path/to/repo"
branch: main@origin [new] tracked
Setting the revset alias "trunk()" to "main@origin"
Working copy now at: uuzqqzqu df8acbac (empty) (no description set)
Parent commit : mzyxwzks 9f01a0e0 main | message
Added 1 files, modified 0 files, removed 0 files
"###);
}
#[test]
@ -308,6 +323,27 @@ fn test_git_clone_colocate() {
insta::assert_snapshot!(stderr, @r###"
Error: Destination path exists and is not an empty directory
"###);
// Clone into a nested path
let (stdout, stderr) = test_env.jj_cmd_ok(
test_env.env_root(),
&[
"git",
"clone",
"source",
"nested/path/to/repo",
"--colocate",
],
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Fetching into new repo in "$TEST_ENV/nested/path/to/repo"
branch: main@origin [new] tracked
Setting the revset alias "trunk()" to "main@origin"
Working copy now at: vzqnnsmr 9407107f (empty) (no description set)
Parent commit : mzyxwzks 9f01a0e0 main | message
Added 1 files, modified 0 files, removed 0 files
"###);
}
#[test]