summaryrefslogtreecommitdiffstats
path: root/src/tools/cargo/tests/testsuite/git_gc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/cargo/tests/testsuite/git_gc.rs')
-rw-r--r--src/tools/cargo/tests/testsuite/git_gc.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/tools/cargo/tests/testsuite/git_gc.rs b/src/tools/cargo/tests/testsuite/git_gc.rs
new file mode 100644
index 000000000..fd4fe30a9
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/git_gc.rs
@@ -0,0 +1,117 @@
+//! 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()));
+}