cargo/tests/testsuite/git_gc.rs
2024-06-17 19:59:18 +08:00

117 lines
3.1 KiB
Rust

//! Tests for git garbage collection.
use std::env;
use std::ffi::OsStr;
use std::path::PathBuf;
use cargo_test_support::git;
use cargo_test_support::git::cargo_uses_gitoxide;
use cargo_test_support::paths;
use cargo_test_support::project;
use cargo_test_support::registry::Package;
use url::Url;
pub fn find_index() -> PathBuf {
let dir = paths::home().join(".cargo/registry/index");
dir.read_dir().unwrap().next().unwrap().unwrap().path()
}
fn run_test(path_env: Option<&OsStr>) {
const N: usize = 50;
let foo = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "*"
"#,
)
.file("src/lib.rs", "")
.build();
Package::new("bar", "0.1.0").publish();
foo.cargo("check").run();
let index = find_index();
let path = paths::home().join("tmp");
let url = Url::from_file_path(&path).unwrap().to_string();
let repo = git2::Repository::init(&path).unwrap();
let index = git2::Repository::open(&index).unwrap();
let mut cfg = repo.config().unwrap();
cfg.set_str("user.email", "foo@bar.com").unwrap();
cfg.set_str("user.name", "Foo Bar").unwrap();
let mut cfg = index.config().unwrap();
cfg.set_str("user.email", "foo@bar.com").unwrap();
cfg.set_str("user.name", "Foo Bar").unwrap();
for _ in 0..N {
git::commit(&repo);
index
.remote_anonymous(&url)
.unwrap()
.fetch(&["refs/heads/master:refs/remotes/foo/master"], None, None)
.unwrap();
}
drop((repo, index));
Package::new("bar", "0.1.1").publish();
let before = find_index()
.join(".git/objects/pack")
.read_dir()
.unwrap()
.count();
assert!(before > N);
let mut cmd = foo.cargo("update");
cmd.env("__CARGO_PACKFILE_LIMIT", "10");
if let Some(path) = path_env {
cmd.env("PATH", path);
}
cmd.env("CARGO_LOG", "trace");
cmd.run();
let after = find_index()
.join(".git/objects/pack")
.read_dir()
.unwrap()
.count();
assert!(
after < before,
"packfiles before: {}\n\
packfiles after: {}",
before,
after
);
}
#[cargo_test(requires_git)]
fn use_git_gc() {
run_test(None);
}
#[cargo_test]
fn avoid_using_git() {
if cargo_uses_gitoxide() {
// file protocol without git binary is currently not possible - needs built-in upload-pack.
// See https://github.com/Byron/gitoxide/issues/734 (support for the file protocol) progress updates.
return;
}
let path = env::var_os("PATH").unwrap_or_default();
let mut paths = env::split_paths(&path).collect::<Vec<_>>();
let idx = paths
.iter()
.position(|p| p.join("git").exists() || p.join("git.exe").exists());
match idx {
Some(i) => {
paths.remove(i);
}
None => return,
}
run_test(Some(&env::join_paths(&paths).unwrap()));
}