mirror of
https://github.com/rust-lang/cargo
synced 2024-10-30 22:57:17 +00:00
872 lines
24 KiB
Rust
872 lines
24 KiB
Rust
use crate::git_gc::find_index;
|
|
use cargo_test_support::registry::Package;
|
|
use cargo_test_support::{basic_manifest, git, paths, project};
|
|
|
|
enum RepoMode {
|
|
Shallow,
|
|
Complete,
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_clones_shallow_two_revs_same_deps() {
|
|
perform_two_revs_same_deps(true)
|
|
}
|
|
|
|
fn perform_two_revs_same_deps(shallow: bool) {
|
|
let bar = git::new("meta-dep", |project| {
|
|
project
|
|
.file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
|
|
.file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
|
|
});
|
|
|
|
let repo = git2::Repository::open(&bar.root()).unwrap();
|
|
let rev1 = repo.revparse_single("HEAD").unwrap().id();
|
|
|
|
// Commit the changes and make sure we trigger a recompile
|
|
bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
|
|
git::add(&repo);
|
|
let rev2 = git::commit(&repo);
|
|
|
|
let foo = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
authors = []
|
|
|
|
[dependencies.bar]
|
|
git = '{}'
|
|
rev = "{}"
|
|
|
|
[dependencies.baz]
|
|
path = "../baz"
|
|
"#,
|
|
bar.url(),
|
|
rev1
|
|
),
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
extern crate bar;
|
|
extern crate baz;
|
|
|
|
fn main() {
|
|
assert_eq!(bar::bar(), 1);
|
|
assert_eq!(baz::baz(), 2);
|
|
}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
let _baz = project()
|
|
.at("baz")
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "0.0.0"
|
|
authors = []
|
|
|
|
[dependencies.bar]
|
|
git = '{}'
|
|
rev = "{}"
|
|
"#,
|
|
bar.url(),
|
|
rev2
|
|
),
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
extern crate bar;
|
|
pub fn baz() -> i32 { bar::bar() }
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
let args = if shallow {
|
|
"build -v -Zgitoxide=fetch -Zgit=shallow-deps"
|
|
} else {
|
|
"build -v"
|
|
};
|
|
foo.cargo(args)
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
assert!(foo.bin("foo").is_file());
|
|
foo.process(&foo.bin("foo")).run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn two_revs_same_deps() {
|
|
perform_two_revs_same_deps(false)
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_clones_registry_with_shallow_protocol_and_follow_up_with_git2_fetch(
|
|
) -> anyhow::Result<()> {
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let shallow_repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
|
|
assert_eq!(
|
|
shallow_repo
|
|
.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"shallow clones always start at depth of 1 to minimize download size"
|
|
);
|
|
assert!(shallow_repo.is_shallow());
|
|
|
|
Package::new("bar", "1.1.0").publish();
|
|
p.cargo("update")
|
|
.env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0")
|
|
.run();
|
|
|
|
let repo = gix::open_opts(
|
|
find_remote_index(RepoMode::Complete),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
3,
|
|
"an entirely new repo was cloned which is never shallow"
|
|
);
|
|
assert!(!repo.is_shallow());
|
|
Ok(())
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_clones_git_dependency_with_shallow_protocol_and_git2_is_used_for_followup_fetches(
|
|
) -> anyhow::Result<()> {
|
|
// Example where an old lockfile with an explicit branch="master" in Cargo.toml.
|
|
Package::new("bar", "1.0.0").publish();
|
|
let (bar, bar_repo) = git::new_repo("bar", |p| {
|
|
p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
|
|
.file("src/lib.rs", "")
|
|
});
|
|
|
|
bar.change_file("src/lib.rs", "// change");
|
|
git::add(&bar_repo);
|
|
git::commit(&bar_repo);
|
|
|
|
{
|
|
let mut walk = bar_repo.revwalk()?;
|
|
walk.push_head()?;
|
|
assert_eq!(
|
|
walk.count(),
|
|
2,
|
|
"original repo has initial commit and change commit"
|
|
);
|
|
}
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = {{ version = "1.0", git = "{}", branch = "master" }}
|
|
"#,
|
|
bar.url()
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-deps")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let db_clone = gix::open_opts(
|
|
find_bar_db(RepoMode::Shallow),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert!(db_clone.is_shallow());
|
|
assert_eq!(
|
|
db_clone
|
|
.rev_parse_single("origin/master")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"db clones are shallow and have a shortened history"
|
|
);
|
|
|
|
let dep_checkout = gix::open_opts(
|
|
find_lexicographically_first_bar_checkout(),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert!(dep_checkout.is_shallow());
|
|
assert_eq!(
|
|
dep_checkout.head_id()?.ancestors().all()?.count(),
|
|
1,
|
|
"db checkouts are hard-linked clones with the shallow file copied separately."
|
|
);
|
|
|
|
bar.change_file("src/lib.rs", "// another change");
|
|
git::add(&bar_repo);
|
|
git::commit(&bar_repo);
|
|
{
|
|
let mut walk = bar_repo.revwalk()?;
|
|
walk.push_head()?;
|
|
assert_eq!(
|
|
walk.count(),
|
|
3,
|
|
"original repo has initial commit and change commit, and another change"
|
|
);
|
|
}
|
|
|
|
p.cargo("update")
|
|
.env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0")
|
|
.run();
|
|
|
|
let db_clone = gix::open_opts(
|
|
find_bar_db(RepoMode::Complete),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert_eq!(
|
|
db_clone
|
|
.rev_parse_single("origin/master")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
3,
|
|
"the db clone was re-initialized and has all commits"
|
|
);
|
|
assert!(
|
|
!db_clone.is_shallow(),
|
|
"shallow-ness was removed as git2 does not support it"
|
|
);
|
|
assert_eq!(
|
|
dep_checkout.head_id()?.ancestors().all()?.count(),
|
|
1,
|
|
"the original dep checkout didn't change - there is a new one for each update we get locally"
|
|
);
|
|
|
|
let max_history_depth = glob::glob(
|
|
paths::home()
|
|
.join(".cargo/git/checkouts/bar-*/*/.git")
|
|
.to_str()
|
|
.unwrap(),
|
|
)?
|
|
.map(|path| -> anyhow::Result<usize> {
|
|
let dep_checkout = gix::open_opts(path?, gix::open::Options::isolated())?;
|
|
let depth = dep_checkout.head_id()?.ancestors().all()?.count();
|
|
assert_eq!(dep_checkout.is_shallow(), depth == 1, "the first checkout is done with gitoxide and shallow, the second one is git2 non-shallow");
|
|
Ok(depth)
|
|
})
|
|
.map(Result::unwrap)
|
|
.max()
|
|
.expect("two checkout repos");
|
|
|
|
assert_eq!(
|
|
max_history_depth, 3,
|
|
"the new checkout sees all commits of the non-shallow DB repository"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_shallow_clone_followed_by_non_shallow_update() -> anyhow::Result<()> {
|
|
Package::new("bar", "1.0.0").publish();
|
|
let (bar, bar_repo) = git::new_repo("bar", |p| {
|
|
p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
|
|
.file("src/lib.rs", "")
|
|
});
|
|
|
|
bar.change_file("src/lib.rs", "// change");
|
|
git::add(&bar_repo);
|
|
git::commit(&bar_repo);
|
|
|
|
{
|
|
let mut walk = bar_repo.revwalk()?;
|
|
walk.push_head()?;
|
|
assert_eq!(
|
|
walk.count(),
|
|
2,
|
|
"original repo has initial commit and change commit"
|
|
);
|
|
}
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = {{ version = "1.0", git = "{}", branch = "master" }}
|
|
"#,
|
|
bar.url()
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-deps")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let shallow_db_clone = gix::open_opts(
|
|
find_bar_db(RepoMode::Shallow),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert!(shallow_db_clone.is_shallow());
|
|
assert_eq!(
|
|
shallow_db_clone
|
|
.rev_parse_single("origin/master")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"db clones are shallow and have a shortened history"
|
|
);
|
|
|
|
let dep_checkout = gix::open_opts(
|
|
find_lexicographically_first_bar_checkout(),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert!(dep_checkout.is_shallow());
|
|
assert_eq!(
|
|
dep_checkout.head_id()?.ancestors().all()?.count(),
|
|
1,
|
|
"db checkouts are hard-linked clones with the shallow file copied separately."
|
|
);
|
|
|
|
bar.change_file("src/lib.rs", "// another change");
|
|
git::add(&bar_repo);
|
|
git::commit(&bar_repo);
|
|
{
|
|
let mut walk = bar_repo.revwalk()?;
|
|
walk.push_head()?;
|
|
assert_eq!(
|
|
walk.count(),
|
|
3,
|
|
"original repo has initial commit and change commit, and another change"
|
|
);
|
|
}
|
|
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch") // shallow-deps is omitted intentionally
|
|
.masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
|
|
.run();
|
|
|
|
let db_clone = gix::open_opts(
|
|
find_bar_db(RepoMode::Complete),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert_eq!(
|
|
db_clone
|
|
.rev_parse_single("origin/master")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
3,
|
|
"we created an entirely new non-shallow clone"
|
|
);
|
|
assert!(!db_clone.is_shallow());
|
|
assert_eq!(
|
|
dep_checkout.head_id()?.ancestors().all()?.count(),
|
|
1,
|
|
"the original dep checkout didn't change - there is a new one for each update we get locally"
|
|
);
|
|
|
|
let max_history_depth = glob::glob(
|
|
paths::home()
|
|
.join(".cargo/git/checkouts/bar-*/*/.git")
|
|
.to_str()
|
|
.unwrap(),
|
|
)?
|
|
.map(|path| -> anyhow::Result<usize> {
|
|
let path = path?;
|
|
let dep_checkout = gix::open_opts(&path, gix::open::Options::isolated())?;
|
|
assert_eq!(
|
|
dep_checkout.is_shallow(),
|
|
path.to_string_lossy().contains("-shallow"),
|
|
"checkouts of shallow db repos are shallow as well"
|
|
);
|
|
let depth = dep_checkout.head_id()?.ancestors().all()?.count();
|
|
Ok(depth)
|
|
})
|
|
.map(Result::unwrap)
|
|
.max()
|
|
.expect("two checkout repos");
|
|
|
|
assert_eq!(
|
|
max_history_depth, 3,
|
|
"we see the previous shallow checkout as well as new new unshallow one"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_clones_registry_with_shallow_protocol_and_follow_up_fetch_maintains_shallowness(
|
|
) -> anyhow::Result<()> {
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"shallow clones always start at depth of 1 to minimize download size"
|
|
);
|
|
assert!(repo.is_shallow());
|
|
|
|
Package::new("bar", "1.1.0").publish();
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index") // NOTE: the flag needs to be consistent or else a different index is created
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits"
|
|
);
|
|
assert!(repo.is_shallow());
|
|
|
|
Package::new("bar", "1.2.0").publish();
|
|
Package::new("bar", "1.3.0").publish();
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"shallow boundaries are moved with each fetch to maintain only a single commit of history"
|
|
);
|
|
assert!(repo.is_shallow());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// If there is shallow *and* non-shallow clones, non-shallow will naturally be returned due to sort order.
|
|
#[cargo_test]
|
|
fn gitoxide_clones_registry_without_shallow_protocol_and_follow_up_fetch_uses_shallowness(
|
|
) -> anyhow::Result<()> {
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.arg("-Zgitoxide=fetch")
|
|
.masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
|
|
.run();
|
|
|
|
let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
2,
|
|
"initial commit and the first crate"
|
|
);
|
|
assert!(!repo.is_shallow());
|
|
|
|
Package::new("bar", "1.1.0").publish();
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let shallow_repo = gix::open_opts(
|
|
find_remote_index(RepoMode::Shallow),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert_eq!(
|
|
shallow_repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"the follow up clones an entirely new index which is now shallow and which is in its own location"
|
|
);
|
|
assert!(shallow_repo.is_shallow());
|
|
|
|
Package::new("bar", "1.2.0").publish();
|
|
Package::new("bar", "1.3.0").publish();
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
assert_eq!(
|
|
shallow_repo
|
|
.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits"
|
|
);
|
|
assert!(shallow_repo.is_shallow());
|
|
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
|
|
.run();
|
|
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
5,
|
|
"we can separately fetch the non-shallow index as well and it sees all commits"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_git_dependencies_switch_from_branch_to_rev() -> anyhow::Result<()> {
|
|
// db exists from previous build, then dependency changes to refer to revision that isn't
|
|
// available in the shallow clone.
|
|
|
|
let (bar, bar_repo) = git::new_repo("bar", |p| {
|
|
p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
|
|
.file("src/lib.rs", "")
|
|
});
|
|
|
|
// this commit would not be available in a shallow clone.
|
|
let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap();
|
|
|
|
bar.change_file("src/lib.rs", "// change");
|
|
git::add(&bar_repo);
|
|
git::commit(&bar_repo);
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = {{ git = "{}", branch = "master" }}
|
|
"#,
|
|
bar.url(),
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-deps")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let db_clone = gix::open_opts(
|
|
find_bar_db(RepoMode::Shallow),
|
|
gix::open::Options::isolated(),
|
|
)?;
|
|
assert!(db_clone.is_shallow());
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = {{ git = "{}", rev = "{}" }}
|
|
"#,
|
|
bar.url(),
|
|
first_commit_pre_change
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-deps")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
assert!(
|
|
db_clone.is_shallow(),
|
|
"we maintain shallowness and never unshallow"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn shallow_deps_work_with_revisions_and_branches_mixed_on_same_dependency() -> anyhow::Result<()> {
|
|
let (bar, bar_repo) = git::new_repo("bar", |p| {
|
|
p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
|
|
.file("src/lib.rs", "")
|
|
});
|
|
|
|
// this commit would not be available in a shallow clone.
|
|
let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap();
|
|
|
|
bar.change_file("src/lib.rs", "// change");
|
|
git::add(&bar_repo);
|
|
git::commit(&bar_repo);
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar-renamed = {{ package = "bar", git = "{}", rev = "{}" }}
|
|
bar = {{ git = "{}", branch = "master" }}
|
|
"#,
|
|
bar.url(),
|
|
first_commit_pre_change,
|
|
bar.url(),
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-deps")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let db_paths = glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap())?
|
|
.map(Result::unwrap)
|
|
.collect::<Vec<_>>();
|
|
assert_eq!(
|
|
db_paths.len(),
|
|
1,
|
|
"only one db checkout source is used per dependency"
|
|
);
|
|
let db_clone = gix::open_opts(&db_paths[0], gix::open::Options::isolated())?;
|
|
assert!(
|
|
db_clone.is_shallow(),
|
|
"the repo is shallow while having all data it needs"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn gitoxide_clones_registry_with_shallow_protocol_and_aborts_and_updates_again(
|
|
) -> anyhow::Result<()> {
|
|
Package::new("bar", "1.0.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("fetch")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"shallow clones always start at depth of 1 to minimize download size"
|
|
);
|
|
assert!(repo.is_shallow());
|
|
let shallow_lock = repo.shallow_file().with_extension("lock");
|
|
// adding a lock file and deleting the original simulates a left-over clone that was aborted, leaving a lock file
|
|
// in place without ever having moved it to the right location.
|
|
std::fs::write(&shallow_lock, &[])?;
|
|
std::fs::remove_file(repo.shallow_file())?;
|
|
|
|
Package::new("bar", "1.1.0").publish();
|
|
p.cargo("update")
|
|
.arg("-Zgitoxide=fetch")
|
|
.arg("-Zgit=shallow-index")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
])
|
|
.run();
|
|
|
|
assert!(!shallow_lock.is_file(), "the repository was re-initialized");
|
|
assert!(repo.is_shallow());
|
|
assert_eq!(
|
|
repo.rev_parse_single("origin/HEAD")?
|
|
.ancestors()
|
|
.all()?
|
|
.count(),
|
|
1,
|
|
"it's a fresh shallow clone - otherwise it would have 2 commits if the previous shallow clone would still be present"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn find_lexicographically_first_bar_checkout() -> std::path::PathBuf {
|
|
glob::glob(
|
|
paths::home()
|
|
.join(".cargo/git/checkouts/bar-*/*/.git")
|
|
.to_str()
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
.next()
|
|
.unwrap()
|
|
.unwrap()
|
|
.to_owned()
|
|
}
|
|
|
|
fn find_remote_index(mode: RepoMode) -> std::path::PathBuf {
|
|
glob::glob(
|
|
paths::home()
|
|
.join(".cargo/registry/index/*")
|
|
.to_str()
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
.map(Result::unwrap)
|
|
.filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow))
|
|
.next()
|
|
.unwrap()
|
|
}
|
|
|
|
/// Find a checkout directory for bar, `shallow` or not.
|
|
fn find_bar_db(mode: RepoMode) -> std::path::PathBuf {
|
|
glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap())
|
|
.unwrap()
|
|
.map(Result::unwrap)
|
|
.filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow))
|
|
.next()
|
|
.unwrap()
|
|
.to_owned()
|
|
}
|