Skip to content

Commit a1559be

Browse files
committed
Implementation of shallow libgit2 fetches behind an unstable flag
1 parent 4eef543 commit a1559be

File tree

10 files changed

+154
-60
lines changed

10 files changed

+154
-60
lines changed

src/cargo/core/features.rs

Lines changed: 45 additions & 12 deletions
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 inputs")
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

Lines changed: 6 additions & 5 deletions
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

Lines changed: 3 additions & 4 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,19 +1160,32 @@ to run with `gitoxide` with the `-Zgitoxide=operation[,operationN]` syntax.
11601160
Valid operations are the following:
11611161

11621162
* `fetch` - All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.
1163+
* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules.
1164+
1165+
## git
1166+
1167+
* Tracking Issue: [TODO]()
1168+
1169+
With the 'git' unstable feature, both `gitoxide` and `git2` will perform shallow fetches of the crate
1170+
index and git dependencies.
1171+
1172+
While `-Zgit` enables all currently implemented features, one can individually select when to perform
1173+
shallow fetches with the `-Zgit=operation[,operationN]` syntax.
1174+
1175+
Valid operations are the following:
1176+
11631177
* `shallow-index` - perform a shallow clone of the index.
11641178
* `shallow-deps` - perform a shallow clone of git dependencies.
1165-
* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules.
11661179

11671180
**Details on shallow clones**
11681181

1169-
* To enable shallow clones, add `-Zgitoxide=fetch,shallow_deps` for fetching git dependencies or `-Zgitoxide=fetch,shallow_index` for fetching registry index.
1182+
* To enable shallow clones, add `-Zgit=shallow-deps` for fetching git dependencies or `-Zgit=shallow-index` for fetching registry index.
11701183
* Shallow-cloned and shallow-checked-out git repositories reside at their own `-shallow` suffixed directories, i.e,
11711184
- `~/.cargo/registry/index/*-shallow`
11721185
- `~/.cargo/git/db/*-shallow`
11731186
- `~/.cargo/git/checkouts/*-shallow`
11741187
* 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.
1175-
* 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.
1188+
* 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. TODO: does this hold for libgit2?
11761189

11771190
## script
11781191

0 commit comments

Comments
 (0)