Skip to content

Commit 1bb9ade

Browse files
committed
feat(git): support shallow fetch for Git CLI backend
The newly added tests also ensure the interop between each backend
1 parent 565b914 commit 1bb9ade

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

src/cargo/sources/git/utils.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ pub fn fetch(
10321032

10331033
debug!("doing a fetch for {remote_url}");
10341034
let result = if let Some(true) = gctx.net_config()?.git_fetch_with_cli {
1035-
fetch_with_cli(repo, remote_url, &refspecs, tags, gctx)
1035+
fetch_with_cli(repo, remote_url, &refspecs, tags, shallow, gctx)
10361036
} else if gctx.cli_unstable().gitoxide.map_or(false, |git| git.fetch) {
10371037
fetch_with_gitoxide(repo, remote_url, refspecs, tags, shallow, gctx)
10381038
} else {
@@ -1076,6 +1076,7 @@ fn fetch_with_cli(
10761076
url: &str,
10771077
refspecs: &[String],
10781078
tags: bool,
1079+
shallow: gix::remote::fetch::Shallow,
10791080
gctx: &GlobalContext,
10801081
) -> CargoResult<()> {
10811082
debug!(target: "git-fetch", backend = "git-cli");
@@ -1087,6 +1088,10 @@ fn fetch_with_cli(
10871088
} else {
10881089
cmd.arg("--no-tags");
10891090
}
1091+
if let gix::remote::fetch::Shallow::DepthAtRemote(depth) = shallow {
1092+
let depth = 0i32.saturating_add_unsigned(depth.get());
1093+
cmd.arg(format!("--depth={depth}"));
1094+
}
10901095
match gctx.shell().verbosity() {
10911096
Verbosity::Normal => {}
10921097
Verbosity::Verbose => {

tests/testsuite/git_shallow.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ use crate::git_gc::find_index;
77
enum Backend {
88
Git2,
99
Gitoxide,
10+
GitCli,
1011
}
1112

1213
impl Backend {
1314
fn to_arg(&self) -> &'static str {
1415
match self {
1516
Backend::Git2 => "",
1617
Backend::Gitoxide => "-Zgitoxide=fetch",
18+
Backend::GitCli => "--config=net.git-fetch-with-cli=true",
1719
}
1820
}
1921

@@ -45,6 +47,11 @@ fn gitoxide_fetch_shallow_dep_two_revs() {
4547
fetch_dep_two_revs(Backend::Gitoxide)
4648
}
4749

50+
#[cargo_test]
51+
fn git_cli_fetch_shallow_dep_two_revs() {
52+
fetch_dep_two_revs(Backend::GitCli)
53+
}
54+
4855
fn fetch_dep_two_revs(backend: Backend) {
4956
let bar = git::new("meta-dep", |project| {
5057
project
@@ -138,6 +145,11 @@ fn gitoxide_fetch_shallow_dep_branch_and_rev() -> anyhow::Result<()> {
138145
fetch_shallow_dep_branch_and_rev(Backend::Gitoxide)
139146
}
140147

148+
#[cargo_test]
149+
fn git_cli_fetch_shallow_dep_branch_and_rev() -> anyhow::Result<()> {
150+
fetch_shallow_dep_branch_and_rev(Backend::GitCli)
151+
}
152+
141153
fn fetch_shallow_dep_branch_and_rev(backend: Backend) -> anyhow::Result<()> {
142154
let (bar, bar_repo) = git::new_repo("bar", |p| {
143155
p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
@@ -203,6 +215,11 @@ fn gitoxide_fetch_shallow_dep_branch_to_rev() -> anyhow::Result<()> {
203215
fetch_shallow_dep_branch_to_rev(Backend::Gitoxide)
204216
}
205217

218+
#[cargo_test]
219+
fn git_cli_fetch_shallow_dep_branch_to_rev() -> anyhow::Result<()> {
220+
fetch_shallow_dep_branch_to_rev(Backend::GitCli)
221+
}
222+
206223
fn fetch_shallow_dep_branch_to_rev(backend: Backend) -> anyhow::Result<()> {
207224
// db exists from previous build, then dependency changes to refer to revision that isn't
208225
// available in the shallow fetch.
@@ -292,6 +309,11 @@ fn gitoxide_fetch_shallow_index_then_git2_fetch_complete() -> anyhow::Result<()>
292309
fetch_shallow_index_then_fetch_complete(Backend::Gitoxide, Backend::Git2)
293310
}
294311

312+
#[cargo_test]
313+
fn git_cli_fetch_shallow_index_then_git2_fetch_complete() -> anyhow::Result<()> {
314+
fetch_shallow_index_then_fetch_complete(Backend::GitCli, Backend::Git2)
315+
}
316+
295317
fn fetch_shallow_index_then_fetch_complete(
296318
backend_1st: Backend,
297319
backend_2nd: Backend,
@@ -362,11 +384,31 @@ fn gitoxide_fetch_shallow_dep_then_git2_fetch_complete() -> anyhow::Result<()> {
362384
fetch_shallow_dep_then_fetch_complete(Backend::Gitoxide, Backend::Git2)
363385
}
364386

387+
#[cargo_test]
388+
fn git_cli_fetch_shallow_dep_then_git2_fetch_complete() -> anyhow::Result<()> {
389+
fetch_shallow_dep_then_fetch_complete(Backend::GitCli, Backend::Git2)
390+
}
391+
365392
#[cargo_test]
366393
fn gitoxide_fetch_shallow_dep_then_gitoxide_fetch_complete() -> anyhow::Result<()> {
367394
fetch_shallow_dep_then_fetch_complete(Backend::Gitoxide, Backend::Gitoxide)
368395
}
369396

397+
#[cargo_test]
398+
fn git_cli_fetch_shallow_dep_then_gitoxide_fetch_complete() -> anyhow::Result<()> {
399+
fetch_shallow_dep_then_fetch_complete(Backend::GitCli, Backend::Gitoxide)
400+
}
401+
402+
#[cargo_test]
403+
fn gitoxide_fetch_shallow_dep_then_git_cli_fetch_complete() -> anyhow::Result<()> {
404+
fetch_shallow_dep_then_fetch_complete(Backend::Gitoxide, Backend::GitCli)
405+
}
406+
407+
#[cargo_test]
408+
fn git_cli_fetch_shallow_dep_then_git_cli_fetch_complete() -> anyhow::Result<()> {
409+
fetch_shallow_dep_then_fetch_complete(Backend::GitCli, Backend::GitCli)
410+
}
411+
370412
fn fetch_shallow_dep_then_fetch_complete(
371413
backend_1st: Backend,
372414
backend_2nd: Backend,
@@ -518,6 +560,11 @@ fn gitoxide_fetch_shallow_index_then_preserve_shallow() -> anyhow::Result<()> {
518560
fetch_shallow_index_then_preserve_shallow(Backend::Gitoxide)
519561
}
520562

563+
#[cargo_test]
564+
fn git_cli_fetch_shallow_index_then_preserve_shallow() -> anyhow::Result<()> {
565+
fetch_shallow_index_then_preserve_shallow(Backend::GitCli)
566+
}
567+
521568
fn fetch_shallow_index_then_preserve_shallow(backend: Backend) -> anyhow::Result<()> {
522569
Package::new("bar", "1.0.0").publish();
523570
let p = project()
@@ -604,6 +651,11 @@ fn gitoxide_fetch_complete_index_then_shallow() -> anyhow::Result<()> {
604651
fetch_complete_index_then_shallow(Backend::Gitoxide)
605652
}
606653

654+
#[cargo_test]
655+
fn git_cli_fetch_complete_index_then_shallow() -> anyhow::Result<()> {
656+
fetch_complete_index_then_shallow(Backend::GitCli)
657+
}
658+
607659
fn fetch_complete_index_then_shallow(backend: Backend) -> anyhow::Result<()> {
608660
Package::new("bar", "1.0.0").publish();
609661
let p = project()
@@ -711,6 +763,25 @@ fn gitoxide_fetch_shallow_index_then_abort_and_update() -> anyhow::Result<()> {
711763
fetch_shallow_index_then_abort_and_update(Backend::Gitoxide)
712764
}
713765

766+
// Git CLI cannot recover from stale lock files like Gitoxide can.
767+
// This test simulates an aborted fetch by creating a stale shallow.lock file.
768+
// Gitoxide can detect and recover from this, but Git CLI will fail with:
769+
//
770+
// ```text
771+
// fatal: Unable to create \'/path/to/.git/shallow.lock\': File exists.
772+
//
773+
// Another git process seems to be running in this repository, e.g.
774+
// an editor opened by \'git commit\'. Please make sure all processes
775+
// are terminated then try again. If it still fails, a git process
776+
// may have crashed in this repository earlier:
777+
// remove the file manually to continue.
778+
// ```
779+
#[cargo_test]
780+
#[ignore = "Git CLI cannot recover from stale lock files"]
781+
fn git_cli_fetch_shallow_index_then_abort_and_update() -> anyhow::Result<()> {
782+
fetch_shallow_index_then_abort_and_update(Backend::GitCli)
783+
}
784+
714785
fn fetch_shallow_index_then_abort_and_update(backend: Backend) -> anyhow::Result<()> {
715786
Package::new("bar", "1.0.0").publish();
716787
let p = project()

0 commit comments

Comments
 (0)