diff --git a/CHANGELOG.md b/CHANGELOG.md index a588a1f891..6c26852ba0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). * Initial support for shallow git repositories has been implemented. However deepening the history of a shallow repository is not yet supported. +* `jj git clone` now accepts a `--depth ` option, which + allows to clone the repository with a given depth. + ### Fixed bugs * Fixed panic when parsing invalid conflict markers of a particular form. diff --git a/cli/src/commands/git/clone.rs b/cli/src/commands/git/clone.rs index 804b5a85d9..7761c7ed66 100644 --- a/cli/src/commands/git/clone.rs +++ b/cli/src/commands/git/clone.rs @@ -15,6 +15,7 @@ use std::fs; use std::io; use std::io::Write; +use std::num::NonZeroU32; use std::path::Path; use std::path::PathBuf; @@ -60,6 +61,9 @@ pub struct GitCloneArgs { /// Whether or not to colocate the Jujutsu repo with the git repo #[arg(long)] colocate: bool, + /// Create a shallow clone of the given depth + #[arg(long)] + depth: Option, } fn absolute_git_source(cwd: &Path, source: &str) -> String { @@ -132,6 +136,7 @@ pub fn cmd_git_clone( ui, command, args.colocate, + args.depth, remote_name, &source, &canonical_wc_path, @@ -195,6 +200,7 @@ fn do_git_clone( ui: &mut Ui, command: &CommandHelper, colocate: bool, + depth: Option, remote_name: &str, source: &str, wc_path: &Path, @@ -219,11 +225,11 @@ fn do_git_clone( git::fetch( fetch_tx.repo_mut(), &git_repo, - None, remote_name, &[StringPattern::everything()], cb, &command.settings().git_settings(), + depth, ) }) .map_err(|err| match err { diff --git a/cli/src/commands/git/fetch.rs b/cli/src/commands/git/fetch.rs index 4322d2d966..64865c9dfe 100644 --- a/cli/src/commands/git/fetch.rs +++ b/cli/src/commands/git/fetch.rs @@ -73,11 +73,11 @@ pub fn cmd_git_fetch( git::fetch( tx.repo_mut(), &git_repo, - None, remote, &args.branch, cb, &command.settings().git_settings(), + None, ) }) .map_err(|err| match err { diff --git a/cli/tests/cli-reference@.md.snap b/cli/tests/cli-reference@.md.snap index d2a4d709aa..b0fc4c3f62 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -968,6 +968,7 @@ The Git repo will be a bare git repo stored inside the `.jj/` directory. Default value: `origin` * `--colocate` — Whether or not to colocate the Jujutsu repo with the git repo +* `--depth ` — Create a shallow clone of the given depth diff --git a/cli/tests/test_git_clone.rs b/cli/tests/test_git_clone.rs index d8b611fa91..c2f58a2630 100644 --- a/cli/tests/test_git_clone.rs +++ b/cli/tests/test_git_clone.rs @@ -522,6 +522,26 @@ fn test_git_clone_with_remote_name() { "#); } +#[test] +fn test_git_clone_with_depth() { + let test_env = TestEnvironment::default(); + test_env.add_config("git.auto-local-branch = true"); + let git_repo_path = test_env.env_root().join("source"); + let git_repo = git2::Repository::init(git_repo_path).unwrap(); + set_up_non_empty_git_repo(&git_repo); + + // local transport does not support shallow clones so we just test that the + // depth arg is passed on here + let stderr = test_env.jj_cmd_failure( + test_env.env_root(), + &["git", "clone", "--depth", "1", "source", "clone"], + ); + insta::assert_snapshot!(stderr, @r#" + Fetching into new repo in "$TEST_ENV/clone" + Error: shallow fetch is not supported by the local transport; class=Net (12) + "#); +} + fn get_bookmark_output(test_env: &TestEnvironment, repo_path: &Path) -> String { test_env.jj_cmd_success(repo_path, &["bookmark", "list", "--all-remotes"]) } diff --git a/lib/src/git.rs b/lib/src/git.rs index d08c3b340d..2390a81378 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -1241,11 +1241,11 @@ pub struct GitFetchStats { pub fn fetch( mut_repo: &mut MutableRepo, git_repo: &git2::Repository, - depth: Option, remote_name: &str, branch_names: &[StringPattern], callbacks: RemoteCallbacks<'_>, git_settings: &GitSettings, + depth: Option, ) -> Result { // Perform a `git fetch` on the local git repo, updating the remote-tracking // branches in the git repo. @@ -1262,8 +1262,8 @@ pub fn fetch( fetch_options.proxy_options(proxy_options); let callbacks = callbacks.into_git(); fetch_options.remote_callbacks(callbacks); - if let Some(depth) = depth.and_then(|depth| depth.get().try_into().ok()) { - fetch_options.depth(depth); + if let Some(depth) = depth { + fetch_options.depth(depth.get().try_into().unwrap_or(i32::MAX)); } // At this point, we are only updating Git's remote tracking branches, not the // local branches. diff --git a/lib/tests/test_git.rs b/lib/tests/test_git.rs index 55610b1a2d..4d51d773b2 100644 --- a/lib/tests/test_git.rs +++ b/lib/tests/test_git.rs @@ -2266,11 +2266,11 @@ fn test_fetch_empty_repo() { let stats = git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); // No default bookmark and no refs @@ -2293,11 +2293,11 @@ fn test_fetch_initial_commit() { let stats = git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); // No default bookmark because the origin repo's HEAD wasn't set @@ -2344,11 +2344,11 @@ fn test_fetch_success() { git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); test_data.repo = tx.commit("test"); @@ -2368,11 +2368,11 @@ fn test_fetch_success() { let stats = git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); // The default bookmark is "main" @@ -2426,11 +2426,11 @@ fn test_fetch_prune_deleted_ref() { git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); // Test the setup @@ -2450,11 +2450,11 @@ fn test_fetch_prune_deleted_ref() { let stats = git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); assert_eq!(stats.import_stats.abandoned_commits, vec![jj_id(&commit)]); @@ -2478,11 +2478,11 @@ fn test_fetch_no_default_branch() { git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); @@ -2502,11 +2502,11 @@ fn test_fetch_no_default_branch() { let stats = git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); // There is no default bookmark @@ -2524,11 +2524,11 @@ fn test_fetch_empty_refspecs() { git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "origin", &[], git::RemoteCallbacks::default(), &git_settings, + None, ) .unwrap(); assert!(tx @@ -2551,11 +2551,11 @@ fn test_fetch_no_such_remote() { let result = git::fetch( tx.repo_mut(), &test_data.git_repo, - None, "invalid-remote", &[StringPattern::everything()], git::RemoteCallbacks::default(), &git_settings, + None, ); assert!(matches!(result, Err(GitFetchError::NoSuchRemote(_)))); }