Skip to content

Commit

Permalink
cli: recursively create clone destination path
Browse files Browse the repository at this point in the history
  • Loading branch information
0xdeafbeef committed Jul 7, 2024
1 parent cd41bc3 commit 802d2f5
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 12 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 10 additions & 11 deletions cli/src/commands/git/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -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:**
Expand Down
36 changes: 36 additions & 0 deletions cli/tests/test_git_clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit 802d2f5

Please sign in to comment.