Skip to content

Commit bf27f90

Browse files
committed
Auto merge of #13252 - connorworley:shallow_libgit2_fetches, r=weihanglo
Implementation of shallow libgit2 fetches behind an unstable flag This is my first contribution, so guidance is appreciated. Fixes #1171 by moving the `shallow-index` and `shallow-deps` aspects of `-Zgitoxide` to a new `-Zgit` unstable flag. The only change in interaction with libgit2 happens in `src/cargo/sources/git/utils.rs`, where we set the depth fetch option if applicable. Shallow fetch tests for gitoxide continue to pass, but libgit2 is harder to test as it silently ignores the depth option for local fetches. I would love any ideas on how to test it in a lightweight way or whether it's OK to wait for an upstream fix.
2 parents 54fd66a + 426b9e3 commit bf27f90

File tree

11 files changed

+155
-60
lines changed

11 files changed

+155
-60
lines changed

src/cargo/core/features.rs

+45-12
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,7 @@ unstable_cli_options!(
770770
dual_proc_macros: bool = ("Build proc-macros for both the host and the target"),
771771
features: Option<Vec<String>>,
772772
gc: bool = ("Track cache usage and \"garbage collect\" unused files"),
773+
git: Option<GitFeatures> = ("Enable support for shallow git fetch operations"),
773774
gitoxide: Option<GitoxideFeatures> = ("Use gitoxide for the given git interactions, or all of them if no argument is given"),
774775
host_config: bool = ("Enable the `[host]` section in the .cargo/config.toml file"),
775776
lints: bool = ("Pass `[lints]` to the linting tools"),
@@ -875,13 +876,47 @@ where
875876
}
876877

877878
#[derive(Debug, Copy, Clone, Default, Deserialize)]
878-
pub struct GitoxideFeatures {
879-
/// All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.
880-
pub fetch: bool,
879+
pub struct GitFeatures {
881880
/// When cloning the index, perform a shallow clone. Maintain shallowness upon subsequent fetches.
882881
pub shallow_index: bool,
883882
/// When cloning git dependencies, perform a shallow clone and maintain shallowness on subsequent fetches.
884883
pub shallow_deps: bool,
884+
}
885+
886+
impl GitFeatures {
887+
fn all() -> Self {
888+
GitFeatures {
889+
shallow_index: true,
890+
shallow_deps: true,
891+
}
892+
}
893+
}
894+
895+
fn parse_git(it: impl Iterator<Item = impl AsRef<str>>) -> CargoResult<Option<GitFeatures>> {
896+
let mut out = GitFeatures::default();
897+
let GitFeatures {
898+
shallow_index,
899+
shallow_deps,
900+
} = &mut out;
901+
902+
for e in it {
903+
match e.as_ref() {
904+
"shallow-index" => *shallow_index = true,
905+
"shallow-deps" => *shallow_deps = true,
906+
_ => {
907+
bail!(
908+
"unstable 'git' only takes 'shallow-index' and 'shallow-deps' as valid inputs"
909+
)
910+
}
911+
}
912+
}
913+
Ok(Some(out))
914+
}
915+
916+
#[derive(Debug, Copy, Clone, Default, Deserialize)]
917+
pub struct GitoxideFeatures {
918+
/// All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.
919+
pub fetch: bool,
885920
/// Checkout git dependencies using `gitoxide` (submodules are still handled by git2 ATM, and filters
886921
/// like linefeed conversions are unsupported).
887922
pub checkout: bool,
@@ -895,9 +930,7 @@ impl GitoxideFeatures {
895930
fn all() -> Self {
896931
GitoxideFeatures {
897932
fetch: true,
898-
shallow_index: true,
899933
checkout: true,
900-
shallow_deps: true,
901934
internal_use_git2: false,
902935
}
903936
}
@@ -907,9 +940,7 @@ impl GitoxideFeatures {
907940
fn safe() -> Self {
908941
GitoxideFeatures {
909942
fetch: true,
910-
shallow_index: false,
911943
checkout: true,
912-
shallow_deps: false,
913944
internal_use_git2: false,
914945
}
915946
}
@@ -921,21 +952,17 @@ fn parse_gitoxide(
921952
let mut out = GitoxideFeatures::default();
922953
let GitoxideFeatures {
923954
fetch,
924-
shallow_index,
925955
checkout,
926-
shallow_deps,
927956
internal_use_git2,
928957
} = &mut out;
929958

930959
for e in it {
931960
match e.as_ref() {
932961
"fetch" => *fetch = true,
933-
"shallow-index" => *shallow_index = true,
934-
"shallow-deps" => *shallow_deps = true,
935962
"checkout" => *checkout = true,
936963
"internal-use-git2" => *internal_use_git2 = true,
937964
_ => {
938-
bail!("unstable 'gitoxide' only takes `fetch`, 'shallow-index', 'shallow-deps' and 'checkout' as valid inputs")
965+
bail!("unstable 'gitoxide' only takes `fetch` and 'checkout' as valid input, for shallow fetches see `-Zgit=shallow-index,shallow-deps`")
939966
}
940967
}
941968
}
@@ -1109,6 +1136,12 @@ impl CliUnstable {
11091136
"doctest-xcompile" => self.doctest_xcompile = parse_empty(k, v)?,
11101137
"dual-proc-macros" => self.dual_proc_macros = parse_empty(k, v)?,
11111138
"gc" => self.gc = parse_empty(k, v)?,
1139+
"git" => {
1140+
self.git = v.map_or_else(
1141+
|| Ok(Some(GitFeatures::all())),
1142+
|v| parse_git(v.split(',')),
1143+
)?
1144+
}
11121145
"gitoxide" => {
11131146
self.gitoxide = v.map_or_else(
11141147
|| Ok(Some(GitoxideFeatures::all())),

src/cargo/sources/git/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mod utils;
1616

1717
/// For `-Zgitoxide` integration.
1818
pub mod fetch {
19-
use crate::core::features::GitoxideFeatures;
19+
use crate::core::features::GitFeatures;
2020
use crate::Config;
2121

2222
/// The kind remote repository to fetch.
@@ -37,18 +37,19 @@ pub mod fetch {
3737
repo_is_shallow: bool,
3838
config: &Config,
3939
) -> gix::remote::fetch::Shallow {
40-
let has_feature = |cb: &dyn Fn(GitoxideFeatures) -> bool| {
40+
let has_feature = |cb: &dyn Fn(GitFeatures) -> bool| {
4141
config
4242
.cli_unstable()
43-
.gitoxide
43+
.git
4444
.map_or(false, |features| cb(features))
4545
};
4646

4747
// maintain shallow-ness and keep downloading single commits, or see if we can do shallow clones
4848
if !repo_is_shallow {
4949
match self {
50-
RemoteKind::GitDependency if has_feature(&|git| git.shallow_deps) => {}
51-
RemoteKind::Registry if has_feature(&|git| git.shallow_index) => {}
50+
RemoteKind::GitDependency if has_feature(&|features| features.shallow_deps) => {
51+
}
52+
RemoteKind::Registry if has_feature(&|features| features.shallow_index) => {}
5253
_ => return gix::remote::fetch::Shallow::NoChange,
5354
}
5455
};

src/cargo/sources/git/oxide.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ pub fn with_retry_and_progress(
2929
) -> CargoResult<()> {
3030
std::thread::scope(|s| {
3131
let mut progress_bar = Progress::new("Fetch", config);
32-
let is_shallow = config
33-
.cli_unstable()
34-
.gitoxide
35-
.map_or(false, |gix| gix.shallow_deps || gix.shallow_index);
32+
let is_shallow = config.cli_unstable().git.map_or(false, |features| {
33+
features.shallow_deps || features.shallow_index
34+
});
3635
network::retry::with_retry(config, || {
3736
let progress_root: Arc<gix::progress::tree::Root> =
3837
gix::progress::tree::root::Options {

src/cargo/sources/git/source.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ impl<'cfg> GitSource<'cfg> {
108108
&source_id,
109109
config
110110
.cli_unstable()
111-
.gitoxide
112-
.map_or(false, |gix| gix.fetch && gix.shallow_deps),
111+
.git
112+
.map_or(false, |features| features.shallow_deps),
113113
);
114114

115115
let source = GitSource {

src/cargo/sources/git/utils.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,9 @@ pub fn fetch(
11171117
if tags {
11181118
opts.download_tags(git2::AutotagOption::All);
11191119
}
1120+
if let gix::remote::fetch::Shallow::DepthAtRemote(depth) = shallow {
1121+
opts.depth(0i32.saturating_add_unsigned(depth.get()));
1122+
}
11201123
// The `fetch` operation here may fail spuriously due to a corrupt
11211124
// repository. It could also fail, however, for a whole slew of other
11221125
// reasons (aka network related reasons). We want Cargo to automatically

src/cargo/sources/registry/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,8 @@ impl<'cfg> RegistrySource<'cfg> {
476476
source_id,
477477
config
478478
.cli_unstable()
479-
.gitoxide
480-
.map_or(false, |gix| gix.fetch && gix.shallow_index)
479+
.git
480+
.map_or(false, |features| features.shallow_index)
481481
&& !source_id.is_sparse(),
482482
);
483483
let ops = if source_id.is_sparse() {

src/doc/src/reference/unstable.md

+16-3
Original file line numberDiff line numberDiff line change
@@ -1172,19 +1172,32 @@ to run with `gitoxide` with the `-Zgitoxide=operation[,operationN]` syntax.
11721172
Valid operations are the following:
11731173

11741174
* `fetch` - All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.
1175+
* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules.
1176+
1177+
## git
1178+
1179+
* Tracking Issue: [#13285](https://github.com/rust-lang/cargo/issues/13285)
1180+
1181+
With the 'git' unstable feature, both `gitoxide` and `git2` will perform shallow fetches of the crate
1182+
index and git dependencies.
1183+
1184+
While `-Zgit` enables all currently implemented features, one can individually select when to perform
1185+
shallow fetches with the `-Zgit=operation[,operationN]` syntax.
1186+
1187+
Valid operations are the following:
1188+
11751189
* `shallow-index` - perform a shallow clone of the index.
11761190
* `shallow-deps` - perform a shallow clone of git dependencies.
1177-
* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules.
11781191

11791192
**Details on shallow clones**
11801193

1181-
* To enable shallow clones, add `-Zgitoxide=fetch,shallow_deps` for fetching git dependencies or `-Zgitoxide=fetch,shallow_index` for fetching registry index.
1194+
* To enable shallow clones, add `-Zgit=shallow-deps` for fetching git dependencies or `-Zgit=shallow-index` for fetching registry index.
11821195
* Shallow-cloned and shallow-checked-out git repositories reside at their own `-shallow` suffixed directories, i.e,
11831196
- `~/.cargo/registry/index/*-shallow`
11841197
- `~/.cargo/git/db/*-shallow`
11851198
- `~/.cargo/git/checkouts/*-shallow`
11861199
* When the unstable feature is on, fetching/cloning a git repository is always a shallow fetch. This roughly equals to `git fetch --depth 1` everywhere.
1187-
* Even with the presence of `Cargo.lock` or specifying a commit `{ rev = "…" }`, gitoxide is still smart enough to shallow fetch without unshallowing the existing repository.
1200+
* Even with the presence of `Cargo.lock` or specifying a commit `{ rev = "…" }`, gitoxide and libgit2 are still smart enough to shallow fetch without unshallowing the existing repository.
11881201

11891202
## script
11901203

tests/testsuite/cargo/z_help/stdout.log

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Available unstable (nightly-only) flags:
1414
-Z doctest-xcompile Compile and run doctests for non-host target using runner config
1515
-Z dual-proc-macros Build proc-macros for both the host and the target
1616
-Z gc Track cache usage and "garbage collect" unused files
17+
-Z git Enable support for shallow git fetch operations
1718
-Z gitoxide Use gitoxide for the given git interactions, or all of them if no argument is given
1819
-Z host-config Enable the `[host]` section in the .cargo/config.toml file
1920
-Z lints Pass `[lints]` to the linting tools

0 commit comments

Comments
 (0)