summaryrefslogtreecommitdiffstats
path: root/src/tools/cargo/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/cargo/tests')
-rw-r--r--src/tools/cargo/tests/build-std/main.rs45
-rw-r--r--src/tools/cargo/tests/testsuite/alt_registry.rs92
-rw-r--r--src/tools/cargo/tests/testsuite/artifact_dep.rs7
-rw-r--r--src/tools/cargo/tests/testsuite/build.rs236
-rw-r--r--src/tools/cargo/tests/testsuite/build_script.rs13
-rw-r--r--src/tools/cargo/tests/testsuite/build_script_env.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/Cargo.toml5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/Cargo.toml4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/Cargo.toml5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/dependency/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/primary/Cargo.toml7
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stdout.log0
l---------src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/in1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/mod.rs24
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/out/Cargo.toml5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log17
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/mod.rs9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_optional/mod.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_optional/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_optional/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_public/in/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_public/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_public/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_public/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/no_public/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/optional/mod.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/optional/out/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/optional/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/in/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/in/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/mod.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/Cargo.toml1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/out/Cargo.toml1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/Cargo.toml11
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/out/Cargo.toml11
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_noop/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_with_version/out/primary/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_git/out/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_path/out/primary/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/public/in/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/public/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/public/mod.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/public/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/public/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/public/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_config/help/stdout.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_features.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_help/help/stdout.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_locate_project/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_logout/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_metadata/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/empty_name/in/.keep0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/empty_name/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/empty_name/out/.keep0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/empty_name/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/empty_name/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/mod.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_pkgid/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/in/Cargo.lock4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/out/Cargo.lock4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_report/help/stdout.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_uninstall/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_vendor/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_verify_project/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_version/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/check.rs49
-rw-r--r--src/tools/cargo/tests/testsuite/check_cfg.rs85
-rw-r--r--src/tools/cargo/tests/testsuite/clean.rs55
-rw-r--r--src/tools/cargo/tests/testsuite/config.rs6
-rw-r--r--src/tools/cargo/tests/testsuite/custom_target.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/doc.rs19
-rw-r--r--src/tools/cargo/tests/testsuite/docscrape.rs78
-rw-r--r--src/tools/cargo/tests/testsuite/features.rs37
-rw-r--r--src/tools/cargo/tests/testsuite/features_namespaced.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/fetch.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/fix.rs164
-rw-r--r--src/tools/cargo/tests/testsuite/freshness.rs8
-rw-r--r--src/tools/cargo/tests/testsuite/generate_lockfile.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/git.rs31
-rw-r--r--src/tools/cargo/tests/testsuite/git_auth.rs10
-rw-r--r--src/tools/cargo/tests/testsuite/global_cache_tracker.rs1862
-rw-r--r--src/tools/cargo/tests/testsuite/install.rs122
-rw-r--r--src/tools/cargo/tests/testsuite/main.rs7
-rw-r--r--src/tools/cargo/tests/testsuite/messages.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/metabuild.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/package.rs239
-rw-r--r--src/tools/cargo/tests/testsuite/patch.rs83
-rw-r--r--src/tools/cargo/tests/testsuite/path.rs11
-rw-r--r--src/tools/cargo/tests/testsuite/pkgid.rs98
-rw-r--r--src/tools/cargo/tests/testsuite/profile_config.rs6
-rw-r--r--src/tools/cargo/tests/testsuite/profile_custom.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/profile_trim_paths.rs267
-rw-r--r--src/tools/cargo/tests/testsuite/pub_priv.rs235
-rw-r--r--src/tools/cargo/tests/testsuite/publish_lockfile.rs12
-rw-r--r--src/tools/cargo/tests/testsuite/registry.rs23
-rw-r--r--src/tools/cargo/tests/testsuite/replace.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/rust_version.rs81
-rw-r--r--src/tools/cargo/tests/testsuite/rustflags.rs6
-rw-r--r--src/tools/cargo/tests/testsuite/test.rs37
-rw-r--r--src/tools/cargo/tests/testsuite/update.rs94
-rw-r--r--src/tools/cargo/tests/testsuite/workspaces.rs1
180 files changed, 4487 insertions, 397 deletions
diff --git a/src/tools/cargo/tests/build-std/main.rs b/src/tools/cargo/tests/build-std/main.rs
index 47a4bb671..c905deb49 100644
--- a/src/tools/cargo/tests/build-std/main.rs
+++ b/src/tools/cargo/tests/build-std/main.rs
@@ -18,6 +18,8 @@
//! `CARGO_RUN_BUILD_STD_TESTS` env var to be set to actually run these tests.
//! Otherwise the tests are skipped.
+#![allow(clippy::disallowed_methods)]
+
use cargo_test_support::*;
use std::env;
use std::path::Path;
@@ -227,3 +229,46 @@ fn custom_test_framework() {
.build_std_arg("core")
.run();
}
+
+// Fixing rust-lang/rust#117839.
+// on macOS it never gets remapped.
+// Might be a separate issue, so only run on Linux.
+#[cargo_test(build_std_real)]
+#[cfg(target_os = "linux")]
+fn remap_path_scope() {
+ let p = project()
+ .file(
+ "src/main.rs",
+ "
+ fn main() {
+ panic!(\"remap to /rustc/<hash>\");
+ }
+ ",
+ )
+ .file(
+ ".cargo/config.toml",
+ "
+ [profile.release]
+ debug = \"line-tables-only\"
+ ",
+ )
+ .build();
+
+ p.cargo("run --release -Ztrim-paths")
+ .masquerade_as_nightly_cargo(&["-Ztrim-paths"])
+ .env("RUST_BACKTRACE", "1")
+ .build_std()
+ .target_host()
+ .with_status(101)
+ .with_stderr_contains(
+ "\
+[FINISHED] release [optimized + debuginfo] [..]
+[RUNNING] [..]
+[..]thread '[..]' panicked at [..]src/main.rs:3:[..]",
+ )
+ .with_stderr_contains("remap to /rustc/<hash>")
+ .with_stderr_contains("[..]at /rustc/[..]/library/std/src/[..]")
+ .with_stderr_contains("[..]at src/main.rs:3[..]")
+ .with_stderr_contains("[..]at /rustc/[..]/library/core/src/[..]")
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/alt_registry.rs b/src/tools/cargo/tests/testsuite/alt_registry.rs
index d6d7dd531..e347af1c7 100644
--- a/src/tools/cargo/tests/testsuite/alt_registry.rs
+++ b/src/tools/cargo/tests/testsuite/alt_registry.rs
@@ -715,7 +715,14 @@ fn bad_registry_name() {
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
- invalid character ` ` in registry name: `bad name`, [..]",
+ TOML parse error at line 7, column 17
+ |
+ 7 | [dependencies.bar]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ invalid character ` ` in registry name: `bad name`, [..]
+
+
+",
)
.run();
@@ -1546,3 +1553,86 @@ or use environment variable CARGO_REGISTRY_TOKEN",
)
.run();
}
+
+#[cargo_test]
+fn config_empty_registry_name() {
+ let _ = RegistryBuilder::new()
+ .no_configure_token()
+ .alternative()
+ .build();
+ let p = project()
+ .file("src/lib.rs", "")
+ .file(
+ ".cargo/config.toml",
+ "[registry.'']
+ ",
+ )
+ .build();
+
+ p.cargo("publish")
+ .arg("--registry")
+ .arg("")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] registry name cannot be empty",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn empty_registry_flag() {
+ let p = project().file("src/lib.rs", "").build();
+
+ p.cargo("publish")
+ .arg("--registry")
+ .arg("")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] registry name cannot be empty",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn empty_dependency_registry() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ bar = { version = "0.1.0", registry = "" }
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+ extern crate bar;
+ pub fn f() { bar::bar(); }
+ ",
+ )
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
+
+Caused by:
+ TOML parse error at line 7, column 23
+ |
+ 7 | bar = { version = \"0.1.0\", registry = \"\" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ registry name cannot be empty
+
+
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/artifact_dep.rs b/src/tools/cargo/tests/testsuite/artifact_dep.rs
index c51298735..01b4ecf47 100644
--- a/src/tools/cargo/tests/testsuite/artifact_dep.rs
+++ b/src/tools/cargo/tests/testsuite/artifact_dep.rs
@@ -2167,8 +2167,11 @@ fn doc_lib_true() {
p.cargo("doc -Z bindeps")
.masquerade_as_nightly_cargo(&["bindeps"])
- .env("CARGO_LOG", "cargo::ops::cargo_rustc::fingerprint")
- .with_stdout("")
+ .with_stderr(
+ "\
+[FINISHED] [..]
+[GENERATED] [CWD]/target/doc/foo/index.html",
+ )
.run();
assert!(p.root().join("target/doc").is_dir());
diff --git a/src/tools/cargo/tests/testsuite/build.rs b/src/tools/cargo/tests/testsuite/build.rs
index 23840ad9a..dd67161d6 100644
--- a/src/tools/cargo/tests/testsuite/build.rs
+++ b/src/tools/cargo/tests/testsuite/build.rs
@@ -460,7 +460,11 @@ fn cargo_compile_with_empty_package_name() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
- package name cannot be an empty string
+ TOML parse error at line 3, column 16
+ |
+ 3 | name = \"\"
+ | ^^
+ package name cannot be empty
",
)
.run();
@@ -479,6 +483,10 @@ fn cargo_compile_with_invalid_package_name() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
+ TOML parse error at line 3, column 16
+ |
+ 3 | name = \"foo::bar\"
+ | ^^^^^^^^^^
invalid character `:` in package name: `foo::bar`, [..]
",
)
@@ -760,7 +768,7 @@ fn cargo_compile_with_invalid_code() {
p.cargo("build")
.with_status(101)
.with_stderr_contains(
- "[ERROR] could not compile `foo` (bin \"foo\") due to previous error\n",
+ "[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n",
)
.run();
assert!(p.root().join("Cargo.lock").is_file());
@@ -1182,7 +1190,11 @@ fn cargo_compile_with_invalid_dep_rename() {
error: failed to parse manifest at `[..]`
Caused by:
- invalid character ` ` in dependency name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
+ TOML parse error at line 7, column 17
+ |
+ 7 | \"haha this isn't a valid name 🐛\" = { package = \"libc\", version = \"0.1\" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
",
)
.run();
@@ -1545,6 +1557,11 @@ fn crate_env_vars() {
// Verify CARGO_TARGET_TMPDIR isn't set for bins
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
+
+ // Verify CARGO_RUSTC_CURRENT_DIR is set for examples
+ let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
}
"#,
)
@@ -1581,14 +1598,26 @@ fn crate_env_vars() {
// Check that CARGO_TARGET_TMPDIR isn't set for lib code
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
env::var("CARGO_TARGET_TMPDIR").unwrap_err();
+
+ // Verify CARGO_RUSTC_CURRENT_DIR is set for examples
+ let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
}
#[test]
- fn env() {
+ fn unit_env_cargo_target_tmpdir() {
// Check that CARGO_TARGET_TMPDIR isn't set for unit tests
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
env::var("CARGO_TARGET_TMPDIR").unwrap_err();
}
+
+ #[test]
+ fn unit_env_cargo_rustc_current_dir() {
+ let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
+ }
"#,
)
.file(
@@ -1605,6 +1634,11 @@ fn crate_env_vars() {
// Verify CARGO_TARGET_TMPDIR isn't set for examples
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
+
+ // Verify CARGO_RUSTC_CURRENT_DIR is set for examples
+ let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
}
"#,
)
@@ -1612,9 +1646,16 @@ fn crate_env_vars() {
"tests/env.rs",
r#"
#[test]
- fn env() {
+ fn integration_env_cargo_target_tmpdir() {
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
}
+
+ #[test]
+ fn integration_env_cargo_rustc_current_dir() {
+ let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
+ }
"#,
);
@@ -1627,9 +1668,16 @@ fn crate_env_vars() {
use test::Bencher;
#[bench]
- fn env(_: &mut Bencher) {
+ fn bench_env_cargo_target_tmpdir(_: &mut Bencher) {
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
}
+
+ #[test]
+ fn bench_env_cargo_rustc_current_dir() {
+ let workspace_dir = std::path::Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
+ }
"#,
)
.build()
@@ -1638,7 +1686,9 @@ fn crate_env_vars() {
};
println!("build");
- p.cargo("build -v").run();
+ p.cargo("build -v")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .run();
println!("bin");
p.process(&p.bin("foo-bar"))
@@ -1646,15 +1696,175 @@ fn crate_env_vars() {
.run();
println!("example");
- p.cargo("run --example ex-env-vars -v").run();
+ p.cargo("run --example ex-env-vars -v")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .run();
println!("test");
- p.cargo("test -v").run();
+ p.cargo("test -v")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .run();
if is_nightly() {
println!("bench");
- p.cargo("bench -v").run();
+ p.cargo("bench -v")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .run();
+ }
+}
+
+#[cargo_test]
+fn cargo_rustc_current_dir_foreign_workspace_dep() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ baz.path = "../baz"
+ baz_member.path = "../baz/baz_member"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ let _baz = project()
+ .at("baz")
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["baz_member"]
+
+ [package]
+ name = "baz"
+ version = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "tests/env.rs",
+ r#"
+ use std::path::Path;
+
+ #[test]
+ fn baz_env() {
+ let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let manifest_dir = Path::new(option_env!("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
+ let current_dir = std::env::current_dir().expect("current_dir");
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
+ let workspace_dir = std::fs::canonicalize(current_dir.join(workspace_dir)).expect("CARGO_RUSTC_CURRENT_DIR");
+ let manifest_dir = std::fs::canonicalize(current_dir.join(manifest_dir)).expect("CARGO_MANIFEST_DIR");
+ assert_eq!(workspace_dir, manifest_dir);
+ }
+ "#,
+ )
+ .file(
+ "baz_member/Cargo.toml",
+ r#"
+ [package]
+ name = "baz_member"
+ version = "0.1.0"
+ authors = []
+ "#,
+ )
+ .file("baz_member/src/lib.rs", "")
+ .file(
+ "baz_member/tests/env.rs",
+ r#"
+ use std::path::Path;
+
+ #[test]
+ fn baz_member_env() {
+ let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
+ }
+ "#,
+ )
+ .build();
+
+ // Verify it works from a different workspace
+ foo.cargo("test -p baz")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .with_stdout_contains("running 1 test\ntest baz_env ... ok")
+ .run();
+ foo.cargo("test -p baz_member")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .with_stdout_contains("running 1 test\ntest baz_member_env ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_rustc_current_dir_non_local_dep() {
+ Package::new("bar", "0.1.0")
+ .file(
+ "tests/bar_env.rs",
+ r#"
+ use std::path::Path;
+
+ #[test]
+ fn bar_env() {
+ let workspace_dir = Path::new(option_env!("CARGO_RUSTC_CURRENT_DIR").expect("CARGO_RUSTC_CURRENT_DIR"));
+ let manifest_dir = Path::new(option_env!("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
+ let current_dir = std::env::current_dir().expect("current_dir");
+ let file_path = workspace_dir.join(file!());
+ assert!(file_path.exists(), "{}", file_path.display());
+ let workspace_dir = std::fs::canonicalize(current_dir.join(workspace_dir)).expect("CARGO_RUSTC_CURRENT_DIR");
+ let manifest_dir = std::fs::canonicalize(current_dir.join(manifest_dir)).expect("CARGO_MANIFEST_DIR");
+ assert_eq!(workspace_dir, manifest_dir);
+ }
+ "#,
+ )
+ .publish();
+
+ let p = project()
+ .file("src/lib.rs", "")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .build();
+
+ p.cargo("test -p bar")
+ .masquerade_as_nightly_cargo(&["CARGO_RUSTC_CURRENT_DIR"])
+ .with_stdout_contains("running 1 test\ntest bar_env ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_rustc_current_dir_is_not_stable() {
+ if is_nightly() {
+ return;
}
+ let p = project()
+ .file(
+ "tests/env.rs",
+ r#"
+ use std::path::Path;
+
+ #[test]
+ fn env() {
+ assert_eq!(option_env!("CARGO_RUSTC_CURRENT_DIR"), None);
+ }
+ "#,
+ )
+ .build();
+
+ p.cargo("test").run();
}
#[cargo_test]
@@ -2959,12 +3169,12 @@ fn freshness_ignores_excluded() {
// Smoke test to make sure it doesn't compile again
println!("first pass");
- foo.cargo("build").with_stdout("").run();
+ foo.cargo("build").with_stderr("[FINISHED] [..]").run();
// Modify an ignored file and make sure we don't rebuild
println!("second pass");
foo.change_file("src/bar.rs", "");
- foo.cargo("build").with_stdout("").run();
+ foo.cargo("build").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -3064,7 +3274,7 @@ fn recompile_space_in_name() {
.build();
foo.cargo("build").run();
foo.root().move_into_the_past();
- foo.cargo("build").with_stdout("").run();
+ foo.cargo("build").with_stderr("[FINISHED] [..]").run();
}
#[cfg(unix)]
diff --git a/src/tools/cargo/tests/testsuite/build_script.rs b/src/tools/cargo/tests/testsuite/build_script.rs
index 408ce6457..f7361fcf3 100644
--- a/src/tools/cargo/tests/testsuite/build_script.rs
+++ b/src/tools/cargo/tests/testsuite/build_script.rs
@@ -1028,7 +1028,7 @@ versions that meet the requirements `*` are: 0.5.0
the package `a-sys` links to the native library `a`, but it conflicts with a previous package which links to `a` as well:
package `foo v0.5.0 ([..])`
-Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='a-sys' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.
+Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = \"a\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.
failed to select a version for `a-sys` which could resolve this conflict
").run();
@@ -1148,7 +1148,7 @@ versions that meet the requirements `*` are: 0.5.0
the package `a-sys` links to the native library `a`, but it conflicts with a previous package which links to `a` as well:
package `foo v0.5.0 ([..])`
-Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='a-sys' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.
+Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = \"a\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.
failed to select a version for `a-sys` which could resolve this conflict
").run();
@@ -1716,7 +1716,7 @@ fn build_deps_not_for_normal() {
.with_stderr_contains("[..]can't find crate for `aaaaa`[..]")
.with_stderr_contains(
"\
-[ERROR] could not compile `foo` (lib) due to previous error
+[ERROR] could not compile `foo` (lib) due to 1 previous error
Caused by:
process didn't exit successfully: [..]
@@ -3245,7 +3245,6 @@ fn fresh_builds_possible_with_multiple_metadata_overrides() {
.run();
p.cargo("build -v")
- .env("CARGO_LOG", "cargo::ops::cargo_rustc::fingerprint=info")
.with_stderr(
"\
[FRESH] foo v0.5.0 ([..])
@@ -3472,7 +3471,7 @@ fn rebuild_only_on_explicit_paths() {
// random other files do not affect freshness
println!("run baz");
- p.change_file("baz", "");
+ p.change_file("baz", "// modified");
p.cargo("build -v")
.with_stderr(
"\
@@ -3484,7 +3483,7 @@ fn rebuild_only_on_explicit_paths() {
// but changing dependent files does
println!("run foo change");
- p.change_file("foo", "");
+ p.change_file("foo", "// modified");
p.cargo("build -v")
.with_stderr(
"\
@@ -4382,7 +4381,7 @@ versions that meet the requirements `*` are: 0.5.0
the package `a` links to the native library `a`, but it conflicts with a previous package which links to `a` as well:
package `foo v0.5.0 ([..])`
-Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='a' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.
+Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = \"a\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.
failed to select a version for `a` which could resolve this conflict
").run();
diff --git a/src/tools/cargo/tests/testsuite/build_script_env.rs b/src/tools/cargo/tests/testsuite/build_script_env.rs
index afa2925f1..5220506a7 100644
--- a/src/tools/cargo/tests/testsuite/build_script_env.rs
+++ b/src/tools/cargo/tests/testsuite/build_script_env.rs
@@ -96,7 +96,7 @@ fn rerun_if_env_or_file_changes() {
.with_stderr("[FINISHED] [..]")
.run();
sleep_ms(1000);
- p.change_file("foo", "");
+ p.change_file("foo", "// modified");
p.cargo("check")
.env("FOO", "bar")
.with_stderr(
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml
index 70cd31826..bc29fac8e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml
@@ -6,3 +6,6 @@ version = "0.0.0"
[dependencies]
some-package = { package = "my-package2", version = "99999.0.0", optional = true }
+
+[features]
+some-package = ["dep:some-package"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml
index 6dd7fb6d6..38ff36eb3 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml
@@ -4,3 +4,6 @@ version = "0.0.0"
[dependencies]
foo = { workspace = true, optional = true }
+
+[features]
+foo = ["dep:foo"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/Cargo.toml
new file mode 100644
index 000000000..24c50556b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+members = ["primary", "dependency"]
+
+[workspace.dependencies]
+foo = { version = "0.0.0", path = "./dependency"} \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/Cargo.toml
new file mode 100644
index 000000000..2d247d4d2
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/Cargo.toml
@@ -0,0 +1,3 @@
+[package]
+name = "foo"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/Cargo.toml
new file mode 100644
index 000000000..b5923a106
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/Cargo.toml
@@ -0,0 +1,4 @@
+cargo-features = ["public-dependency"]
+[package]
+name = "bar"
+version = "0.0.0" \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs
new file mode 100644
index 000000000..680d4c4e3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .args(["foo", "-p", "bar", "--public"])
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/Cargo.toml
new file mode 100644
index 000000000..24c50556b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+members = ["primary", "dependency"]
+
+[workspace.dependencies]
+foo = { version = "0.0.0", path = "./dependency"} \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/dependency/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/dependency/Cargo.toml
new file mode 100644
index 000000000..2d247d4d2
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/dependency/Cargo.toml
@@ -0,0 +1,3 @@
+[package]
+name = "foo"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/primary/Cargo.toml
new file mode 100644
index 000000000..665c6ae5e
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/out/primary/Cargo.toml
@@ -0,0 +1,7 @@
+cargo-features = ["public-dependency"]
+[package]
+name = "bar"
+version = "0.0.0"
+
+[dependencies]
+foo = { workspace = true, public = true }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.log
new file mode 100644
index 000000000..efa1ae9fa
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.log
@@ -0,0 +1 @@
+ Adding foo (workspace) to public dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/detect_workspace_inherit_public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/in b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/in
new file mode 120000
index 000000000..6c6a27fcf
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/in
@@ -0,0 +1 @@
+../add-basic.in \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/mod.rs
new file mode 100644
index 000000000..d7044ee11
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/mod.rs
@@ -0,0 +1,24 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("@1.2.3")
+ .current_dir(cwd)
+ .assert()
+ .failure()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/out/Cargo.toml
new file mode 100644
index 000000000..3ecdb6681
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/out/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stderr.log
new file mode 100644
index 000000000..d9547a42a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stderr.log
@@ -0,0 +1 @@
+error: package name cannot be empty
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_name/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log
index cf2a91313..d2931ae9c 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log
@@ -32,6 +32,17 @@ Options:
The package will be removed from your features.
+ --public
+ Mark the dependency as public
+
+ The dependency can be referenced in your library's public API.
+
+ --no-public
+ Mark the dependency as private
+
+ While you can use the crate in your implementation, it cannot be referenced in your public
+ API.
+
--rename <NAME>
Rename the dependency
@@ -45,12 +56,12 @@ Options:
-n, --dry-run
Don't actually write the manifest
- -q, --quiet
- Do not print cargo log messages
-
-v, --verbose...
Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet
+ Do not print cargo log messages
+
--color <WHEN>
Coloring: auto, always, never
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
index e8633b0c4..653c2db94 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
@@ -12,10 +12,12 @@ mod deprecated_section;
mod detect_workspace_inherit;
mod detect_workspace_inherit_features;
mod detect_workspace_inherit_optional;
+mod detect_workspace_inherit_public;
mod dev;
mod dev_build_conflict;
mod dev_prefer_existing_version;
mod dry_run;
+mod empty_dep_name;
mod empty_dep_table;
mod features;
mod features_activated_over_limit;
@@ -65,6 +67,7 @@ mod namever;
mod no_args;
mod no_default_features;
mod no_optional;
+mod no_public;
mod offline_empty_cache;
mod optional;
mod overwrite_default_features;
@@ -81,11 +84,16 @@ mod overwrite_no_default_features;
mod overwrite_no_default_features_with_default_features;
mod overwrite_no_optional;
mod overwrite_no_optional_with_optional;
+mod overwrite_no_public;
+mod overwrite_no_public_with_public;
mod overwrite_optional;
mod overwrite_optional_with_no_optional;
+mod overwrite_optional_with_optional;
mod overwrite_path_noop;
mod overwrite_path_with_version;
mod overwrite_preserves_inline_table;
+mod overwrite_public;
+mod overwrite_public_with_no_public;
mod overwrite_rename_with_no_rename;
mod overwrite_rename_with_rename;
mod overwrite_rename_with_rename_noop;
@@ -103,6 +111,7 @@ mod preserve_dep_std_table;
mod preserve_features_table;
mod preserve_sorted;
mod preserve_unsorted;
+mod public;
mod quiet;
mod registry;
mod rename;
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/no_optional/mod.rs
index 9145528bf..cc7e79b97 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/no_optional/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_optional/mod.rs
@@ -7,19 +7,7 @@ use cargo_test_support::curr_dir;
#[cargo_test]
fn case() {
cargo_test_support::registry::init();
- for name in ["my-package1", "my-package2"] {
- for ver in [
- "0.1.1+my-package",
- "0.2.0+my-package",
- "0.2.3+my-package",
- "0.4.1+my-package",
- "20.0.0+my-package",
- "99999.0.0+my-package",
- "99999.0.0-alpha.1+my-package",
- ] {
- cargo_test_support::registry::Package::new(name, ver).publish();
- }
- }
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
@@ -27,7 +15,7 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("add")
- .arg_line("my-package1 my-package2@0.4.1 --no-optional")
+ .arg_line("my-package --no-optional")
.current_dir(cwd)
.assert()
.success()
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/no_optional/out/Cargo.toml
index c5e017892..496ac8a62 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/no_optional/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_optional/out/Cargo.toml
@@ -5,5 +5,4 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = "99999.0.0"
-my-package2 = "0.4.1"
+my-package = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/no_optional/stderr.log
index fb8d4903d..8e025739f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/no_optional/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_optional/stderr.log
@@ -1,3 +1,2 @@
Updating `dummy-registry` index
- Adding my-package1 v99999.0.0 to dependencies.
- Adding my-package2 v0.4.1 to dependencies.
+ Adding my-package v0.1.0 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/no_public/in/Cargo.toml
new file mode 100644
index 000000000..e9087535b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_public/in/Cargo.toml
@@ -0,0 +1,6 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_public/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/no_public/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_public/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/no_public/mod.rs
new file mode 100644
index 000000000..912ac3fd3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package --no-public")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/no_public/out/Cargo.toml
new file mode 100644
index 000000000..b9f045116
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_public/out/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/no_public/stderr.log
new file mode 100644
index 000000000..8e025739f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_public/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package v0.1.0 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/no_public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/no_public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/no_public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/optional/mod.rs
index 408a46ed3..8daaa961d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/optional/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/optional/mod.rs
@@ -7,19 +7,7 @@ use cargo_test_support::curr_dir;
#[cargo_test]
fn case() {
cargo_test_support::registry::init();
- for name in ["my-package1", "my-package2"] {
- for ver in [
- "0.1.1+my-package",
- "0.2.0+my-package",
- "0.2.3+my-package",
- "0.4.1+my-package",
- "20.0.0+my-package",
- "99999.0.0+my-package",
- "99999.0.0-alpha.1+my-package",
- ] {
- cargo_test_support::registry::Package::new(name, ver).publish();
- }
- }
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
@@ -27,7 +15,7 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("add")
- .arg_line("my-package1 my-package2@0.4.1 --optional")
+ .arg_line("my-package --optional")
.current_dir(cwd)
.assert()
.success()
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/optional/out/Cargo.toml
index eda5445c5..a8789b033 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/optional/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/optional/out/Cargo.toml
@@ -5,5 +5,7 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = { version = "99999.0.0", optional = true }
-my-package2 = { version = "0.4.1", optional = true }
+my-package = { version = "0.1.0", optional = true }
+
+[features]
+my-package = ["dep:my-package"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/optional/stderr.log
index 8cf4812cf..595ac276b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/optional/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/optional/stderr.log
@@ -1,3 +1,2 @@
Updating `dummy-registry` index
- Adding my-package1 v99999.0.0 to optional dependencies.
- Adding my-package2 v0.4.1 to optional dependencies.
+ Adding my-package v0.1.0 to optional dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml
index ad1205481..27e6e175d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml
@@ -6,3 +6,6 @@ version = "0.0.0"
[dependencies]
cargo-list-test-fixture-dependency = { optional = true, path = "../dependency", version = "0.0.0" }
+
+[features]
+cargo-list-test-fixture-dependency = ["dep:cargo-list-test-fixture-dependency"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml
index 6dd7fb6d6..38ff36eb3 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml
@@ -4,3 +4,6 @@ version = "0.0.0"
[dependencies]
foo = { workspace = true, optional = true }
+
+[features]
+foo = ["dep:foo"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml
index bbaf4f552..717252191 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml
@@ -7,3 +7,6 @@ version = "0.0.0"
[dependencies]
your-face = { version = "0.0.0", path = "dependency", optional = true, default-features = false, features = ["nose", "mouth"], registry = "alternative" }
+
+[features]
+your-face = ["dep:your-face"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/in/Cargo.toml
index c5e017892..496ac8a62 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/in/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/in/Cargo.toml
@@ -5,5 +5,4 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = "99999.0.0"
-my-package2 = "0.4.1"
+my-package = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs
index 9145528bf..cc7e79b97 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs
@@ -7,19 +7,7 @@ use cargo_test_support::curr_dir;
#[cargo_test]
fn case() {
cargo_test_support::registry::init();
- for name in ["my-package1", "my-package2"] {
- for ver in [
- "0.1.1+my-package",
- "0.2.0+my-package",
- "0.2.3+my-package",
- "0.4.1+my-package",
- "20.0.0+my-package",
- "99999.0.0+my-package",
- "99999.0.0-alpha.1+my-package",
- ] {
- cargo_test_support::registry::Package::new(name, ver).publish();
- }
- }
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
@@ -27,7 +15,7 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("add")
- .arg_line("my-package1 my-package2@0.4.1 --no-optional")
+ .arg_line("my-package --no-optional")
.current_dir(cwd)
.assert()
.success()
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/out/Cargo.toml
index c5e017892..496ac8a62 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/out/Cargo.toml
@@ -5,5 +5,4 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = "99999.0.0"
-my-package2 = "0.4.1"
+my-package = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/stderr.log
index fb8d4903d..8e025739f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional/stderr.log
@@ -1,3 +1,2 @@
Updating `dummy-registry` index
- Adding my-package1 v99999.0.0 to dependencies.
- Adding my-package2 v0.4.1 to dependencies.
+ Adding my-package v0.1.0 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/Cargo.toml
index 8cd2616d4..98e2f7da1 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/Cargo.toml
@@ -5,5 +5,4 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = { version = "99999.0.0", optional = false }
-my-package2 = { version = "0.4.1", optional = false }
+my-package = { version = "0.1.0", optional = false }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs
index 408a46ed3..8daaa961d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs
@@ -7,19 +7,7 @@ use cargo_test_support::curr_dir;
#[cargo_test]
fn case() {
cargo_test_support::registry::init();
- for name in ["my-package1", "my-package2"] {
- for ver in [
- "0.1.1+my-package",
- "0.2.0+my-package",
- "0.2.3+my-package",
- "0.4.1+my-package",
- "20.0.0+my-package",
- "99999.0.0+my-package",
- "99999.0.0-alpha.1+my-package",
- ] {
- cargo_test_support::registry::Package::new(name, ver).publish();
- }
- }
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
@@ -27,7 +15,7 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("add")
- .arg_line("my-package1 my-package2@0.4.1 --optional")
+ .arg_line("my-package --optional")
.current_dir(cwd)
.assert()
.success()
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml
index eda5445c5..a8789b033 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml
@@ -5,5 +5,7 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = { version = "99999.0.0", optional = true }
-my-package2 = { version = "0.4.1", optional = true }
+my-package = { version = "0.1.0", optional = true }
+
+[features]
+my-package = ["dep:my-package"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.log
index 8cf4812cf..595ac276b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.log
@@ -1,3 +1,2 @@
Updating `dummy-registry` index
- Adding my-package1 v99999.0.0 to optional dependencies.
- Adding my-package2 v0.4.1 to optional dependencies.
+ Adding my-package v0.1.0 to optional dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/Cargo.toml
new file mode 100644
index 000000000..43d0d8238
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = "0.1.0" \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/mod.rs
new file mode 100644
index 000000000..912ac3fd3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package --no-public")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/out/Cargo.toml
new file mode 100644
index 000000000..b9f045116
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/out/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stderr.log
new file mode 100644
index 000000000..8e025739f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package v0.1.0 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/Cargo.toml
new file mode 100644
index 000000000..c6e61bdca
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = { version = "0.1.0", public = false }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs
new file mode 100644
index 000000000..bbf8d65a6
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package --public")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/out/Cargo.toml
new file mode 100644
index 000000000..77fccaa6a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/out/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = { version = "0.1.0", public = true }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.log
new file mode 100644
index 000000000..5259bbde8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package v0.1.0 to public dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_no_public_with_public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/in/Cargo.toml
index c5e017892..496ac8a62 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/in/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/in/Cargo.toml
@@ -5,5 +5,4 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = "99999.0.0"
-my-package2 = "0.4.1"
+my-package = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/mod.rs
index 408a46ed3..8daaa961d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/mod.rs
@@ -7,19 +7,7 @@ use cargo_test_support::curr_dir;
#[cargo_test]
fn case() {
cargo_test_support::registry::init();
- for name in ["my-package1", "my-package2"] {
- for ver in [
- "0.1.1+my-package",
- "0.2.0+my-package",
- "0.2.3+my-package",
- "0.4.1+my-package",
- "20.0.0+my-package",
- "99999.0.0+my-package",
- "99999.0.0-alpha.1+my-package",
- ] {
- cargo_test_support::registry::Package::new(name, ver).publish();
- }
- }
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
@@ -27,7 +15,7 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("add")
- .arg_line("my-package1 my-package2@0.4.1 --optional")
+ .arg_line("my-package --optional")
.current_dir(cwd)
.assert()
.success()
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml
index eda5445c5..a8789b033 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml
@@ -5,5 +5,7 @@ name = "cargo-list-test-fixture"
version = "0.0.0"
[dependencies]
-my-package1 = { version = "99999.0.0", optional = true }
-my-package2 = { version = "0.4.1", optional = true }
+my-package = { version = "0.1.0", optional = true }
+
+[features]
+my-package = ["dep:my-package"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/stderr.log
index 8cf4812cf..595ac276b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional/stderr.log
@@ -1,3 +1,2 @@
Updating `dummy-registry` index
- Adding my-package1 v99999.0.0 to optional dependencies.
- Adding my-package2 v0.4.1 to optional dependencies.
+ Adding my-package v0.1.0 to optional dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/Cargo.toml
index 5ef953209..a7722da07 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/Cargo.toml
@@ -10,4 +10,3 @@ other = ["your-face/nose"]
[dependencies]
your-face = { version = "99999.0.0", optional = true }
-my-package2 = { version = "0.4.1", optional = true }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs
index 3090a7527..511b31e29 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs
@@ -7,17 +7,7 @@ use cargo_test_support::curr_dir;
#[cargo_test]
fn case() {
cargo_test_support::registry::init();
- for ver in [
- "0.1.1+my-package",
- "0.2.0+my-package",
- "0.2.3+my-package",
- "0.4.1+my-package",
- "20.0.0+my-package",
- "99999.0.0+my-package",
- "99999.0.0-alpha.1+my-package",
- ] {
- cargo_test_support::registry::Package::new("my-package2", ver).publish();
- }
+
cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package")
.feature("nose", &[])
.feature("mouth", &[])
@@ -31,7 +21,7 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("add")
- .arg_line("your-face my-package2@0.4.1 --no-optional")
+ .arg_line("your-face --no-optional")
.current_dir(cwd)
.assert()
.success()
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/out/Cargo.toml
index bf6c52963..b57286ed5 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/out/Cargo.toml
@@ -10,4 +10,3 @@ other = ["your-face/nose"]
[dependencies]
your-face = { version = "99999.0.0" }
-my-package2 = { version = "0.4.1" }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.log
index 5fe113e86..796b9601b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.log
@@ -5,4 +5,3 @@
- eyes
- mouth
- nose
- Adding my-package2 v0.4.1 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/Cargo.toml
new file mode 100644
index 000000000..e446eca38
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/Cargo.toml
@@ -0,0 +1,11 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package1 = { version = "99999.0.0", optional = true }
+
+[features]
+default = ["dep:my-package1"] \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs
new file mode 100644
index 000000000..434124e93
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package1", "99999.0.0").publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package1 --optional")
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/out/Cargo.toml
new file mode 100644
index 000000000..e68fcdb3c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/out/Cargo.toml
@@ -0,0 +1,11 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package1 = { version = "99999.0.0", optional = true }
+
+[features]
+default = ["dep:my-package1"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.log
new file mode 100644
index 000000000..ba9cb313d
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package1 v99999.0.0 to optional dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_optional_with_optional/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_noop/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_noop/out/Cargo.toml
index bbaf4f552..717252191 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_noop/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_noop/out/Cargo.toml
@@ -7,3 +7,6 @@ version = "0.0.0"
[dependencies]
your-face = { version = "0.0.0", path = "dependency", optional = true, default-features = false, features = ["nose", "mouth"], registry = "alternative" }
+
+[features]
+your-face = ["dep:your-face"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_with_version/out/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_with_version/out/primary/Cargo.toml
index a20f2095d..c45f79491 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_with_version/out/primary/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_path_with_version/out/primary/Cargo.toml
@@ -6,3 +6,6 @@ version = "0.0.0"
[dependencies]
cargo-list-test-fixture-dependency = { optional = true, version = "20.0" }
+
+[features]
+cargo-list-test-fixture-dependency = ["dep:cargo-list-test-fixture-dependency"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/Cargo.toml
new file mode 100644
index 000000000..43d0d8238
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = "0.1.0" \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/mod.rs
new file mode 100644
index 000000000..bbf8d65a6
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package --public")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/out/Cargo.toml
new file mode 100644
index 000000000..77fccaa6a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/out/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = { version = "0.1.0", public = true }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stderr.log
new file mode 100644
index 000000000..5259bbde8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package v0.1.0 to public dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/Cargo.toml
new file mode 100644
index 000000000..cc7ec1a9b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = { version = "0.1.0", public = true } \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs
new file mode 100644
index 000000000..912ac3fd3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package --no-public")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/out/Cargo.toml
new file mode 100644
index 000000000..cfa80cc13
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/out/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = { version = "0.1.0" }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.log
new file mode 100644
index 000000000..8e025739f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package v0.1.0 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_public_with_no_public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/out/Cargo.toml
index 450229245..0217d4176 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/out/Cargo.toml
@@ -6,3 +6,6 @@ version = "0.0.0"
[dependencies]
a1 = { package = "versioned-package", version = "0.1.1", optional = true }
+
+[features]
+a1 = ["dep:a1"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_git/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_git/out/Cargo.toml
index 260014024..a3eabd065 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_git/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_git/out/Cargo.toml
@@ -6,3 +6,6 @@ version = "0.0.0"
[dependencies]
versioned-package = { version = "0.3.0", optional = true, git = "[ROOTURL]/versioned-package" }
+
+[features]
+versioned-package = ["dep:versioned-package"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_path/out/primary/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_path/out/primary/Cargo.toml
index 07253670a..bd460a11b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_path/out/primary/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_add/overwrite_version_with_path/out/primary/Cargo.toml
@@ -6,3 +6,6 @@ version = "0.0.0"
[dependencies]
cargo-list-test-fixture-dependency = { version = "0.0.0", optional = true, path = "../dependency" }
+
+[features]
+cargo-list-test-fixture-dependency = ["dep:cargo-list-test-fixture-dependency"]
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/public/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/public/in/Cargo.toml
new file mode 100644
index 000000000..e9087535b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/public/in/Cargo.toml
@@ -0,0 +1,6 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/public/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/public/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/public/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/public/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/public/mod.rs
new file mode 100644
index 000000000..bbf8d65a6
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/public/mod.rs
@@ -0,0 +1,26 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("my-package --public")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/public/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/public/out/Cargo.toml
new file mode 100644
index 000000000..77fccaa6a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/public/out/Cargo.toml
@@ -0,0 +1,9 @@
+cargo-features = ["public-dependency"]
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+my-package = { version = "0.1.0", public = true }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/public/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/public/stderr.log
new file mode 100644
index 000000000..5259bbde8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/public/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding my-package v0.1.0 to public dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/public/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/public/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/public/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
index f8aac0ad8..0404d12b4 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
@@ -26,7 +26,7 @@ fn case() {
.current_dir(cwd)
.masquerade_as_nightly_cargo(&["msrv-policy"])
.assert()
- .code(101)
+ .code(0)
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
index 96bcbddc2..430abe31b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
@@ -1,7 +1,2 @@
Updating `dummy-registry` index
Adding rust-version-user v0.2.1 to dependencies.
-error: failed to select a version for the requirement `rust-version-user = "^0.2.1"`
-candidate versions found which didn't match: 0.2.1, 0.1.0
-location searched: `dummy-registry` index (which is replacing registry `crates-io`)
-required by package `cargo-list-test-fixture v0.0.0 ([ROOT]/case)`
-perhaps a crate was updated and forgotten to be re-vendored?
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log
index 95546b4a3..cfea6e01e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log
@@ -11,8 +11,8 @@ Options:
--no-fail-fast Run all benchmarks regardless of failure
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log
index 58b12cdcd..3918fd44a 100644
--- a/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log
@@ -6,8 +6,8 @@ Options:
--ignore-rust-version Ignore `rust-version` specification in packages
--future-incompat-report Outputs a future incompatibility report at the end of the build
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log
index bbf090d1d..7b6289798 100644
--- a/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log
@@ -6,8 +6,8 @@ Options:
--ignore-rust-version Ignore `rust-version` specification in packages
--future-incompat-report Outputs a future incompatibility report at the end of the build
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log
index 6e9e82772..80571e5dc 100644
--- a/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log
@@ -4,9 +4,9 @@ Usage: cargo[EXE] clean [OPTIONS]
Options:
--doc Whether or not to clean just the documentation directory
- -q, --quiet Do not print cargo log messages
-n, --dry-run Display what would be deleted without deleting anything
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_config/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_config/help/stdout.log
index 50caca72a..5c14335fc 100644
--- a/src/tools/cargo/tests/testsuite/cargo_config/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_config/help/stdout.log
@@ -7,6 +7,7 @@ Commands:
Options:
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log
index 8ff5f9b72..e1a19bedd 100644
--- a/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log
@@ -8,8 +8,8 @@ Options:
--document-private-items Document private items
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_features.rs b/src/tools/cargo/tests/testsuite/cargo_features.rs
index d319ed686..8b7daa214 100644
--- a/src/tools/cargo/tests/testsuite/cargo_features.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_features.rs
@@ -296,7 +296,7 @@ fn allow_features_to_rustc() {
"src/lib.rs",
r#"
#![allow(internal_features)]
- #![feature(test_2018_feature)]
+ #![feature(rustc_attrs)]
"#,
)
.build();
@@ -307,7 +307,7 @@ fn allow_features_to_rustc() {
.with_stderr_contains("[..]E0725[..]")
.run();
- p.cargo("-Zallow-features=test_2018_feature check")
+ p.cargo("-Zallow-features=rustc_attrs check")
.masquerade_as_nightly_cargo(&["allow-features"])
.with_stderr(
"\
diff --git a/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log
index 32f29f1b3..5645a6c03 100644
--- a/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log
@@ -3,8 +3,8 @@ Fetch dependencies of a package from the network
Usage: cargo[EXE] fetch [OPTIONS]
Options:
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log
index 3e8b1427f..a93215c50 100644
--- a/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log
@@ -11,8 +11,8 @@ Options:
--allow-staged Fix code even if the working directory has staged changes
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stdout.log
index 07eff888a..5d0bf1359 100644
--- a/src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stdout.log
@@ -3,8 +3,8 @@ Generate the lockfile for a package
Usage: cargo[EXE] generate-lockfile [OPTIONS]
Options:
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_help/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_help/help/stdout.log
index a03946b45..1f7a710d6 100644
--- a/src/tools/cargo/tests/testsuite/cargo_help/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_help/help/stdout.log
@@ -7,6 +7,7 @@ Arguments:
Options:
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log
index 588b45ccf..197a5f8d1 100644
--- a/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log
@@ -15,8 +15,8 @@ Options:
2021, 2024]
--name <NAME> Set the resulting package name, defaults to the directory name
--registry <REGISTRY> Registry to use
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log
index 5e3458d37..baaba7a72 100644
--- a/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log
@@ -20,9 +20,9 @@ Options:
--list list all installed packages and their versions
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
--debug Build in debug mode (with the 'dev' profile) instead of release mode
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_locate_project/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_locate_project/help/stdout.log
index 1c6ea7b25..f39d61b7a 100644
--- a/src/tools/cargo/tests/testsuite/cargo_locate_project/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_locate_project/help/stdout.log
@@ -5,8 +5,8 @@ Usage: cargo[EXE] locate-project [OPTIONS]
Options:
--workspace Locate Cargo.toml of the workspace root
--message-format <FMT> Output representation [possible values: json, plain]
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log
index e0d5e7e69..0a699f72f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log
@@ -8,8 +8,8 @@ Arguments:
Options:
--registry <REGISTRY> Registry to use
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_logout/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_logout/help/stdout.log
index fe328d765..3f9679f9b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_logout/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_logout/help/stdout.log
@@ -4,8 +4,8 @@ Usage: cargo[EXE] logout [OPTIONS]
Options:
--registry <REGISTRY> Registry to use
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_metadata/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_metadata/help/stdout.log
index 939fc40c9..f44f66c88 100644
--- a/src/tools/cargo/tests/testsuite/cargo_metadata/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_metadata/help/stdout.log
@@ -8,8 +8,8 @@ Options:
--no-deps Output information only about the workspace members and don't
fetch dependencies
--format-version <VERSION> Format version [possible values: 1]
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/empty_name/in/.keep b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/in/.keep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/in/.keep
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/empty_name/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/mod.rs
new file mode 100644
index 000000000..a7d56630f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("new")
+ .args(["foo", "--name", ""])
+ .current_dir(cwd)
+ .assert()
+ .failure()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/empty_name/out/.keep b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/out/.keep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/out/.keep
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/empty_name/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/stderr.log
new file mode 100644
index 000000000..d9547a42a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/stderr.log
@@ -0,0 +1 @@
+error: package name cannot be empty
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/empty_name/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/empty_name/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log
index 3df5eceb8..52a6f83a1 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log
@@ -15,8 +15,8 @@ Options:
2021, 2024]
--name <NAME> Set the resulting package name, defaults to the directory name
--registry <REGISTRY> Registry to use
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
index da0304409..806bd2ec3 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
@@ -4,6 +4,7 @@ mod add_members_to_workspace_with_absolute_package_path;
mod add_members_to_workspace_with_empty_members;
mod add_members_to_workspace_with_exclude_list;
mod add_members_to_workspace_with_members_glob;
+mod empty_name;
mod help;
mod inherit_workspace_lints;
mod inherit_workspace_package_table;
diff --git a/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log
index 110df8e9a..b6f436d04 100644
--- a/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log
@@ -12,8 +12,8 @@ Options:
--index <INDEX> Registry index URL to modify owners for
--registry <REGISTRY> Registry to modify owners for
--token <TOKEN> API token to use when authenticating
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log
index 5079c2a6f..ec2464a8d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log
@@ -7,8 +7,8 @@ Options:
--no-verify Don't verify the contents by building them
--no-metadata Ignore warnings about a lack of human-usable metadata
--allow-dirty Allow dirty working directories to be packaged
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_pkgid/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_pkgid/help/stdout.log
index 5971e88dc..657bb9e5d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_pkgid/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_pkgid/help/stdout.log
@@ -6,8 +6,8 @@ Arguments:
[SPEC]
Options:
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log
index df2594fb4..d598c93d6 100644
--- a/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log
@@ -9,8 +9,8 @@ Options:
--token <TOKEN> Token to use when uploading
--no-verify Don't verify the contents by building them
--allow-dirty Allow dirty working directories to be packaged
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stdout.log
index 83db5413d..a645ea3c2 100644
--- a/src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stdout.log
@@ -5,8 +5,8 @@ Deprecated, use `cargo metadata --no-deps` instead.
Usage: cargo[EXE] read-manifest [OPTIONS]
Options:
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log
index 47d2c87ad..c3dc74b2d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log
@@ -7,8 +7,8 @@ Arguments:
Options:
-n, --dry-run Don't actually write the manifest
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/in/Cargo.lock b/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/in/Cargo.lock
index 06c2052d5..2302220f2 100644
--- a/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/in/Cargo.lock
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/in/Cargo.lock
@@ -43,13 +43,13 @@ checksum = "31162e7d23a085553c42dee375787b451a481275473f7779c4a63bcc267a24fd"
name = "semver"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3031434e07edc922bf1b8262f075fac1522694f17b1ee7ad314c4cabd5d2723f"
+checksum = "106bee742e3199d9e59f4269e458dfc825c1b4648c483b1c2b7a45cd2610a308"
[[package]]
name = "serde"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75d9264696ebbf5315a6b068e9910c4df9274365afac2d88abf66525df660218"
+checksum = "be7d269f612a60e3c2c4a4a120e2d878a3f3298a5285eda6e95453905a107d9a"
[[package]]
name = "toml"
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/out/Cargo.lock b/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/out/Cargo.lock
index bd8c90f46..0946cee47 100644
--- a/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/out/Cargo.lock
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/update_lock_file/out/Cargo.lock
@@ -36,13 +36,13 @@ checksum = "84949cb53285a6c481d0133065a7b669871acfd9e20f273f4ce1283c309775d5"
name = "semver"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3031434e07edc922bf1b8262f075fac1522694f17b1ee7ad314c4cabd5d2723f"
+checksum = "106bee742e3199d9e59f4269e458dfc825c1b4648c483b1c2b7a45cd2610a308"
[[package]]
name = "serde"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75d9264696ebbf5315a6b068e9910c4df9274365afac2d88abf66525df660218"
+checksum = "be7d269f612a60e3c2c4a4a120e2d878a3f3298a5285eda6e95453905a107d9a"
[[package]]
name = "toml"
diff --git a/src/tools/cargo/tests/testsuite/cargo_report/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_report/help/stdout.log
index 67819de55..95872662e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_report/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_report/help/stdout.log
@@ -7,6 +7,7 @@ Commands:
Options:
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log
index 97c13382a..2e39d4f9e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log
@@ -8,8 +8,8 @@ Arguments:
Options:
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log
index 60069f526..8952330b0 100644
--- a/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log
@@ -11,8 +11,8 @@ Options:
--future-incompat-report Outputs a future incompatibility report at the end of the build
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log
index 67ee27e6b..a0a3cde5d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log
@@ -9,8 +9,8 @@ Options:
--open Opens the docs in a browser after the operation
--ignore-rust-version Ignore `rust-version` specification in packages
--message-format <FMT> Error format
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log
index 9cc508bba..e2024a990 100644
--- a/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log
@@ -1,4 +1,4 @@
-Search packages in crates.io
+Search packages in the registry. Default registry is crates.io
Usage: cargo[EXE] search [OPTIONS] [QUERY]...
@@ -9,8 +9,8 @@ Options:
--limit <LIMIT> Limit the number of results (default: 10, max: 100)
--index <INDEX> Registry index URL to search packages in
--registry <REGISTRY> Registry to search packages in
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log
index 4170583a8..9865fd59e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log
@@ -3,7 +3,6 @@ Display a tree visualization of a dependency graph
Usage: cargo[EXE] tree [OPTIONS]
Options:
- -q, --quiet Do not print cargo log messages
-e, --edges <KINDS> The kinds of dependencies to display (features, normal, build, dev, all,
no-normal, no-build, no-dev, no-proc-macro)
-i, --invert [<SPEC>] Invert the tree direction and focus on the given package
@@ -17,6 +16,7 @@ Options:
ascii]
-f, --format <FORMAT> Format string used for printing dependencies [default: {p}]
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_uninstall/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_uninstall/help/stdout.log
index efdf11c03..1988e7a0e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_uninstall/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_uninstall/help/stdout.log
@@ -7,8 +7,8 @@ Arguments:
Options:
--root <DIR> Directory to uninstall packages from
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log
index 92caeb656..8e0bf2ccb 100644
--- a/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log
@@ -6,8 +6,8 @@ Options:
-n, --dry-run Don't actually write the lockfile
--recursive Force updating all dependencies of [SPEC]... as well
--precise <PRECISE> Update [SPEC] to exactly PRECISE
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_vendor/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_vendor/help/stdout.log
index 7f37ab56e..4e05e75c8 100644
--- a/src/tools/cargo/tests/testsuite/cargo_vendor/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_vendor/help/stdout.log
@@ -10,8 +10,8 @@ Options:
-s, --sync <TOML> Additional `Cargo.toml` to sync and vendor
--respect-source-config Respect `[source]` config in `.cargo/config`
--versioned-dirs Always include version in subdir name
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for
diff --git a/src/tools/cargo/tests/testsuite/cargo_verify_project/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_verify_project/help/stdout.log
index a61534500..7adc34e6c 100644
--- a/src/tools/cargo/tests/testsuite/cargo_verify_project/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_verify_project/help/stdout.log
@@ -3,8 +3,8 @@ Check correctness of crate manifest
Usage: cargo[EXE] verify-project [OPTIONS]
Options:
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_version/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_version/help/stdout.log
index 3f79051ad..2ad1c551c 100644
--- a/src/tools/cargo/tests/testsuite/cargo_version/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_version/help/stdout.log
@@ -3,8 +3,8 @@ Show version information
Usage: cargo[EXE] version [OPTIONS]
Options:
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log
index 61dc800c7..072ceaac7 100644
--- a/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log
@@ -11,8 +11,8 @@ Options:
--index <INDEX> Registry index URL to yank from
--registry <REGISTRY> Registry to yank from
--token <TOKEN> API token to use when authenticating
- -q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
diff --git a/src/tools/cargo/tests/testsuite/check.rs b/src/tools/cargo/tests/testsuite/check.rs
index 03611ae67..b7ad3eb1d 100644
--- a/src/tools/cargo/tests/testsuite/check.rs
+++ b/src/tools/cargo/tests/testsuite/check.rs
@@ -3,11 +3,12 @@
use std::fmt::{self, Write};
use crate::messages::raw_rustc_output;
+use cargo_test_support::compare;
use cargo_test_support::install::exe;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
+use cargo_test_support::tools;
use cargo_test_support::{basic_bin_manifest, basic_manifest, git, project};
-use cargo_test_support::{tools, wrapped_clippy_driver};
#[cargo_test]
fn check_success() {
@@ -804,7 +805,7 @@ fn short_message_format() {
.with_stderr_contains(
"\
src/lib.rs:1:27: error[E0308]: mismatched types
-error: could not compile `foo` (lib) due to previous error
+error: could not compile `foo` (lib) due to 1 previous error
",
)
.run();
@@ -1250,7 +1251,7 @@ fn check_fixable_error_no_fix() {
[CHECKING] foo v0.0.1 ([..])
{}\
[WARNING] `foo` (lib) generated 1 warning
-[ERROR] could not compile `foo` (lib) due to previous error; 1 warning emitted
+[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted
",
rustc_message
);
@@ -1432,7 +1433,7 @@ fn check_fixable_warning_for_clippy() {
foo.cargo("check")
// We can't use `clippy` so we use a `rustc` workspace wrapper instead
- .env("RUSTC_WORKSPACE_WRAPPER", wrapped_clippy_driver())
+ .env("RUSTC_WORKSPACE_WRAPPER", tools::wrapped_clippy_driver())
.with_stderr_contains("[..] (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion)")
.run();
}
@@ -1519,3 +1520,43 @@ fn versionless_package() {
)
.run();
}
+
+#[cargo_test]
+fn pkgid_querystring_works() {
+ let git_project = git::new("gitdep", |p| {
+ p.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+
+ [dependencies]
+ gitdep = {{ git = "{}", branch = "master" }}
+ "#,
+ git_project.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("generate-lockfile").run();
+
+ let output = p.cargo("pkgid").arg("gitdep").exec_with_output().unwrap();
+ let gitdep_pkgid = String::from_utf8(output.stdout).unwrap();
+ let gitdep_pkgid = gitdep_pkgid.trim();
+ compare::assert_match_exact("git+file://[..]/gitdep?branch=master#1.0.0", &gitdep_pkgid);
+
+ p.cargo("build -p")
+ .arg(gitdep_pkgid)
+ .with_stderr(
+ "\
+[COMPILING] gitdep v1.0.0 (file:///[..]/gitdep?branch=master#[..])
+[FINISHED] dev [..]",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/check_cfg.rs b/src/tools/cargo/tests/testsuite/check_cfg.rs
index 57d5f8053..42cfe6065 100644
--- a/src/tools/cargo/tests/testsuite/check_cfg.rs
+++ b/src/tools/cargo/tests/testsuite/check_cfg.rs
@@ -15,16 +15,16 @@ macro_rules! x {
$what, '(', $($who,)* ')', "'", "[..]")
}
}};
- ($tool:tt => $what:tt of $who:tt with $($first_value:tt $($other_values:tt)*)?) => {{
+ ($tool:tt => $what:tt of $who:tt with $first_value:tt $($other_values:tt)*) => {{
#[cfg(windows)]
{
concat!("[RUNNING] [..]", $tool, "[..] --check-cfg \"",
- $what, '(', $who, ", values(", $("/\"", $first_value, "/\"", $(", ", "/\"", $other_values, "/\"",)*)* "))", '"', "[..]")
+ $what, '(', $who, ", values(", "/\"", $first_value, "/\"", $(", ", "/\"", $other_values, "/\"",)* "))", '"', "[..]")
}
#[cfg(not(windows))]
{
concat!("[RUNNING] [..]", $tool, "[..] --check-cfg '",
- $what, '(', $who, ", values(", $("\"", $first_value, "\"", $(", ", "\"", $other_values, "\"",)*)* "))", "'", "[..]")
+ $what, '(', $who, ", values(", "\"", $first_value, "\"", $(", ", "\"", $other_values, "\"",)* "))", "'", "[..]")
}
}};
}
@@ -142,6 +142,77 @@ fn features_with_namespaced_features() {
}
#[cargo_test(nightly, reason = "--check-cfg is unstable")]
+fn features_fingerprint() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [features]
+ f_a = []
+ f_b = []
+ "#,
+ )
+ .file("src/lib.rs", "#[cfg(feature = \"f_b\")] fn entry() {}")
+ .build();
+
+ p.cargo("check -v -Zcheck-cfg")
+ .masquerade_as_nightly_cargo(&["check-cfg"])
+ .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a" "f_b"))
+ .with_stderr_does_not_contain("[..]unexpected_cfgs[..]")
+ .run();
+
+ p.cargo("check -v -Zcheck-cfg")
+ .masquerade_as_nightly_cargo(&["check-cfg"])
+ .with_stderr_does_not_contain("[..]rustc[..]")
+ .run();
+
+ // checking that re-ordering the features does not invalid the fingerprint
+ p.change_file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [features]
+ f_b = []
+ f_a = []
+ "#,
+ );
+
+ p.cargo("check -v -Zcheck-cfg")
+ .masquerade_as_nightly_cargo(&["check-cfg"])
+ .with_stderr_does_not_contain("[..]rustc[..]")
+ .run();
+
+ p.change_file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [features]
+ f_a = []
+ "#,
+ );
+
+ p.cargo("check -v -Zcheck-cfg")
+ .masquerade_as_nightly_cargo(&["check-cfg"])
+ // we check that the fingerprint is indeed dirty
+ .with_stderr_contains("[..]Dirty[..]the list of declared features changed")
+ // that is cause rustc to be called again with the new check-cfg args
+ .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a"))
+ // and that we indeed found a new warning from the unexpected_cfgs lint
+ .with_stderr_contains("[..]unexpected_cfgs[..]")
+ .run();
+}
+
+#[cargo_test(nightly, reason = "--check-cfg is unstable")]
fn well_known_names_values() {
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
@@ -150,7 +221,7 @@ fn well_known_names_values() {
p.cargo("check -v -Zcheck-cfg")
.masquerade_as_nightly_cargo(&["check-cfg"])
- .with_stderr_contains(x!("rustc" => "cfg" of "feature" with))
+ .with_stderr_contains(x!("rustc" => "cfg"))
.run();
}
@@ -213,7 +284,7 @@ fn well_known_names_values_test() {
p.cargo("test -v -Zcheck-cfg")
.masquerade_as_nightly_cargo(&["check-cfg"])
- .with_stderr_contains(x!("rustc" => "cfg" of "feature" with))
+ .with_stderr_contains(x!("rustc" => "cfg"))
.run();
}
@@ -226,8 +297,8 @@ fn well_known_names_values_doctest() {
p.cargo("test -v --doc -Zcheck-cfg")
.masquerade_as_nightly_cargo(&["check-cfg"])
- .with_stderr_contains(x!("rustc" => "cfg" of "feature" with))
- .with_stderr_contains(x!("rustdoc" => "cfg" of "feature" with))
+ .with_stderr_contains(x!("rustc" => "cfg"))
+ .with_stderr_contains(x!("rustdoc" => "cfg"))
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/clean.rs b/src/tools/cargo/tests/testsuite/clean.rs
index fbb4d3e5b..913bf19cb 100644
--- a/src/tools/cargo/tests/testsuite/clean.rs
+++ b/src/tools/cargo/tests/testsuite/clean.rs
@@ -1,5 +1,6 @@
//! Tests for the `cargo clean` command.
+use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
use cargo_test_support::{
basic_bin_manifest, basic_manifest, git, main_file, project, project_in, rustc_host,
@@ -33,7 +34,10 @@ fn different_dir() {
p.cargo("build").run();
assert!(p.build_dir().is_dir());
- p.cargo("clean").cwd("src").with_stdout("").run();
+ p.cargo("clean")
+ .cwd("src")
+ .with_stderr("[REMOVED] [..]")
+ .run();
assert!(!p.build_dir().is_dir());
}
@@ -81,7 +85,7 @@ fn clean_multiple_packages() {
p.cargo("clean -p d1 -p d2")
.cwd("src")
- .with_stdout("")
+ .with_stderr("[REMOVED] [..]")
.run();
assert!(p.bin("foo").is_file());
assert!(!d1_path.is_file());
@@ -226,7 +230,9 @@ fn clean_release() {
p.cargo("build --release").run();
p.cargo("clean -p foo").run();
- p.cargo("build --release").with_stdout("").run();
+ p.cargo("build --release")
+ .with_stderr("[FINISHED] [..]")
+ .run();
p.cargo("clean -p foo --release").run();
p.cargo("build --release")
@@ -354,7 +360,7 @@ fn clean_git() {
.build();
p.cargo("build").run();
- p.cargo("clean -p dep").with_stdout("").run();
+ p.cargo("clean -p dep").with_stderr("[REMOVED] [..]").run();
p.cargo("build").run();
}
@@ -379,7 +385,7 @@ fn registry() {
Package::new("bar", "0.1.0").publish();
p.cargo("build").run();
- p.cargo("clean -p bar").with_stdout("").run();
+ p.cargo("clean -p bar").with_stderr("[REMOVED] [..]").run();
p.cargo("build").run();
}
@@ -805,15 +811,6 @@ fn clean_dry_run() {
.file("src/lib.rs", "")
.build();
- let ls_r = || -> Vec<_> {
- let mut file_list: Vec<_> = walkdir::WalkDir::new(p.build_dir())
- .into_iter()
- .filter_map(|e| e.map(|e| e.path().to_owned()).ok())
- .collect();
- file_list.sort();
- file_list
- };
-
// Start with no files.
p.cargo("clean --dry-run")
.with_stdout("")
@@ -823,7 +820,7 @@ fn clean_dry_run() {
)
.run();
p.cargo("check").run();
- let before = ls_r();
+ let before = p.build_dir().ls_r();
p.cargo("clean --dry-run")
.with_stderr(
"[SUMMARY] [..] files, [..] total\n\
@@ -831,7 +828,7 @@ fn clean_dry_run() {
)
.run();
// Verify it didn't delete anything.
- let after = ls_r();
+ let after = p.build_dir().ls_r();
assert_eq!(before, after);
let expected = cargo::util::iter_join(before.iter().map(|p| p.to_str().unwrap()), "\n");
eprintln!("{expected}");
@@ -854,3 +851,29 @@ fn doc_with_package_selection() {
.with_stderr("error: --doc cannot be used with -p")
.run();
}
+
+#[cargo_test]
+fn quiet_does_not_show_summary() {
+ // Checks that --quiet works with `cargo clean`, since there was a
+ // subtle issue with how the flag is defined as a global flag.
+ let p = project()
+ .file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check").run();
+ p.cargo("clean --quiet --dry-run")
+ .with_stdout("")
+ .with_stderr("")
+ .run();
+ // Verify exact same command without -q would actually display something.
+ p.cargo("clean --dry-run")
+ .with_stdout("")
+ .with_stderr(
+ "\
+[SUMMARY] [..] files, [..] total
+[WARNING] no files deleted due to --dry-run
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/config.rs b/src/tools/cargo/tests/testsuite/config.rs
index e5078bd8e..bcd126020 100644
--- a/src/tools/cargo/tests/testsuite/config.rs
+++ b/src/tools/cargo/tests/testsuite/config.rs
@@ -2,9 +2,9 @@
use cargo::core::{PackageIdSpec, Shell};
use cargo::util::config::{self, Config, Definition, JobsConfig, SslVersionConfig, StringList};
-use cargo::util::toml::schema::TomlTrimPaths;
-use cargo::util::toml::schema::TomlTrimPathsValue;
-use cargo::util::toml::schema::{self as cargo_toml, TomlDebugInfo, VecStringOrBool as VSOB};
+use cargo::util_schemas::manifest::TomlTrimPaths;
+use cargo::util_schemas::manifest::TomlTrimPathsValue;
+use cargo::util_schemas::manifest::{self as cargo_toml, TomlDebugInfo, VecStringOrBool as VSOB};
use cargo::CargoResult;
use cargo_test_support::compare;
use cargo_test_support::{panic_error, paths, project, symlink_supported, t};
diff --git a/src/tools/cargo/tests/testsuite/custom_target.rs b/src/tools/cargo/tests/testsuite/custom_target.rs
index a04029075..45cb3ac9f 100644
--- a/src/tools/cargo/tests/testsuite/custom_target.rs
+++ b/src/tools/cargo/tests/testsuite/custom_target.rs
@@ -178,6 +178,8 @@ fn changing_spec_rebuilds() {
}
#[cargo_test(nightly, reason = "requires features no_core, lang_items")]
+// This is randomly crashing in lld. See https://github.com/rust-lang/rust/issues/115985
+#[cfg_attr(all(windows, target_env = "gnu"), ignore = "windows-gnu lld crashing")]
fn changing_spec_relearns_crate_types() {
// Changing the .json file will invalidate the cache of crate types.
let p = project()
diff --git a/src/tools/cargo/tests/testsuite/doc.rs b/src/tools/cargo/tests/testsuite/doc.rs
index 65169d214..37dd47d76 100644
--- a/src/tools/cargo/tests/testsuite/doc.rs
+++ b/src/tools/cargo/tests/testsuite/doc.rs
@@ -75,7 +75,14 @@ fn doc_twice() {
)
.run();
- p.cargo("doc").with_stdout("").run();
+ p.cargo("doc")
+ .with_stderr(
+ "\
+[FINISHED] [..]
+[GENERATED] [CWD]/target/doc/foo/index.html
+",
+ )
+ .run();
}
#[cargo_test]
@@ -118,9 +125,14 @@ fn doc_deps() {
assert_eq!(p.glob("target/debug/**/*.rlib").count(), 0);
assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 1);
+ // Make sure it doesn't recompile.
p.cargo("doc")
- .env("CARGO_LOG", "cargo::ops::cargo_rustc::fingerprint")
- .with_stdout("")
+ .with_stderr(
+ "\
+[FINISHED] [..]
+[GENERATED] [CWD]/target/doc/foo/index.html
+",
+ )
.run();
assert!(p.root().join("target/doc").is_dir());
@@ -1686,6 +1698,7 @@ fn doc_message_format() {
r#"
{
"message": {
+ "$message_type": "diagnostic",
"children": "{...}",
"code": "{...}",
"level": "error",
diff --git a/src/tools/cargo/tests/testsuite/docscrape.rs b/src/tools/cargo/tests/testsuite/docscrape.rs
index d4d011ff3..91871be04 100644
--- a/src/tools/cargo/tests/testsuite/docscrape.rs
+++ b/src/tools/cargo/tests/testsuite/docscrape.rs
@@ -48,6 +48,84 @@ fn basic() {
assert!(p.build_dir().join("doc/src/ex/ex.rs.html").exists());
}
+// This test ensures that even if there is no `[workspace]` in the top-level `Cargo.toml` file, the
+// dependencies will get their examples scraped and that they appear in the generated documentation.
+#[cargo_test(nightly, reason = "-Zrustdoc-scrape-examples is unstable")]
+fn scrape_examples_for_non_workspace_reexports() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ edition = "2021"
+ authors = []
+
+ [dependencies]
+ a = { path = "crates/a" }
+ "#,
+ )
+ .file("src/lib.rs", "pub use a::*;")
+ // Example
+ .file(
+ "examples/one.rs",
+ r#"use foo::*;
+fn main() {
+ let foo = Foo::new("yes".into());
+ foo.maybe();
+}"#,
+ )
+ // `a` crate
+ .file(
+ "crates/a/Cargo.toml",
+ r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#,
+ )
+ .file(
+ "crates/a/src/lib.rs",
+ r#"
+#[derive(Debug)]
+pub struct Foo {
+ foo: String,
+ yes: bool,
+}
+
+impl Foo {
+ pub fn new(foo: String) -> Self {
+ Self { foo, yes: true }
+ }
+
+ pub fn maybe(&self) {
+ if self.yes {
+ println!("{}", self.foo)
+ }
+ }
+}"#,
+ )
+ .build();
+
+ p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples --no-deps")
+ .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"])
+ .with_stderr_unordered(
+ "\
+[CHECKING] a v0.0.1 ([CWD]/crates/a)
+[CHECKING] foo v0.0.1 ([CWD])
+[SCRAPING] foo v0.0.1 ([CWD])
+[DOCUMENTING] foo v0.0.1 ([CWD])
+[FINISHED] [..]
+[GENERATED] [CWD]/target/doc/foo/index.html",
+ )
+ .run();
+
+ let doc_html = p.read_file("target/doc/foo/struct.Foo.html");
+ assert!(doc_html.contains("Examples found in repository"));
+}
+
#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")]
fn avoid_build_script_cycle() {
let p = project()
diff --git a/src/tools/cargo/tests/testsuite/features.rs b/src/tools/cargo/tests/testsuite/features.rs
index 4b7455c37..febdf52fe 100644
--- a/src/tools/cargo/tests/testsuite/features.rs
+++ b/src/tools/cargo/tests/testsuite/features.rs
@@ -60,6 +60,10 @@ fn empty_feature_name() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
+ TOML parse error at line 8, column 17
+ |
+ 8 | \"\" = []
+ | ^^
feature name cannot be empty
",
)
@@ -627,7 +631,14 @@ fn cyclic_feature2() {
.file("src/main.rs", "fn main() {}")
.build();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check")
+ .with_stderr(
+ "\
+[CHECKING] foo [..]
+[FINISHED] [..]
+",
+ )
+ .run();
}
#[cargo_test]
@@ -1047,8 +1058,8 @@ fn no_rebuild_when_frobbing_default_feature() {
.build();
p.cargo("check").run();
- p.cargo("check").with_stdout("").run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -1098,8 +1109,8 @@ fn unions_work_with_no_default_features() {
.build();
p.cargo("check").run();
- p.cargo("check").with_stdout("").run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -2048,7 +2059,11 @@ fn invalid_feature_names_error() {
error: failed to parse manifest at `[ROOT]/foo/Cargo.toml`
Caused by:
- invalid character `+` in feature `+foo` in package foo v0.1.0 ([ROOT]/foo), \
+ TOML parse error at line 8, column 17
+ |
+ 8 | \"+foo\" = []
+ | ^^^^^^
+ invalid character `+` in feature `+foo`, \
the first character must be a Unicode XID start character or digit \
(most letters or `_` or `0` to `9`)
",
@@ -2075,7 +2090,11 @@ Caused by:
error: failed to parse manifest at `[ROOT]/foo/Cargo.toml`
Caused by:
- invalid character `&` in feature `a&b` in package foo v0.1.0 ([ROOT]/foo), \
+ TOML parse error at line 8, column 13
+ |
+ 8 | \"a&b\" = []
+ | ^^^^^
+ invalid character `&` in feature `a&b`, \
characters must be Unicode XID characters, '-', `+`, or `.` \
(numbers, `+`, `-`, `_`, `.`, or most letters)
",
@@ -2108,6 +2127,10 @@ fn invalid_feature_name_slash_error() {
error: failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
+ TOML parse error at line 7, column 17
+ |
+ 7 | \"foo/bar\" = []
+ | ^^^^^^^^^
feature named `foo/bar` is not allowed to contain slashes
",
)
diff --git a/src/tools/cargo/tests/testsuite/features_namespaced.rs b/src/tools/cargo/tests/testsuite/features_namespaced.rs
index f24186c15..b79be55e8 100644
--- a/src/tools/cargo/tests/testsuite/features_namespaced.rs
+++ b/src/tools/cargo/tests/testsuite/features_namespaced.rs
@@ -439,6 +439,10 @@ fn crate_syntax_bad_name() {
[ERROR] failed to parse manifest at [..]/foo/Cargo.toml`
Caused by:
+ TOML parse error at line 10, column 17
+ |
+ 10 | \"dep:bar\" = []
+ | ^^^^^^^^^
feature named `dep:bar` is not allowed to start with `dep:`
",
)
diff --git a/src/tools/cargo/tests/testsuite/fetch.rs b/src/tools/cargo/tests/testsuite/fetch.rs
index f90131a59..9be5f79d0 100644
--- a/src/tools/cargo/tests/testsuite/fetch.rs
+++ b/src/tools/cargo/tests/testsuite/fetch.rs
@@ -11,7 +11,7 @@ fn no_deps() {
.file("src/a.rs", "")
.build();
- p.cargo("fetch").with_stdout("").run();
+ p.cargo("fetch").with_stderr("").run();
}
#[cargo_test]
diff --git a/src/tools/cargo/tests/testsuite/fix.rs b/src/tools/cargo/tests/testsuite/fix.rs
index 33de721cd..7cb5bd65e 100644
--- a/src/tools/cargo/tests/testsuite/fix.rs
+++ b/src/tools/cargo/tests/testsuite/fix.rs
@@ -5,8 +5,8 @@ use cargo_test_support::compare::assert_match_exact;
use cargo_test_support::git::{self, init};
use cargo_test_support::paths::{self, CargoPathExt};
use cargo_test_support::registry::{Dependency, Package};
+use cargo_test_support::tools;
use cargo_test_support::{basic_manifest, is_nightly, project, Project};
-use cargo_test_support::{tools, wrapped_clippy_driver};
#[cargo_test]
fn do_not_fix_broken_builds() {
@@ -29,7 +29,7 @@ fn do_not_fix_broken_builds() {
p.cargo("fix --allow-no-vcs")
.env("__CARGO_FIX_YOLO", "1")
.with_status(101)
- .with_stderr_contains("[ERROR] could not compile `foo` (lib) due to previous error")
+ .with_stderr_contains("[ERROR] could not compile `foo` (lib) due to 1 previous error")
.run();
assert!(p.read_file("src/lib.rs").contains("let mut x = 3;"));
}
@@ -110,6 +110,7 @@ fn rustc_shim_for_cargo_fix() -> Project {
}
let status = Command::new("rustc")
.args(env::args().skip(1))
+ .env_remove("CARGO_MAKEFLAGS")
.status()
.expect("failed to run rustc");
process::exit(status.code().unwrap_or(2));
@@ -193,7 +194,7 @@ fn broken_clippy_fixes_backed_out() {
.env("__CARGO_FIX_YOLO", "1")
.env("RUSTC", p.root().join("foo/target/debug/foo"))
// We can't use `clippy` so we use a `rustc` workspace wrapper instead
- .env("RUSTC_WORKSPACE_WRAPPER", wrapped_clippy_driver())
+ .env("RUSTC_WORKSPACE_WRAPPER", tools::wrapped_clippy_driver())
.with_stderr_contains(
"warning: failed to automatically apply fixes suggested by rustc \
to crate `bar`\n\
@@ -1857,9 +1858,22 @@ fn non_edition_lint_migration() {
assert!(contents.contains("from_utf8(crate::foo::FOO)"));
}
-// For rust-lang/cargo#9857
#[cargo_test]
fn fix_in_dependency() {
+ // Tests what happens if rustc emits a suggestion to modify a file from a
+ // dependency in cargo's home directory. This should never happen, and
+ // indicates a bug in rustc. However, there are several known bugs in
+ // rustc where it does this (often involving macros), so `cargo fix` has a
+ // guard that says if the suggestion points to some location in CARGO_HOME
+ // to not apply it.
+ //
+ // See https://github.com/rust-lang/cargo/issues/9857 for some other
+ // examples.
+ //
+ // This test uses a simulated rustc which replays a suggestion via a JSON
+ // message that points into CARGO_HOME. This does not use the real rustc
+ // because as the bugs are fixed in the real rustc, that would cause this
+ // test to stop working.
Package::new("bar", "1.0.0")
.file(
"src/lib.rs",
@@ -1895,8 +1909,146 @@ fn fix_in_dependency() {
"#,
)
.build();
+ p.cargo("fetch").run();
+
+ // The path in CARGO_HOME.
+ let bar_path = std::fs::read_dir(paths::home().join(".cargo/registry/src"))
+ .unwrap()
+ .next()
+ .unwrap()
+ .unwrap()
+ .path();
+ // Since this is a substitution into a Rust string (representing a JSON
+ // string), deal with backslashes like on Windows.
+ let bar_path_str = bar_path.to_str().unwrap().replace("\\", "/");
+
+ // This is a fake rustc that will emit a JSON message when the `foo` crate
+ // builds that tells cargo to modify a file it shouldn't.
+ let rustc = project()
+ .at("rustc-replay")
+ .file("Cargo.toml", &basic_manifest("rustc-replay", "1.0.0"))
+ .file("src/main.rs",
+ &r##"
+ fn main() {
+ let pkg_name = match std::env::var("CARGO_PKG_NAME") {
+ Ok(pkg_name) => pkg_name,
+ Err(_) => {
+ let r = std::process::Command::new("rustc")
+ .args(std::env::args_os().skip(1))
+ .status();
+ std::process::exit(r.unwrap().code().unwrap_or(2));
+ }
+ };
+ if pkg_name == "foo" {
+ eprintln!("{}", r#"{
+ "$message_type": "diagnostic",
+ "message": "unused variable: `abc`",
+ "code":
+ {
+ "code": "unused_variables",
+ "explanation": null
+ },
+ "level": "warning",
+ "spans":
+ [
+ {
+ "file_name": "__BAR_PATH__/bar-1.0.0/src/lib.rs",
+ "byte_start": 127,
+ "byte_end": 129,
+ "line_start": 5,
+ "line_end": 5,
+ "column_start": 29,
+ "column_end": 31,
+ "is_primary": true,
+ "text":
+ [
+ {
+ "text": " let $i = 1;",
+ "highlight_start": 29,
+ "highlight_end": 31
+ }
+ ],
+ "label": null,
+ "suggested_replacement": null,
+ "suggestion_applicability": null,
+ "expansion": null
+ }
+ ],
+ "children":
+ [
+ {
+ "message": "`#[warn(unused_variables)]` on by default",
+ "code": null,
+ "level": "note",
+ "spans":
+ [],
+ "children":
+ [],
+ "rendered": null
+ },
+ {
+ "message": "if this is intentional, prefix it with an underscore",
+ "code": null,
+ "level": "help",
+ "spans":
+ [
+ {
+ "file_name": "__BAR_PATH__/bar-1.0.0/src/lib.rs",
+ "byte_start": 127,
+ "byte_end": 129,
+ "line_start": 5,
+ "line_end": 5,
+ "column_start": 29,
+ "column_end": 31,
+ "is_primary": true,
+ "text":
+ [
+ {
+ "text": " let $i = 1;",
+ "highlight_start": 29,
+ "highlight_end": 31
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "_abc",
+ "suggestion_applicability": "MachineApplicable",
+ "expansion": null
+ }
+ ],
+ "children":
+ [],
+ "rendered": null
+ }
+ ],
+ "rendered": "warning: unused variable: `abc`\n --> __BAR_PATH__/bar-1.0.0/src/lib.rs:5:29\n |\n5 | let $i = 1;\n | ^^ help: if this is intentional, prefix it with an underscore: `_abc`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n"
+ }"#.replace("\n", ""));
+ }
+ }
+ "##.replace("__BAR_PATH__", &bar_path_str))
+ .build();
+ rustc.cargo("build").run();
+ let rustc_bin = rustc.bin("rustc-replay");
- p.cargo("fix --allow-no-vcs")
- .with_stderr_does_not_contain("[FIXED] [..]")
+ // The output here should not say `Fixed`.
+ //
+ // It is OK to compare the full diagnostic output here because the text is
+ // hard-coded in rustc-replay. Normally tests should not be checking the
+ // compiler output.
+ p.cargo("fix --lib --allow-no-vcs")
+ .env("RUSTC", &rustc_bin)
+ .with_stderr("\
+[CHECKING] bar v1.0.0
+[CHECKING] foo v0.1.0 [..]
+warning: unused variable: `abc`
+ --> [ROOT]/home/.cargo/registry/src/[..]/bar-1.0.0/src/lib.rs:5:29
+ |
+5 | let $i = 1;
+ | ^^ help: if this is intentional, prefix it with an underscore: `_abc`
+ |
+ = note: `#[warn(unused_variables)]` on by default
+
+warning: `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)
+[FINISHED] [..]
+")
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/freshness.rs b/src/tools/cargo/tests/testsuite/freshness.rs
index d450cbbd9..2d9b3df68 100644
--- a/src/tools/cargo/tests/testsuite/freshness.rs
+++ b/src/tools/cargo/tests/testsuite/freshness.rs
@@ -34,7 +34,7 @@ fn modifying_and_moving() {
)
.run();
- p.cargo("build").with_stdout("").run();
+ p.cargo("build").with_stderr("[FINISHED] [..]").run();
p.root().move_into_the_past();
p.root().join("target").move_into_the_past();
@@ -223,7 +223,7 @@ fn changing_lib_features_caches_targets() {
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
- p.cargo("build").with_stdout("").run();
+ p.cargo("build").with_stderr("[FINISHED] [..]").run();
p.cargo("build --features foo")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
@@ -666,7 +666,7 @@ fn rerun_if_changed_in_dep() {
.build();
p.cargo("build").run();
- p.cargo("build").with_stdout("").run();
+ p.cargo("build").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -1522,7 +1522,7 @@ fn bust_patched_dep() {
sleep_ms(1000);
}
- p.change_file("reg1new/src/lib.rs", "");
+ p.change_file("reg1new/src/lib.rs", "// modified");
if is_coarse_mtime() {
sleep_ms(1000);
}
diff --git a/src/tools/cargo/tests/testsuite/generate_lockfile.rs b/src/tools/cargo/tests/testsuite/generate_lockfile.rs
index d2b633605..ed282fc19 100644
--- a/src/tools/cargo/tests/testsuite/generate_lockfile.rs
+++ b/src/tools/cargo/tests/testsuite/generate_lockfile.rs
@@ -161,13 +161,13 @@ fn cargo_update_generate_lockfile() {
let lockfile = p.root().join("Cargo.lock");
assert!(!lockfile.is_file());
- p.cargo("update").with_stdout("").run();
+ p.cargo("update").with_stderr("").run();
assert!(lockfile.is_file());
fs::remove_file(p.root().join("Cargo.lock")).unwrap();
assert!(!lockfile.is_file());
- p.cargo("update").with_stdout("").run();
+ p.cargo("update").with_stderr("").run();
assert!(lockfile.is_file());
}
diff --git a/src/tools/cargo/tests/testsuite/git.rs b/src/tools/cargo/tests/testsuite/git.rs
index e27315346..d9289acc6 100644
--- a/src/tools/cargo/tests/testsuite/git.rs
+++ b/src/tools/cargo/tests/testsuite/git.rs
@@ -591,12 +591,12 @@ fn recompilation() {
.run();
// Don't recompile the second time
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
// Modify a file manually, shouldn't trigger a recompile
git_project.change_file("src/bar.rs", r#"pub fn bar() { println!("hello!"); }"#);
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
p.cargo("update")
.with_stderr(&format!(
@@ -605,7 +605,7 @@ fn recompilation() {
))
.run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
// Commit the changes and make sure we don't trigger a recompile because the
// lock file says not to change
@@ -614,7 +614,7 @@ fn recompilation() {
git::commit(&repo);
println!("compile after commit");
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
p.root().move_into_the_past();
// Update the dependency and carry on!
@@ -638,7 +638,7 @@ fn recompilation() {
.run();
// Make sure clean only cleans one dep
- p.cargo("clean -p foo").with_stdout("").run();
+ p.cargo("clean -p foo").with_stderr("[REMOVED] [..]").run();
p.cargo("check")
.with_stderr(
"[CHECKING] foo v0.5.0 ([CWD])\n\
@@ -742,7 +742,14 @@ fn update_with_shared_deps() {
// By default, not transitive updates
println!("dep1 update");
- p.cargo("update dep1").with_stdout("").run();
+ p.cargo("update dep1")
+ .with_stderr(
+ "\
+[UPDATING] git repository [..]
+[UPDATING] bar v0.5.0 [..]
+",
+ )
+ .run();
// Don't do anything bad on a weird --precise argument
println!("bar bad precise update");
@@ -766,7 +773,7 @@ Caused by:
println!("bar precise update");
p.cargo("update bar --precise")
.arg(&old_head.to_string())
- .with_stdout("")
+ .with_stderr("[UPDATING] bar v0.5.0 [..]")
.run();
// Updating recursively should, however, update the repo.
@@ -1496,12 +1503,12 @@ fn git_build_cmd_freshness() {
// Smoke test to make sure it doesn't compile again
println!("first pass");
- foo.cargo("check").with_stdout("").run();
+ foo.cargo("check").with_stderr("[FINISHED] [..]").run();
// Modify an ignored file and make sure we don't rebuild
println!("second pass");
foo.change_file("src/bar.rs", "");
- foo.cargo("check").with_stdout("").run();
+ foo.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -1636,7 +1643,7 @@ fn git_repo_changing_no_rebuild() {
// And now for the real test! Make sure that p1 doesn't get rebuilt
// even though the git repo has changed.
- p1.cargo("check").with_stdout("").run();
+ p1.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -1741,7 +1748,7 @@ fn fetch_downloads() {
))
.run();
- p.cargo("fetch").with_stdout("").run();
+ p.cargo("fetch").with_stderr("").run();
}
#[cargo_test]
@@ -1786,7 +1793,7 @@ fn fetch_downloads_with_git2_first_then_with_gitoxide_and_vice_versa() {
.run();
Package::new("bar", "1.0.0").publish(); // trigger a crates-index change.
- p.cargo("fetch").with_stdout("").run();
+ p.cargo("fetch").with_stderr("").run();
}
#[cargo_test]
diff --git a/src/tools/cargo/tests/testsuite/git_auth.rs b/src/tools/cargo/tests/testsuite/git_auth.rs
index b6e68fa3d..c79ae7ce0 100644
--- a/src/tools/cargo/tests/testsuite/git_auth.rs
+++ b/src/tools/cargo/tests/testsuite/git_auth.rs
@@ -105,11 +105,6 @@ fn setup_failed_auth_test() -> (SocketAddr, JoinHandle<()>, Arc<AtomicUsize>) {
// Tests that HTTP auth is offered from `credential.helper`.
#[cargo_test]
fn http_auth_offered() {
- // TODO(Seb): remove this once possible.
- if cargo_uses_gitoxide() {
- // Without the fixes in https://github.com/Byron/gitoxide/releases/tag/gix-v0.41.0 this test is flaky.
- return;
- }
let (addr, t, connections) = setup_failed_auth_test();
let p = project()
.file(
@@ -372,11 +367,6 @@ Caused by:
#[cargo_test]
fn instead_of_url_printed() {
- // TODO(Seb): remove this once possible.
- if cargo_uses_gitoxide() {
- // Without the fixes in https://github.com/Byron/gitoxide/releases/tag/gix-v0.41.0 this test is flaky.
- return;
- }
let (addr, t, _connections) = setup_failed_auth_test();
let config = paths::home().join(".gitconfig");
let mut config = git2::Config::open(&config).unwrap();
diff --git a/src/tools/cargo/tests/testsuite/global_cache_tracker.rs b/src/tools/cargo/tests/testsuite/global_cache_tracker.rs
new file mode 100644
index 000000000..68a606902
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/global_cache_tracker.rs
@@ -0,0 +1,1862 @@
+//! Tests for last-use tracking and auto-gc.
+//!
+//! Cargo supports an environment variable called `__CARGO_TEST_LAST_USE_NOW`
+//! to have cargo pretend that the current time is the given time (in seconds
+//! since the unix epoch). This is used throughout these tests to simulate
+//! what happens when time passes. The [`days_ago_unix`] and
+//! [`months_ago_unix`] functions help with setting this value.
+
+use super::config::ConfigBuilder;
+use cargo::core::global_cache_tracker::{self, DeferredGlobalLastUse, GlobalCacheTracker};
+use cargo::util::cache_lock::CacheLockMode;
+use cargo::util::interning::InternedString;
+use cargo::Config;
+use cargo_test_support::paths::{self, CargoPathExt};
+use cargo_test_support::registry::{Package, RegistryBuilder};
+use cargo_test_support::{
+ basic_manifest, cargo_process, execs, git, project, retry, sleep_ms, thread_wait_timeout,
+ Project,
+};
+use itertools::Itertools;
+use std::fmt::Write;
+use std::path::PathBuf;
+use std::process::Stdio;
+use std::time::{Duration, SystemTime};
+
+/// Helper to create a simple `foo` project which depends on a registry
+/// dependency called `bar`.
+fn basic_foo_bar_project() -> Project {
+ Package::new("bar", "1.0.0").publish();
+ project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build()
+}
+
+/// Helper to get the names of files in a directory as strings.
+fn get_names(glob: &str) -> Vec<String> {
+ let mut names: Vec<_> = glob::glob(paths::home().join(glob).to_str().unwrap())
+ .unwrap()
+ .map(|p| p.unwrap().file_name().unwrap().to_str().unwrap().to_owned())
+ .collect();
+ names.sort();
+ names
+}
+
+fn get_registry_names(which: &str) -> Vec<String> {
+ get_names(&format!(".cargo/registry/{which}/*/*"))
+}
+
+fn get_index_names() -> Vec<String> {
+ get_names(&format!(".cargo/registry/index/*"))
+}
+
+fn get_git_db_names() -> Vec<String> {
+ get_names(&format!(".cargo/git/db/*"))
+}
+
+fn get_git_checkout_names(db_name: &str) -> Vec<String> {
+ get_names(&format!(".cargo/git/checkouts/{db_name}/*"))
+}
+
+fn days_ago(n: u64) -> SystemTime {
+ SystemTime::now() - Duration::from_secs(60 * 60 * 24 * n)
+}
+
+/// Helper for simulating running cargo in the past. Use with the
+/// __CARGO_TEST_LAST_USE_NOW environment variable.
+fn days_ago_unix(n: u64) -> String {
+ days_ago(n)
+ .duration_since(SystemTime::UNIX_EPOCH)
+ .unwrap()
+ .as_secs()
+ .to_string()
+}
+
+/// Helper for simulating running cargo in the past. Use with the
+/// __CARGO_TEST_LAST_USE_NOW environment variable.
+fn months_ago_unix(n: u64) -> String {
+ days_ago_unix(n * 30)
+}
+
+/// Populates last-use database and the cache files.
+///
+/// This makes it easier to more accurately specify exact sizes. Creating
+/// specific sizes with `Package` is too difficult.
+fn populate_cache(config: &Config, test_crates: &[(&str, u64, u64, u64)]) -> (PathBuf, PathBuf) {
+ let cache_dir = paths::home().join(".cargo/registry/cache/example.com-a6c4a5adcb232b9a");
+ let src_dir = paths::home().join(".cargo/registry/src/example.com-a6c4a5adcb232b9a");
+
+ GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .rm_rf();
+
+ let _lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let mut tracker = GlobalCacheTracker::new(&config).unwrap();
+ let mut deferred = DeferredGlobalLastUse::new();
+
+ cache_dir.rm_rf();
+ cache_dir.mkdir_p();
+ src_dir.rm_rf();
+ src_dir.mkdir_p();
+ paths::home()
+ .join(".cargo/registry/index/example.com-a6c4a5adcb232b9a")
+ .mkdir_p();
+ let mut create = |name: &str, age, crate_size: u64, src_size: u64| {
+ let crate_filename = InternedString::new(&format!("{name}.crate"));
+ deferred.mark_registry_crate_used_stamp(
+ global_cache_tracker::RegistryCrate {
+ encoded_registry_name: "example.com-a6c4a5adcb232b9a".into(),
+ crate_filename,
+ size: crate_size,
+ },
+ Some(&days_ago(age)),
+ );
+ deferred.mark_registry_src_used_stamp(
+ global_cache_tracker::RegistrySrc {
+ encoded_registry_name: "example.com-a6c4a5adcb232b9a".into(),
+ package_dir: name.into(),
+ size: Some(src_size),
+ },
+ Some(&days_ago(age)),
+ );
+ std::fs::write(
+ cache_dir.join(crate_filename),
+ "x".repeat(crate_size as usize),
+ )
+ .unwrap();
+ let path = src_dir.join(name);
+ path.mkdir_p();
+ std::fs::write(path.join("data"), "x".repeat(src_size as usize)).unwrap()
+ };
+
+ for (name, age, crate_size, src_size) in test_crates {
+ create(name, *age, *crate_size, *src_size);
+ }
+ deferred.save(&mut tracker).unwrap();
+
+ (cache_dir, src_dir)
+}
+
+#[cargo_test]
+fn auto_gc_gated() {
+ // Requires -Zgc to both track last-use data and to run auto-gc.
+ let p = basic_foo_bar_project();
+ p.cargo("check")
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ // Check that it did not create a database or delete anything.
+ let config = ConfigBuilder::new().build();
+ assert!(!GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .exists());
+ assert_eq!(get_index_names().len(), 1);
+
+ // Again in the future, shouldn't auto-gc.
+ p.cargo("check").run();
+ assert!(!GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .exists());
+ assert_eq!(get_index_names().len(), 1);
+}
+
+#[cargo_test]
+fn clean_gc_gated() {
+ cargo_process("clean gc")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: the `cargo clean gc` command is unstable, and only available on the \
+nightly channel of Cargo, but this is the `stable` channel
+See [..]
+See [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn implies_source() {
+ // Checks that when a src, crate, or checkout is marked as used, the
+ // corresponding index or git db also gets marked as used.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let _lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let mut deferred = DeferredGlobalLastUse::new();
+ let mut tracker = GlobalCacheTracker::new(&config).unwrap();
+
+ deferred.mark_registry_crate_used(global_cache_tracker::RegistryCrate {
+ encoded_registry_name: "example.com-a6c4a5adcb232b9a".into(),
+ crate_filename: "regex-1.8.4.crate".into(),
+ size: 123,
+ });
+ deferred.mark_registry_src_used(global_cache_tracker::RegistrySrc {
+ encoded_registry_name: "index.crates.io-6f17d22bba15001f".into(),
+ package_dir: "rand-0.8.5".into(),
+ size: None,
+ });
+ deferred.mark_git_checkout_used(global_cache_tracker::GitCheckout {
+ encoded_git_name: "cargo-e7ff1db891893a9e".into(),
+ short_name: "f0a4ee0".into(),
+ size: None,
+ });
+ deferred.save(&mut tracker).unwrap();
+
+ let mut indexes = tracker.registry_index_all().unwrap();
+ assert_eq!(indexes.len(), 2);
+ indexes.sort_by(|a, b| a.0.encoded_registry_name.cmp(&b.0.encoded_registry_name));
+ assert_eq!(
+ indexes[0].0.encoded_registry_name,
+ "example.com-a6c4a5adcb232b9a"
+ );
+ assert_eq!(
+ indexes[1].0.encoded_registry_name,
+ "index.crates.io-6f17d22bba15001f"
+ );
+
+ let dbs = tracker.git_db_all().unwrap();
+ assert_eq!(dbs.len(), 1);
+ assert_eq!(dbs[0].0.encoded_git_name, "cargo-e7ff1db891893a9e");
+}
+
+#[cargo_test]
+fn auto_gc_defaults() {
+ // Checks that the auto-gc deletes old entries, and leaves new ones intact.
+ Package::new("old", "1.0.0").publish();
+ Package::new("new", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ old = "1.0"
+ new = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ // Populate the last-use data.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ assert_eq!(get_registry_names("src"), ["new-1.0.0", "old-1.0.0"]);
+ assert_eq!(
+ get_registry_names("cache"),
+ ["new-1.0.0.crate", "old-1.0.0.crate"]
+ );
+
+ // Run again with just one package. Make sure the old src gets deleted,
+ // but .crate does not.
+ p.change_file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ new = "1.0"
+ "#,
+ );
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(2))
+ .run();
+ assert_eq!(get_registry_names("src"), ["new-1.0.0"]);
+ assert_eq!(
+ get_registry_names("cache"),
+ ["new-1.0.0.crate", "old-1.0.0.crate"]
+ );
+
+ // Run again after the .crate should have aged out.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ assert_eq!(get_registry_names("src"), ["new-1.0.0"]);
+ assert_eq!(get_registry_names("cache"), ["new-1.0.0.crate"]);
+}
+
+#[cargo_test]
+fn auto_gc_config() {
+ // Can configure auto gc settings.
+ Package::new("old", "1.0.0").publish();
+ Package::new("new", "1.0.0").publish();
+ let p = project()
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [gc.auto]
+ frequency = "always"
+ max-src-age = "1 day"
+ max-crate-age = "3 days"
+ max-index-age = "3 days"
+ max-git-co-age = "1 day"
+ max-git-db-age = "3 days"
+ "#,
+ )
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ old = "1.0"
+ new = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ // Populate the last-use data.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(4))
+ .run();
+ assert_eq!(get_registry_names("src"), ["new-1.0.0", "old-1.0.0"]);
+ assert_eq!(
+ get_registry_names("cache"),
+ ["new-1.0.0.crate", "old-1.0.0.crate"]
+ );
+
+ // Run again with just one package. Make sure the old src gets deleted,
+ // but .crate does not.
+ p.change_file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ new = "1.0"
+ "#,
+ );
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2))
+ .run();
+ assert_eq!(get_registry_names("src"), ["new-1.0.0"]);
+ assert_eq!(
+ get_registry_names("cache"),
+ ["new-1.0.0.crate", "old-1.0.0.crate"]
+ );
+
+ // Run again after the .crate should have aged out.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ assert_eq!(get_registry_names("src"), ["new-1.0.0"]);
+ assert_eq!(get_registry_names("cache"), ["new-1.0.0.crate"]);
+}
+
+#[cargo_test]
+fn frequency() {
+ // gc.auto.frequency settings
+ let p = basic_foo_bar_project();
+ p.change_file(
+ ".cargo/config.toml",
+ r#"
+ [gc.auto]
+ frequency = "never"
+ "#,
+ );
+ // Populate data in the past.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ assert_eq!(get_index_names().len(), 1);
+ assert_eq!(get_registry_names("src"), ["bar-1.0.0"]);
+ assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]);
+
+ p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0"));
+
+ // Try after the default expiration time, with "never" it shouldn't gc.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ assert_eq!(get_index_names().len(), 1);
+ assert_eq!(get_registry_names("src"), ["bar-1.0.0"]);
+ assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]);
+
+ // Try again with a setting that allows it to run.
+ p.cargo("check -Zgc")
+ .env("CARGO_GC_AUTO_FREQUENCY", "1 day")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ assert_eq!(get_index_names().len(), 0);
+ assert_eq!(get_registry_names("src").len(), 0);
+ assert_eq!(get_registry_names("cache").len(), 0);
+}
+
+#[cargo_test]
+fn auto_gc_index() {
+ // Deletes the index if it hasn't been used in a while.
+ let p = basic_foo_bar_project();
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ assert_eq!(get_index_names().len(), 1);
+
+ // Make sure it stays within the time frame.
+ p.change_file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ "#,
+ );
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(2))
+ .run();
+ assert_eq!(get_index_names().len(), 1);
+
+ // After it expires, it should be deleted.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ assert_eq!(get_index_names().len(), 0);
+}
+
+#[cargo_test]
+fn auto_gc_git() {
+ // auto-gc should delete git checkouts and dbs.
+
+ // Returns the short git name of a a checkout.
+ let short_id = |repo: &git2::Repository| -> String {
+ let head = repo.revparse_single("HEAD").unwrap();
+ let short_id = head.short_id().unwrap();
+ short_id.as_str().unwrap().to_owned()
+ };
+
+ // Set up a git dependency and fetch it and populate the database,
+ // 6 months in the past.
+ let (git_project, git_repo) = git::new_repo("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ git = '{}' }}
+ "#,
+ git_project.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(6))
+ .run();
+ let db_names = get_git_db_names();
+ assert_eq!(db_names.len(), 1);
+ let first_short_oid = short_id(&git_repo);
+ assert_eq!(
+ get_git_checkout_names(&db_names[0]),
+ [first_short_oid.clone()]
+ );
+
+ // Use a new git checkout, should keep both.
+ git_project.change_file("src/lib.rs", "// modified");
+ git::add(&git_repo);
+ git::commit(&git_repo);
+ p.cargo("update -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(6))
+ .run();
+ assert_eq!(get_git_db_names().len(), 1);
+ let second_short_oid = short_id(&git_repo);
+ let mut both = vec![first_short_oid, second_short_oid.clone()];
+ both.sort();
+ assert_eq!(get_git_checkout_names(&db_names[0]), both);
+
+ // In the future, using the second checkout should delete the first.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ assert_eq!(get_git_db_names().len(), 1);
+ assert_eq!(
+ get_git_checkout_names(&db_names[0]),
+ [second_short_oid.clone()]
+ );
+
+ // After three months, the db should get deleted.
+ p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0"));
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ assert_eq!(get_git_db_names().len(), 0);
+ assert_eq!(get_git_checkout_names(&db_names[0]).len(), 0);
+}
+
+#[cargo_test]
+fn auto_gc_various_commands() {
+ // Checks that auto gc works with a variety of commands.
+ //
+ // Auto-gc is only run on a subset of commands. Generally it is run on
+ // commands that are already doing a lot of work, or heavily involve the
+ // use of the registry.
+ Package::new("bar", "1.0.0").publish();
+ let cmds = ["check", "fetch"];
+ for cmd in cmds {
+ eprintln!("checking command {cmd}");
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ // Populate the last-use data.
+ p.cargo(cmd)
+ .arg("-Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let indexes = tracker.registry_index_all().unwrap();
+ assert_eq!(indexes.len(), 1);
+ let crates = tracker.registry_crate_all().unwrap();
+ assert_eq!(crates.len(), 1);
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), 1);
+ drop(lock);
+
+ // After everything is aged out, it should all be deleted.
+ p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0"));
+ p.cargo(cmd)
+ .arg("-Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let indexes = tracker.registry_index_all().unwrap();
+ assert_eq!(indexes.len(), 0);
+ let crates = tracker.registry_crate_all().unwrap();
+ assert_eq!(crates.len(), 0);
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), 0);
+ drop(tracker);
+ drop(lock);
+ paths::home().join(".cargo/registry").rm_rf();
+ GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .rm_rf();
+ }
+}
+
+#[cargo_test]
+fn updates_last_use_various_commands() {
+ // Checks that last-use tracking is updated by various commands.
+ //
+ // Not *all* commands update the index tracking, even though they
+ // technically involve reading the index. There isn't a convenient place
+ // to ensure it gets saved while avoiding saving too often in other
+ // commands. For the most part, this should be fine, since these commands
+ // usually aren't run without running one of the commands that does save
+ // the tracking. Some of the commands are:
+ //
+ // - login, owner, yank, search
+ // - report future-incompatibilities
+ // - package --no-verify
+ // - fetch --locked
+ Package::new("bar", "1.0.0").publish();
+ let cmds = [
+ // name, expected_crates (0=doesn't download)
+ ("check", 1),
+ ("fetch", 1),
+ ("tree", 1),
+ ("generate-lockfile", 0),
+ ("update", 0),
+ ("metadata", 1),
+ ("vendor --respect-source-config", 1),
+ ];
+ for (cmd, expected_crates) in cmds {
+ eprintln!("checking command {cmd}");
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ // Populate the last-use data.
+ p.cargo(cmd)
+ .arg("-Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let indexes = tracker.registry_index_all().unwrap();
+ assert_eq!(indexes.len(), 1);
+ let crates = tracker.registry_crate_all().unwrap();
+ assert_eq!(crates.len(), expected_crates);
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), expected_crates);
+ drop(tracker);
+ drop(lock);
+ paths::home().join(".cargo/registry").rm_rf();
+ GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .rm_rf();
+ }
+}
+
+#[cargo_test]
+fn both_git_and_http_index_cleans() {
+ // Checks that either the git or http index cache gets cleaned.
+ let _crates_io = RegistryBuilder::new().build();
+ let _alternative = RegistryBuilder::new().alternative().http_index().build();
+ Package::new("from_git", "1.0.0").publish();
+ Package::new("from_http", "1.0.0")
+ .alternative(true)
+ .publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ from_git = "1.0"
+ from_http = { version = "1.0", registry = "alternative" }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("update -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let indexes = tracker.registry_index_all().unwrap();
+ assert_eq!(indexes.len(), 2);
+ assert_eq!(get_index_names().len(), 2);
+ drop(lock);
+
+ // Running in the future without these indexes should delete them.
+ p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0"));
+ p.cargo("clean gc -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let indexes = tracker.registry_index_all().unwrap();
+ assert_eq!(indexes.len(), 0);
+ assert_eq!(get_index_names().len(), 0);
+ drop(lock);
+}
+
+#[cargo_test]
+fn clean_gc_dry_run() {
+ // Basic `clean --gc --dry-run` test.
+ let p = basic_foo_bar_project();
+ // Populate the last-use data.
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+
+ let registry_root = paths::home().join(".cargo/registry");
+ let glob_registry = |name| -> PathBuf {
+ let mut paths: Vec<_> = glob::glob(registry_root.join(name).join("*").to_str().unwrap())
+ .unwrap()
+ .map(|p| p.unwrap())
+ .collect();
+ assert_eq!(paths.len(), 1);
+ paths.pop().unwrap()
+ };
+ let index = glob_registry("index").ls_r();
+ let src = glob_registry("src").ls_r();
+ let cache = glob_registry("cache").ls_r();
+ let expected_files = index
+ .iter()
+ .chain(src.iter())
+ .chain(cache.iter())
+ .map(|p| p.to_str().unwrap())
+ .join("\n");
+
+ p.cargo("clean gc --dry-run -v -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stdout_unordered(&expected_files)
+ .with_stderr(
+ "[SUMMARY] [..] files, [..] total\n\
+ [WARNING] no files deleted due to --dry-run",
+ )
+ .run();
+
+ // Again, make sure the information is still tracked.
+ p.cargo("clean gc --dry-run -v -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stdout_unordered(&expected_files)
+ .with_stderr(
+ "[SUMMARY] [..] files, [..] total\n\
+ [WARNING] no files deleted due to --dry-run",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn clean_default_gc() {
+ // `clean gc` without options should also gc
+ let p = basic_foo_bar_project();
+ // Populate the last-use data.
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ p.cargo("clean gc -v -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr_unordered(
+ "\
+[REMOVING] [ROOT]/home/.cargo/registry/index/[..]
+[REMOVING] [ROOT]/home/.cargo/registry/src/[..]
+[REMOVING] [ROOT]/home/.cargo/registry/cache/[..]
+[REMOVED] [..] files, [..] total
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn tracks_sizes() {
+ // Checks that sizes are properly tracked in the db.
+ Package::new("dep1", "1.0.0")
+ .file("src/lib.rs", "")
+ .publish();
+ Package::new("dep2", "1.0.0")
+ .file("src/lib.rs", "")
+ .file("data", &"abcdefghijklmnopqrstuvwxyz".repeat(1000))
+ .publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ dep1 = "1.0"
+ dep2 = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+
+ // Check that the crate sizes are the same as on disk.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let _lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let mut crates = tracker.registry_crate_all().unwrap();
+ crates.sort_by(|a, b| a.0.crate_filename.cmp(&b.0.crate_filename));
+ let db_sizes: Vec<_> = crates.iter().map(|c| c.0.size).collect();
+
+ let mut actual: Vec<_> = p
+ .glob(paths::home().join(".cargo/registry/cache/*/*"))
+ .map(|p| p.unwrap())
+ .collect();
+ actual.sort();
+ let actual_sizes: Vec<_> = actual
+ .iter()
+ .map(|path| std::fs::metadata(path).unwrap().len())
+ .collect();
+ assert_eq!(db_sizes, actual_sizes);
+
+ // Also check the src sizes are computed.
+ let mut srcs = tracker.registry_src_all().unwrap();
+ srcs.sort_by(|a, b| a.0.package_dir.cmp(&b.0.package_dir));
+ let db_sizes: Vec<_> = srcs.iter().map(|c| c.0.size.unwrap()).collect();
+ let mut actual: Vec<_> = p
+ .glob(paths::home().join(".cargo/registry/src/*/*"))
+ .map(|p| p.unwrap())
+ .collect();
+ actual.sort();
+ // .cargo-ok is not tracked in the size.
+ actual.iter().for_each(|p| p.join(".cargo-ok").rm_rf());
+ let actual_sizes: Vec<_> = actual
+ .iter()
+ .map(|path| cargo_util::du(path, &[]).unwrap())
+ .collect();
+ assert_eq!(db_sizes, actual_sizes);
+ assert!(db_sizes[1] > 26000);
+}
+
+#[cargo_test]
+fn max_size() {
+ // Checks --max-crate-size and --max-src-size with various cleaning thresholds.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+
+ let test_crates = [
+ // name, age, crate_size, src_size
+ ("a-1.0.0", 5, 1, 1),
+ ("b-1.0.0", 6, 2, 2),
+ ("c-1.0.0", 3, 3, 3),
+ ("d-1.0.0", 2, 4, 4),
+ ("e-1.0.0", 2, 5, 5),
+ ("f-1.0.0", 9, 6, 6),
+ ("g-1.0.0", 1, 1, 1),
+ ];
+
+ // Determine the order things get deleted so they can be verified.
+ let mut names_by_timestamp: Vec<_> = test_crates
+ .iter()
+ .map(|(name, age, _, _)| (days_ago_unix(*age), name))
+ .collect();
+ names_by_timestamp.sort();
+ let names_by_timestamp: Vec<_> = names_by_timestamp
+ .into_iter()
+ .map(|(_, name)| name)
+ .collect();
+
+ // This exercises the different boundary conditions.
+ for (clean_size, files, bytes) in [
+ (22, 0, 0),
+ (21, 1, 6),
+ (16, 1, 6),
+ (15, 2, 8),
+ (14, 2, 8),
+ (13, 3, 9),
+ (12, 4, 12),
+ (10, 4, 12),
+ (9, 5, 16),
+ (6, 5, 16),
+ (5, 6, 21),
+ (1, 6, 21),
+ (0, 7, 22),
+ ] {
+ let (removed, kept) = names_by_timestamp.split_at(files);
+ // --max-crate-size
+ let (cache_dir, src_dir) = populate_cache(&config, &test_crates);
+ let mut stderr = String::new();
+ for name in removed {
+ writeln!(stderr, "[REMOVING] [..]{name}.crate").unwrap();
+ }
+ let total_display = if removed.is_empty() {
+ String::new()
+ } else {
+ format!(", {bytes}B total")
+ };
+ let files_display = if files == 1 {
+ format!("1 file")
+ } else {
+ format!("{files} files")
+ };
+ write!(stderr, "[REMOVED] {files_display}{total_display}").unwrap();
+ cargo_process(&format!("clean gc -Zgc -v --max-crate-size={clean_size}"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr_unordered(&stderr)
+ .run();
+ for name in kept {
+ assert!(cache_dir.join(format!("{name}.crate")).exists());
+ }
+ for name in removed {
+ assert!(!cache_dir.join(format!("{name}.crate")).exists());
+ }
+
+ // --max-src-size
+ populate_cache(&config, &test_crates);
+ let mut stderr = String::new();
+ for name in removed {
+ writeln!(stderr, "[REMOVING] [..]{name}").unwrap();
+ }
+ let total_display = if files == 0 {
+ String::new()
+ } else {
+ format!(", {bytes}B total")
+ };
+ write!(stderr, "[REMOVED] {files_display}{total_display}").unwrap();
+ cargo_process(&format!("clean gc -Zgc -v --max-src-size={clean_size}"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr_unordered(&stderr)
+ .run();
+ for name in kept {
+ assert!(src_dir.join(name).exists());
+ }
+ for name in removed {
+ assert!(!src_dir.join(name).exists());
+ }
+ }
+}
+
+#[cargo_test]
+fn max_size_untracked_crate() {
+ // When a .crate file exists from an older version of cargo that did not
+ // track sizes, `clean --max-crate-size` should populate the db with the
+ // sizes.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let cache = paths::home().join(".cargo/registry/cache/example.com-a6c4a5adcb232b9a");
+ cache.mkdir_p();
+ paths::home()
+ .join(".cargo/registry/index/example.com-a6c4a5adcb232b9a")
+ .mkdir_p();
+ // Create the `.crate files.
+ let test_crates = [
+ // name, size
+ ("a-1.0.0.crate", 1234),
+ ("b-1.0.0.crate", 42),
+ ("c-1.0.0.crate", 0),
+ ];
+ for (name, size) in test_crates {
+ std::fs::write(cache.join(name), "x".repeat(size as usize)).unwrap()
+ }
+ // This should scan the directory and populate the db with the size information.
+ cargo_process("clean gc -Zgc -v --max-crate-size=100000")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[REMOVED] 0 files")
+ .run();
+ // Check that it stored the size data.
+ let _lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let crates = tracker.registry_crate_all().unwrap();
+ let mut actual: Vec<_> = crates
+ .iter()
+ .map(|(rc, _time)| (rc.crate_filename.as_str(), rc.size))
+ .collect();
+ actual.sort();
+ assert_eq!(test_crates, actual.as_slice());
+}
+
+/// Helper to prepare the max-size test.
+fn max_size_untracked_prepare() -> (Config, Project) {
+ // First, publish and download a dependency.
+ let p = basic_foo_bar_project();
+ p.cargo("fetch").run();
+ // Pretend it was an older version that did not track last-use.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .rm_rf();
+ (config, p)
+}
+
+/// Helper to verify the max-size test.
+fn max_size_untracked_verify(config: &Config) {
+ let actual: Vec<_> = glob::glob(
+ paths::home()
+ .join(".cargo/registry/src/*/*")
+ .to_str()
+ .unwrap(),
+ )
+ .unwrap()
+ .map(|p| p.unwrap())
+ .collect();
+ assert_eq!(actual.len(), 1);
+ let actual_size = cargo_util::du(&actual[0], &[]).unwrap();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), 1);
+ assert_eq!(srcs[0].0.size, Some(actual_size));
+ drop(lock);
+}
+
+#[cargo_test]
+fn max_size_untracked_src_from_use() {
+ // When a src directory exists from an older version of cargo that did not
+ // track sizes, doing a build should populate the db with an entry with an
+ // unknown size. `clean --max-src-size` should then fix the size.
+ let (config, p) = max_size_untracked_prepare();
+
+ // Run a command that will update the db with an unknown src size.
+ p.cargo("tree -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ // Check that it is None.
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), 1);
+ assert_eq!(srcs[0].0.size, None);
+ drop(lock);
+
+ // Fix the size.
+ p.cargo("clean gc -v --max-src-size=10000 -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[REMOVED] 0 files")
+ .run();
+ max_size_untracked_verify(&config);
+}
+
+#[cargo_test]
+fn max_size_untracked_src_from_clean() {
+ // When a src directory exists from an older version of cargo that did not
+ // track sizes, `clean --max-src-size` should populate the db with the
+ // sizes.
+ let (config, p) = max_size_untracked_prepare();
+
+ // Clean should scan the src and update the db.
+ p.cargo("clean gc -v --max-src-size=10000 -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[REMOVED] 0 files")
+ .run();
+ max_size_untracked_verify(&config);
+}
+
+#[cargo_test]
+fn max_download_size() {
+ // --max-download-size
+ //
+ // This creates some sample crates of specific sizes, and then tries
+ // deleting at various specific size thresholds that exercise different
+ // edge conditions.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+
+ let test_crates = [
+ // name, age, crate_size, src_size
+ ("d-1.0.0", 4, 4, 5),
+ ("c-1.0.0", 3, 3, 3),
+ ("a-1.0.0", 1, 2, 5),
+ ("b-1.0.0", 1, 1, 7),
+ ];
+
+ for (max_size, num_deleted, files_deleted, bytes) in [
+ (30, 0, 0, 0),
+ (29, 1, 1, 5),
+ (24, 2, 2, 9),
+ (20, 3, 3, 12),
+ (1, 7, 7, 29),
+ (0, 8, 8, 30),
+ ] {
+ populate_cache(&config, &test_crates);
+ // Determine the order things will be deleted.
+ let delete_order: Vec<String> = test_crates
+ .iter()
+ .flat_map(|(name, _, _, _)| [name.to_string(), format!("{name}.crate")])
+ .collect();
+ let (removed, _kept) = delete_order.split_at(num_deleted);
+ let mut stderr = String::new();
+ for name in removed {
+ writeln!(stderr, "[REMOVING] [..]{name}").unwrap();
+ }
+ let files_display = if files_deleted == 1 {
+ format!("1 file")
+ } else {
+ format!("{files_deleted} files")
+ };
+ let total_display = if removed.is_empty() {
+ String::new()
+ } else {
+ format!(", {bytes}B total")
+ };
+ write!(stderr, "[REMOVED] {files_display}{total_display}",).unwrap();
+ cargo_process(&format!("clean gc -Zgc -v --max-download-size={max_size}"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr_unordered(&stderr)
+ .run();
+ }
+}
+
+#[cargo_test]
+fn package_cache_lock_during_build() {
+ // Verifies that a shared lock is held during a build. Resolution and
+ // downloads should be OK while that is held, but mutation should block.
+ //
+ // This works by launching a build with a build script that will pause.
+ // Then it performs other cargo commands and verifies their behavior.
+ Package::new("bar", "1.0.0").publish();
+ let p_foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "build.rs",
+ r#"
+ fn main() {
+ std::fs::write("blocking", "").unwrap();
+ let path = std::path::Path::new("ready");
+ loop {
+ if path.exists() {
+ break;
+ } else {
+ std::thread::sleep(std::time::Duration::from_millis(100))
+ }
+ }
+ }
+ "#,
+ )
+ .build();
+ let p_foo2 = project()
+ .at("foo2")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo2"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ // Start a build that will pause once the build starts.
+ let mut foo_child = p_foo
+ .cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .build_command()
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .spawn()
+ .unwrap();
+
+ // Wait for it to enter build script.
+ retry(100, || p_foo.root().join("blocking").exists().then_some(()));
+
+ // Start a build with a different target directory. It should not block,
+ // even though it gets a download lock, and then a shared lock.
+ //
+ // Also verify that auto-gc gets disabled.
+ p_foo2
+ .cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("CARGO_GC_AUTO_FREQUENCY", "always")
+ .env("CARGO_LOG", "gc=debug")
+ .with_stderr_contains("[UPDATING] `dummy-registry` index")
+ .with_stderr_contains("[CHECKING] bar v1.0.0")
+ .with_stderr_contains("[CHECKING] foo2 v0.1.0 [..]")
+ .with_stderr_contains("[FINISHED] [..]")
+ .with_stderr_contains("[..]unable to acquire mutate lock, auto gc disabled")
+ .run();
+
+ // Ensure that the first build really blocked.
+ assert!(matches!(foo_child.try_wait(), Ok(None)));
+
+ // Cleaning while a command is running should block.
+ let mut clean_cmd = p_foo2
+ .cargo("clean gc --max-download-size=0 -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .build_command();
+ clean_cmd.stderr(Stdio::piped());
+ let mut clean_child = clean_cmd.spawn().unwrap();
+
+ // Give the clean command a chance to finish (it shouldn't).
+ sleep_ms(500);
+ // They should both still be running.
+ assert!(matches!(foo_child.try_wait(), Ok(None)));
+ assert!(matches!(clean_child.try_wait(), Ok(None)));
+
+ // Let the original build finish.
+ p_foo.change_file("ready", "");
+
+ // Wait for clean to finish.
+ let thread = std::thread::spawn(|| clean_child.wait_with_output().unwrap());
+ let output = thread_wait_timeout(100, thread);
+ assert!(output.status.success());
+ // Validate the output of the clean.
+ execs()
+ .with_stderr(
+ "\
+[BLOCKING] waiting for file lock on package cache mutation
+[REMOVED] [..]
+",
+ )
+ .run_output(&output);
+}
+
+#[cargo_test]
+fn read_only_locking_auto_gc() {
+ // Tests the behavior for auto-gc on a read-only directory.
+ let p = basic_foo_bar_project();
+ // Populate cache.
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ let cargo_home = paths::home().join(".cargo");
+ let mut perms = std::fs::metadata(&cargo_home).unwrap().permissions();
+ // Test when it can't update auto-gc db.
+ perms.set_readonly(true);
+ std::fs::set_permissions(&cargo_home, perms.clone()).unwrap();
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[CHECKING] bar v1.0.0
+[CHECKING] foo v0.1.0 [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+ // Try again without the last-use existing (such as if the cache was
+ // populated by an older version of cargo).
+ perms.set_readonly(false);
+ std::fs::set_permissions(&cargo_home, perms.clone()).unwrap();
+ let config = ConfigBuilder::new().build();
+ GlobalCacheTracker::db_path(&config)
+ .into_path_unlocked()
+ .rm_rf();
+ perms.set_readonly(true);
+ std::fs::set_permissions(&cargo_home, perms.clone()).unwrap();
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[FINISHED] [..]")
+ .run();
+ perms.set_readonly(false);
+ std::fs::set_permissions(&cargo_home, perms).unwrap();
+}
+
+#[cargo_test]
+fn delete_index_also_deletes_crates() {
+ // Checks that when an index is delete that src and cache directories also get deleted.
+ let p = basic_foo_bar_project();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+
+ assert_eq!(get_registry_names("src"), ["bar-1.0.0"]);
+ assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]);
+
+ p.cargo("clean gc")
+ .arg("--max-index-age=0 days")
+ .arg("-Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[REMOVED] [..]")
+ .run();
+
+ assert_eq!(get_registry_names("src").len(), 0);
+ assert_eq!(get_registry_names("cache").len(), 0);
+}
+
+#[cargo_test]
+fn clean_syncs_missing_files() {
+ // When files go missing in the cache, clean operations that need to track
+ // the size should also remove them from the database.
+ Package::new("bar", "1.0.0").publish();
+ Package::new("baz", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ baz = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+
+ // Verify things are tracked.
+ let config = ConfigBuilder::new().unstable_flag("gc").build();
+ let lock = config
+ .acquire_package_cache_lock(CacheLockMode::MutateExclusive)
+ .unwrap();
+ let tracker = GlobalCacheTracker::new(&config).unwrap();
+ let crates = tracker.registry_crate_all().unwrap();
+ assert_eq!(crates.len(), 2);
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), 2);
+ drop(lock);
+
+ // Remove the files.
+ for pattern in [
+ ".cargo/registry/cache/*/bar-1.0.0.crate",
+ ".cargo/registry/src/*/bar-1.0.0",
+ ] {
+ p.glob(paths::home().join(pattern))
+ .map(|p| p.unwrap())
+ .next()
+ .unwrap()
+ .rm_rf();
+ }
+
+ // Clean should update the db.
+ p.cargo("clean gc -v --max-download-size=1GB -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[REMOVED] 0 files")
+ .run();
+
+ // Verify
+ let crates = tracker.registry_crate_all().unwrap();
+ assert_eq!(crates.len(), 1);
+ let srcs = tracker.registry_src_all().unwrap();
+ assert_eq!(srcs.len(), 1);
+}
+
+#[cargo_test]
+fn offline_doesnt_auto_gc() {
+ // When running offline, auto-gc shouldn't run.
+ let p = basic_foo_bar_project();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ // Remove the dependency.
+ p.change_file("Cargo.toml", &basic_manifest("foo", "0.1.0"));
+ // Run offline, make sure it doesn't delete anything
+ p.cargo("check --offline -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[CHECKING] foo v0.1.0[..]\n[FINISHED][..]")
+ .run();
+ assert_eq!(get_registry_names("src"), ["bar-1.0.0"]);
+ assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]);
+ // Run online, make sure auto-gc runs.
+ p.cargo("check -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[FINISHED][..]")
+ .run();
+ assert_eq!(get_registry_names("src"), &[] as &[String]);
+ assert_eq!(get_registry_names("cache"), &[] as &[String]);
+}
+
+#[cargo_test]
+fn can_handle_future_schema() -> anyhow::Result<()> {
+ // It should work when a future version of cargo has made schema changes
+ // to the database.
+ let p = basic_foo_bar_project();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ // Modify the schema to pretend this is done by a future version of cargo.
+ let config = ConfigBuilder::new().build();
+ let db_path = GlobalCacheTracker::db_path(&config).into_path_unlocked();
+ let conn = rusqlite::Connection::open(&db_path)?;
+ let user_version: u32 =
+ conn.query_row("SELECT user_version FROM pragma_user_version", [], |row| {
+ row.get(0)
+ })?;
+ conn.execute("ALTER TABLE global_data ADD COLUMN foo DEFAULT 123", [])?;
+ conn.pragma_update(None, "user_version", &(user_version + 1))?;
+ drop(conn);
+ // Verify it doesn't blow up.
+ p.cargo("clean gc --max-download-size=0 -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr("[REMOVED] 4 files, [..] total")
+ .run();
+ Ok(())
+}
+
+#[cargo_test]
+fn clean_max_git_age() {
+ // --max-git-*-age flags
+ let (git_a, git_a_repo) = git::new_repo("git_a", |p| {
+ p.file("Cargo.toml", &basic_manifest("git_a", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ git_a = {{ git = '{}' }}
+ "#,
+ git_a.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+ // Populate last-use tracking.
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(4))
+ .run();
+ // Update git_a to create a separate checkout.
+ git_a.change_file("src/lib.rs", "// test");
+ git::add(&git_a_repo);
+ git::commit(&git_a_repo);
+ // Update last-use tracking, where the first git checkout will stay "old".
+ p.cargo("update -p git_a -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2))
+ .with_stderr(
+ "\
+[UPDATING] git repository [..]
+[UPDATING] git_a v1.0.0 [..]
+",
+ )
+ .run();
+
+ let db_names = get_git_db_names();
+ assert_eq!(db_names.len(), 1);
+ let db_name = &db_names[0];
+ let co_names = get_git_checkout_names(&db_name);
+ assert_eq!(co_names.len(), 2);
+
+ // Delete the first checkout
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-git-co-age=3 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[..]/[..]
+[REMOVED] [..]
+",
+ )
+ .run();
+
+ let db_names = get_git_db_names();
+ assert_eq!(db_names.len(), 1);
+ let co_names = get_git_checkout_names(&db_name);
+ assert_eq!(co_names.len(), 1);
+
+ // delete the second checkout
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-git-co-age=0 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[..]/[..]
+[REMOVED] [..]
+",
+ )
+ .run();
+
+ let db_names = get_git_db_names();
+ assert_eq!(db_names.len(), 1);
+ let co_names = get_git_checkout_names(&db_name);
+ assert_eq!(co_names.len(), 0);
+
+ // delete the db
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-git-db-age=1 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/db/git_a-[..]
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[..]
+[REMOVED] [..]
+",
+ )
+ .run();
+
+ let db_names = get_git_db_names();
+ assert_eq!(db_names.len(), 0);
+ let co_names = get_git_checkout_names(&db_name);
+ assert_eq!(co_names.len(), 0);
+}
+
+#[cargo_test]
+fn clean_max_src_crate_age() {
+ // --max-src-age and --max-crate-age flags
+ let p = basic_foo_bar_project();
+ // Populate last-use tracking.
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(4))
+ .run();
+ // Update bar to create a separate copy with a different timestamp.
+ Package::new("bar", "1.0.1").publish();
+ p.cargo("update -p bar -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2))
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[UPDATING] bar v1.0.0 -> v1.0.1
+",
+ )
+ .run();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2))
+ .with_stderr(
+ "\
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.0.1 [..]
+",
+ )
+ .run();
+
+ assert_eq!(get_registry_names("src"), ["bar-1.0.0", "bar-1.0.1"]);
+ assert_eq!(
+ get_registry_names("cache"),
+ ["bar-1.0.0.crate", "bar-1.0.1.crate"]
+ );
+
+ // Delete the old src.
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-src-age=3 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [..]/bar-1.0.0
+[REMOVED] [..]
+",
+ )
+ .run();
+
+ // delete the second src
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-src-age=0 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [..]/bar-1.0.1
+[REMOVED] [..]
+",
+ )
+ .run();
+
+ // delete the old crate
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-crate-age=3 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [..]/bar-1.0.0.crate
+[REMOVED] [..]
+",
+ )
+ .run();
+
+ // delete the seecond crate
+ p.cargo("clean gc -v -Zgc")
+ .arg("--max-crate-age=0 days")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [..]/bar-1.0.1.crate
+[REMOVED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn clean_max_git_size() {
+ // clean --max-git-size
+ //
+ // Creates two checkouts. The sets a size threshold to delete one. And
+ // then with 0 max size to delete everything.
+ let (git_project, git_repo) = git::new_repo("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ git = '{}' }}
+ "#,
+ git_project.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+ // Fetch and populate db.
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(3))
+ .run();
+
+ // Figure out the name of the first checkout.
+ let git_root = paths::home().join(".cargo/git");
+ let db_names = get_git_db_names();
+ assert_eq!(db_names.len(), 1);
+ let db_name = &db_names[0];
+ let co_names = get_git_checkout_names(&db_name);
+ assert_eq!(co_names.len(), 1);
+ let first_co_name = &co_names[0];
+
+ // Make an update and create a new checkout.
+ git_project.change_file("src/lib.rs", "// modified");
+ git::add(&git_repo);
+ git::commit(&git_repo);
+ p.cargo("update -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ // Use a different time so that the first checkout timestamp is less
+ // than the second.
+ .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2))
+ .run();
+
+ // Figure out the threshold to use.
+ let mut co_names = get_git_checkout_names(&db_name);
+ assert_eq!(co_names.len(), 2);
+ co_names.retain(|name| name != first_co_name);
+ assert_eq!(co_names.len(), 1);
+ let second_co_name = &co_names[0];
+ let second_co_path = git_root
+ .join("checkouts")
+ .join(db_name)
+ .join(second_co_name);
+ let second_co_size = cargo_util::du(&second_co_path, &["!.git"]).unwrap();
+
+ let db_size = cargo_util::du(&git_root.join("db").join(db_name), &[]).unwrap();
+
+ let threshold = db_size + second_co_size;
+
+ p.cargo(&format!("clean gc --max-git-size={threshold} -Zgc -v"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(&format!(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/{db_name}/{first_co_name}
+[REMOVED] [..]
+"
+ ))
+ .run();
+
+ // And then try cleaning everything.
+ p.cargo("clean gc --max-git-size=0 -Zgc -v")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr_unordered(&format!(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/{db_name}/{second_co_name}
+[REMOVING] [ROOT]/home/.cargo/git/db/{db_name}
+[REMOVED] [..]
+"
+ ))
+ .run();
+}
+
+// Helper for setting up fake git sizes for git size cleaning.
+fn setup_fake_git_sizes(db_name: &str, db_size: usize, co_sizes: &[usize]) {
+ let base_git = paths::home().join(".cargo/git");
+ let db_path = base_git.join("db").join(db_name);
+ db_path.mkdir_p();
+ std::fs::write(db_path.join("test"), "x".repeat(db_size)).unwrap();
+ let base_co = base_git.join("checkouts").join(db_name);
+ for (i, size) in co_sizes.iter().enumerate() {
+ let co_name = format!("co{i}");
+ let co_path = base_co.join(co_name);
+ co_path.mkdir_p();
+ std::fs::write(co_path.join("test"), "x".repeat(*size)).unwrap();
+ }
+}
+
+#[cargo_test]
+fn clean_max_git_size_untracked() {
+ // If there are git directories that aren't tracked in the database,
+ // `--max-git-size` should pick it up.
+ //
+ // The db_name of "example" depends on the sorting order of the names ("e"
+ // should be after "c"), so that the db comes after the checkouts.
+ setup_fake_git_sizes("example", 5000, &[1000, 2000]);
+ cargo_process(&format!("clean gc -Zgc -v --max-git-size=7000"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/example/co0
+[REMOVED] [..]
+",
+ )
+ .run();
+ cargo_process(&format!("clean gc -Zgc -v --max-git-size=5000"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/example/co1
+[REMOVED] [..]
+",
+ )
+ .run();
+ cargo_process(&format!("clean gc -Zgc -v --max-git-size=0"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/db/example
+[REMOVED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn clean_max_git_size_deletes_co_from_db() {
+ // In the scenario where it thinks it needs to delete the db, it should
+ // also delete all the checkouts.
+ //
+ // The db_name of "abc" depends on the sorting order of the names ("a"
+ // should be before "c"), so that the db comes before the checkouts.
+ setup_fake_git_sizes("abc", 5000, &[1000, 2000]);
+ // This deletes everything because it tries to delete the db, which then
+ // deletes all checkouts.
+ cargo_process(&format!("clean gc -Zgc -v --max-git-size=3000"))
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/db/abc
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/abc/co1
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/abc/co0
+[REMOVED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn handles_missing_index() {
+ // Checks behavior when index is missing.
+ let p = basic_foo_bar_project();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ paths::home().join(".cargo/registry/index").rm_rf();
+ cargo_process("clean gc -v --max-download-size=0 -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr_unordered(
+ "\
+[REMOVING] [ROOT]/home/.cargo/registry/cache/[..]
+[REMOVING] [ROOT]/home/.cargo/registry/src/[..]
+[REMOVED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn handles_missing_git_db() {
+ // Checks behavior when git db is missing.
+ let git_project = git::new("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ git = '{}' }}
+ "#,
+ git_project.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .run();
+ paths::home().join(".cargo/git/db").rm_rf();
+ cargo_process("clean gc -v --max-git-size=0 -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stderr(
+ "\
+[REMOVING] [ROOT]/home/.cargo/git/checkouts/[..]
+[REMOVED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn clean_gc_quiet_is_quiet() {
+ // Checks that --quiet works with `cargo clean gc`, since there was a
+ // subtle issue with how the flag is defined as a global flag.
+ let p = basic_foo_bar_project();
+ p.cargo("fetch -Zgc")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4))
+ .run();
+ p.cargo("clean gc --quiet -Zgc --dry-run")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stdout("")
+ .with_stderr("")
+ .run();
+ // Verify exact same command without -q would actually display something.
+ p.cargo("clean gc -Zgc --dry-run")
+ .masquerade_as_nightly_cargo(&["gc"])
+ .with_stdout("")
+ .with_stderr(
+ "\
+[SUMMARY] [..] files, [..] total
+[WARNING] no files deleted due to --dry-run
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/install.rs b/src/tools/cargo/tests/testsuite/install.rs
index fd53b607b..16ed32ee7 100644
--- a/src/tools/cargo/tests/testsuite/install.rs
+++ b/src/tools/cargo/tests/testsuite/install.rs
@@ -3,6 +3,7 @@
use std::fs::{self, OpenOptions};
use std::io::prelude::*;
use std::path::Path;
+use std::thread;
use cargo_test_support::compare;
use cargo_test_support::cross_compile;
@@ -11,10 +12,10 @@ use cargo_test_support::registry::{self, registry_path, Package};
use cargo_test_support::{
basic_manifest, cargo_process, no_such_file_err_msg, project, project_in, symlink_supported, t,
};
-use cargo_util::ProcessError;
+use cargo_util::{ProcessBuilder, ProcessError};
use cargo_test_support::install::{
- assert_has_installed_exe, assert_has_not_installed_exe, cargo_home,
+ assert_has_installed_exe, assert_has_not_installed_exe, cargo_home, exe,
};
use cargo_test_support::paths::{self, CargoPathExt};
use std::env;
@@ -1010,7 +1011,7 @@ fn compile_failure() {
.with_status(101)
.with_stderr_contains(
"\
-[ERROR] could not compile `foo` (bin \"foo\") due to previous error
+[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error
[ERROR] failed to compile `foo v0.0.1 ([..])`, intermediate artifacts can be \
found at `[..]target`.\nTo reuse those artifacts with a future compilation, \
set the environment variable `CARGO_TARGET_DIR` to that path.
@@ -2507,3 +2508,118 @@ fn install_incompat_msrv() {
")
.with_status(101).run();
}
+
+fn assert_tracker_noexistence(key: &str) {
+ let v1_data: toml::Value =
+ toml::from_str(&fs::read_to_string(cargo_home().join(".crates.toml")).unwrap()).unwrap();
+ let v2_data: serde_json::Value =
+ serde_json::from_str(&fs::read_to_string(cargo_home().join(".crates2.json")).unwrap())
+ .unwrap();
+
+ assert!(v1_data["v1"].get(key).is_none());
+ assert!(v2_data["installs"][key].is_null());
+}
+
+#[cargo_test]
+fn uninstall_running_binary() {
+ use std::io::Write;
+
+ Package::new("foo", "0.0.1")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#,
+ )
+ .file(
+ "src/main.rs",
+ r#"
+ use std::net::TcpStream;
+ use std::env::var;
+ use std::io::Read;
+ fn main() {
+ for i in 0..2 {
+ TcpStream::connect(&var("__ADDR__").unwrap()[..])
+ .unwrap()
+ .read_to_end(&mut Vec::new())
+ .unwrap();
+ }
+ }
+ "#,
+ )
+ .publish();
+
+ cargo_process("install foo")
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] foo v0.0.1 (registry [..])
+[INSTALLING] foo v0.0.1
+[COMPILING] foo v0.0.1
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
+[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
+[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ )
+ .run();
+ assert_has_installed_exe(cargo_home(), "foo");
+
+ let foo_bin = cargo_home().join("bin").join(exe("foo"));
+ let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = l.local_addr().unwrap().to_string();
+ let t = thread::spawn(move || {
+ ProcessBuilder::new(foo_bin)
+ .env("__ADDR__", addr)
+ .exec()
+ .unwrap();
+ });
+ let key = "foo 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)";
+
+ #[cfg(windows)]
+ {
+ // Ensure foo is running before the first `cargo uninstall` call
+ l.accept().unwrap().0.write_all(&[1]).unwrap();
+ cargo_process("uninstall foo")
+ .with_status(101)
+ .with_stderr_contains("[ERROR] failed to remove file `[CWD]/home/.cargo/bin/foo[EXE]`")
+ .run();
+ // Ensure foo is stopped before the second `cargo uninstall` call
+ l.accept().unwrap().0.write_all(&[1]).unwrap();
+ t.join().unwrap();
+ cargo_process("uninstall foo")
+ .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
+ .run();
+ };
+
+ #[cfg(not(windows))]
+ {
+ // Ensure foo is running before the first `cargo uninstall` call
+ l.accept().unwrap().0.write_all(&[1]).unwrap();
+ cargo_process("uninstall foo")
+ .with_stderr("[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]")
+ .run();
+ l.accept().unwrap().0.write_all(&[1]).unwrap();
+ t.join().unwrap();
+ };
+
+ assert_has_not_installed_exe(cargo_home(), "foo");
+ assert_tracker_noexistence(key);
+
+ cargo_process("install foo")
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[INSTALLING] foo v0.0.1
+[COMPILING] foo v0.0.1
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
+[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)
+[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/main.rs b/src/tools/cargo/tests/testsuite/main.rs
index 07f749e34..8e2d6dedf 100644
--- a/src/tools/cargo/tests/testsuite/main.rs
+++ b/src/tools/cargo/tests/testsuite/main.rs
@@ -1,6 +1,6 @@
-// See src/cargo/lib.rs for notes on these lint settings.
-#![warn(rust_2018_idioms)]
-#![allow(clippy::all)]
+#![allow(clippy::disallowed_methods)]
+#![allow(clippy::print_stderr)]
+#![allow(clippy::print_stdout)]
#[macro_use]
extern crate cargo_test_macro;
@@ -98,6 +98,7 @@ mod git_auth;
mod git_gc;
mod git_shallow;
mod glob_targets;
+mod global_cache_tracker;
mod help;
mod https;
mod inheritable_workspace_fields;
diff --git a/src/tools/cargo/tests/testsuite/messages.rs b/src/tools/cargo/tests/testsuite/messages.rs
index 2c534d8f0..fb92593bc 100644
--- a/src/tools/cargo/tests/testsuite/messages.rs
+++ b/src/tools/cargo/tests/testsuite/messages.rs
@@ -136,7 +136,7 @@ fn deduplicate_errors() {
.with_stderr(&format!(
"\
[COMPILING] foo v0.0.1 [..]
-{}error: could not compile `foo` (lib) due to previous error
+{}error: could not compile `foo` (lib) due to 1 previous error
",
rustc_message
))
diff --git a/src/tools/cargo/tests/testsuite/metabuild.rs b/src/tools/cargo/tests/testsuite/metabuild.rs
index 022d0bff0..1c0196c98 100644
--- a/src/tools/cargo/tests/testsuite/metabuild.rs
+++ b/src/tools/cargo/tests/testsuite/metabuild.rs
@@ -740,6 +740,7 @@ fn metabuild_failed_build_json() {
r#"
{
"message": {
+ "$message_type": "diagnostic",
"children": "{...}",
"code": "{...}",
"level": "error",
diff --git a/src/tools/cargo/tests/testsuite/package.rs b/src/tools/cargo/tests/testsuite/package.rs
index 4ec4fc0d6..371157e4e 100644
--- a/src/tools/cargo/tests/testsuite/package.rs
+++ b/src/tools/cargo/tests/testsuite/package.rs
@@ -5,6 +5,7 @@ use cargo_test_support::publish::validate_crate_contents;
use cargo_test_support::registry::{self, Package};
use cargo_test_support::{
basic_manifest, cargo_process, git, path2url, paths, project, symlink_supported, t,
+ ProjectBuilder,
};
use flate2::read::GzDecoder;
use std::fs::{self, read_to_string, File};
@@ -54,7 +55,19 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[WARNING] manifest has no documentation[..]
+See [..]
+[PACKAGING] foo v0.0.1 ([CWD])
+[VERIFYING] foo v0.0.1 ([CWD])
+[COMPILING] foo v0.0.1 ([CWD][..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[PACKAGED] 4 files, [..] ([..] compressed)
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
validate_crate_contents(
@@ -695,6 +708,7 @@ fn ignore_nested() {
authors = []
license = "MIT"
description = "foo"
+ homepage = "https://example.com/"
"#;
let main_rs = r#"
fn main() { println!("hello"); }
@@ -711,8 +725,6 @@ fn ignore_nested() {
p.cargo("package")
.with_stderr(
"\
-[WARNING] manifest has no documentation[..]
-See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
[PACKAGING] foo v0.0.1 ([CWD])
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
@@ -732,7 +744,17 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[PACKAGING] foo v0.0.1 ([CWD])
+[VERIFYING] foo v0.0.1 ([CWD])
+[COMPILING] foo v0.0.1 ([CWD][..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[PACKAGED] 4 files, [..] ([..] compressed)
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
validate_crate_contents(
@@ -2730,6 +2752,7 @@ fn basic_filesizes() {
exclude = ["*.txt"]
license = "MIT"
description = "foo"
+ homepage = "https://example.com/"
"#;
let main_rs_contents = r#"fn main() { println!("🦀"); }"#;
let cargo_toml_contents = format!(
@@ -2740,6 +2763,7 @@ version = "0.0.1"
authors = []
exclude = ["*.txt"]
description = "foo"
+homepage = "https://example.com/"
license = "MIT"
"#,
cargo::core::package::MANIFEST_PREAMBLE
@@ -2775,7 +2799,17 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[PACKAGING] foo v0.0.1 [..]
+[VERIFYING] foo v0.0.1 [..]
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] [..]
+[PACKAGED] 4 files[..]
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
let compressed_size = f.metadata().unwrap().len();
@@ -2802,6 +2836,7 @@ fn larger_filesizes() {
authors = []
license = "MIT"
description = "foo"
+ documentation = "https://example.com/"
"#;
let lots_of_crabs = std::iter::repeat("🦀").take(1337).collect::<String>();
let main_rs_contents = format!(r#"fn main() {{ println!("{}"); }}"#, lots_of_crabs);
@@ -2820,6 +2855,7 @@ name = "foo"
version = "0.0.1"
authors = []
description = "foo"
+documentation = "https://example.com/"
license = "MIT"
"#,
cargo::core::package::MANIFEST_PREAMBLE
@@ -2857,7 +2893,17 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[PACKAGING] foo v0.0.1 [..]
+[VERIFYING] foo v0.0.1 [..]
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] [..]
+[PACKAGED] 5 files, [..]
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
let compressed_size = f.metadata().unwrap().len();
@@ -2895,6 +2941,7 @@ fn symlink_filesizes() {
authors = []
license = "MIT"
description = "foo"
+ homepage = "https://example.com/"
"#;
let lots_of_crabs = std::iter::repeat("🦀").take(1337).collect::<String>();
let main_rs_contents = format!(r#"fn main() {{ println!("{}"); }}"#, lots_of_crabs);
@@ -2913,6 +2960,7 @@ name = "foo"
version = "0.0.1"
authors = []
description = "foo"
+homepage = "https://example.com/"
license = "MIT"
"#,
cargo::core::package::MANIFEST_PREAMBLE
@@ -2955,7 +3003,17 @@ src/main.rs.bak
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[PACKAGING] foo v0.0.1 [..]
+[VERIFYING] foo v0.0.1 [..]
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] [..]
+[PACKAGED] 7 files, [..]
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
let compressed_size = f.metadata().unwrap().len();
@@ -3031,7 +3089,19 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[WARNING] manifest has no documentation[..]
+See [..]
+[PACKAGING] foo v0.0.1 ([CWD])
+[VERIFYING] foo v0.0.1 ([CWD])
+[COMPILING] foo v0.0.1 ([CWD][..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[PACKAGED] 4 files, [..] ([..] compressed)
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
validate_crate_contents(
@@ -3085,7 +3155,19 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[WARNING] manifest has no documentation[..]
+See [..]
+[PACKAGING] foo v0.0.1 ([CWD])
+[VERIFYING] foo v0.0.1 ([CWD])
+[COMPILING] foo v0.0.1 ([CWD][..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[PACKAGED] 4 files, [..] ([..] compressed)
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
validate_crate_contents(
@@ -3132,3 +3214,142 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for
&[],
);
}
+
+#[cargo_test]
+fn include_files_called_target_project() {
+ // https://github.com/rust-lang/cargo/issues/12790
+ // files and folders called "target" should be included, unless they're the actual target directory
+ let p = init_and_add_inner_target(project())
+ .file("target/foo.txt", "")
+ .build();
+
+ p.cargo("package -l")
+ .with_stdout(
+ "\
+Cargo.lock
+Cargo.toml
+Cargo.toml.orig
+data/not_target
+data/target
+derp/not_target/foo.txt
+derp/target/foo.txt
+src/main.rs
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn include_files_called_target_git() {
+ // https://github.com/rust-lang/cargo/issues/12790
+ // files and folders called "target" should be included, unless they're the actual target directory
+ let (p, repo) = git::new_repo("foo", |p| init_and_add_inner_target(p));
+ // add target folder but not committed.
+ _ = fs::create_dir(p.build_dir()).unwrap();
+ _ = fs::write(p.build_dir().join("foo.txt"), "").unwrap();
+ p.cargo("package -l")
+ .with_stdout(
+ "\
+.cargo_vcs_info.json
+Cargo.lock
+Cargo.toml
+Cargo.toml.orig
+data/not_target
+data/target
+derp/not_target/foo.txt
+derp/target/foo.txt
+src/main.rs
+",
+ )
+ .run();
+
+ // if target is committed, it should be include.
+ git::add(&repo);
+ git::commit(&repo);
+ p.cargo("package -l")
+ .with_stdout(
+ "\
+.cargo_vcs_info.json
+Cargo.lock
+Cargo.toml
+Cargo.toml.orig
+data/not_target
+data/target
+derp/not_target/foo.txt
+derp/target/foo.txt
+src/main.rs
+target/foo.txt
+",
+ )
+ .run();
+}
+
+fn init_and_add_inner_target(p: ProjectBuilder) -> ProjectBuilder {
+ p.file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#,
+ )
+ .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
+ // file called target, should be included
+ .file("data/target", "")
+ .file("data/not_target", "")
+ // folder called target, should be included
+ .file("derp/target/foo.txt", "")
+ .file("derp/not_target/foo.txt", "")
+}
+
+#[cargo_test]
+fn build_script_outside_pkg_root() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ license = "MIT"
+ description = "foo"
+ authors = []
+ build = "../t_custom_build/custom_build.rs"
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ let mut expect_msg = String::from("\
+warning: manifest has no documentation, homepage or repository.
+See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
+error: the source file of build script doesn't appear to exist.
+This may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files.
+Please update the `build` setting in the manifest at `[CWD]/Cargo.toml` and point to a path inside the root of the package.
+");
+ // custom_build.rs does not exist
+ p.cargo("package -l")
+ .with_status(101)
+ .with_stderr(&expect_msg)
+ .run();
+
+ // custom_build.rs outside the package root
+ let custom_build_root = paths::root().join("t_custom_build");
+ _ = fs::create_dir(&custom_build_root).unwrap();
+ _ = fs::write(&custom_build_root.join("custom_build.rs"), "fn main() {}");
+ expect_msg = format!(
+ "\
+warning: manifest has no documentation, homepage or repository.
+See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
+error: the source file of build script doesn't appear to be a path inside of the package.
+It is at `{}/t_custom_build/custom_build.rs`, whereas the root the package is `[CWD]`.
+This may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files.
+Please update the `build` setting in the manifest at `[CWD]/Cargo.toml` and point to a path inside the root of the package.
+", paths::root().display());
+ p.cargo("package -l")
+ .with_status(101)
+ .with_stderr(&expect_msg)
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/patch.rs b/src/tools/cargo/tests/testsuite/patch.rs
index a467f60b5..a4522e822 100644
--- a/src/tools/cargo/tests/testsuite/patch.rs
+++ b/src/tools/cargo/tests/testsuite/patch.rs
@@ -2700,3 +2700,86 @@ perhaps a crate was updated and forgotten to be re-vendored?"#,
)
.run();
}
+
+#[cargo_test]
+fn from_config_empty() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [patch.'']
+ bar = { path = 'bar' }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
+ .file("bar/src/lib.rs", r#""#)
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] [patch] entry `` should be a URL or registry name
+
+Caused by:
+ invalid url ``: relative URL without a base
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn from_manifest_empty() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+
+ [patch.'']
+ bar = { path = 'bar' }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
+ .file("bar/src/lib.rs", r#""#)
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
+
+Caused by:
+ [patch] entry `` should be a URL or registry name
+
+Caused by:
+ invalid url ``: relative URL without a base
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/path.rs b/src/tools/cargo/tests/testsuite/path.rs
index ebbb72f9a..f458717cd 100644
--- a/src/tools/cargo/tests/testsuite/path.rs
+++ b/src/tools/cargo/tests/testsuite/path.rs
@@ -83,7 +83,12 @@ fn cargo_compile_with_nested_deps_shorthand() {
p.process(&p.bin("foo")).with_stdout("test passed\n").run();
println!("cleaning");
- p.cargo("clean -v").with_stdout("").run();
+ p.cargo("clean -v")
+ .with_stderr(
+ "[REMOVING] [CWD]/target\n\
+ [REMOVED] [..]",
+ )
+ .run();
println!("building baz");
p.cargo("build -p baz")
.with_stderr(
@@ -350,7 +355,7 @@ fn deep_dependencies_trigger_rebuild() {
in [..]\n",
)
.run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
// Make sure an update to baz triggers a rebuild of bar
//
@@ -437,7 +442,7 @@ fn no_rebuild_two_deps() {
)
.run();
assert!(p.bin("foo").is_file());
- p.cargo("build").with_stdout("").run();
+ p.cargo("build").with_stderr("[FINISHED] [..]").run();
assert!(p.bin("foo").is_file());
}
diff --git a/src/tools/cargo/tests/testsuite/pkgid.rs b/src/tools/cargo/tests/testsuite/pkgid.rs
index 88d991e80..fee45b215 100644
--- a/src/tools/cargo/tests/testsuite/pkgid.rs
+++ b/src/tools/cargo/tests/testsuite/pkgid.rs
@@ -1,5 +1,7 @@
//! Tests for the `cargo pkgid` command.
+use cargo_test_support::basic_lib_manifest;
+use cargo_test_support::git;
use cargo_test_support::project;
use cargo_test_support::registry::Package;
@@ -34,7 +36,10 @@ fn local() {
p.cargo("generate-lockfile").run();
p.cargo("pkgid foo")
- .with_stdout(format!("file://[..]{}#0.1.0", p.root().to_str().unwrap()))
+ .with_stdout(format!(
+ "path+file://[..]{}#0.1.0",
+ p.root().to_str().unwrap()
+ ))
.run();
// Bad file URL.
@@ -89,7 +94,7 @@ fn registry() {
p.cargo("generate-lockfile").run();
p.cargo("pkgid crates-io")
- .with_stdout("https://github.com/rust-lang/crates.io-index#crates-io@0.1.0")
+ .with_stdout("registry+https://github.com/rust-lang/crates.io-index#crates-io@0.1.0")
.run();
// Bad URL.
@@ -143,7 +148,7 @@ fn multiple_versions() {
p.cargo("generate-lockfile").run();
p.cargo("pkgid two-ver:0.2.0")
- .with_stdout("https://github.com/rust-lang/crates.io-index#two-ver@0.2.0")
+ .with_stdout("registry+https://github.com/rust-lang/crates.io-index#two-ver@0.2.0")
.run();
// Incomplete version.
@@ -163,7 +168,7 @@ Please re-run this command with one of the following specifications:
p.cargo("pkgid two-ver@0.2")
.with_stdout(
"\
-https://github.com/rust-lang/crates.io-index#two-ver@0.2.0
+registry+https://github.com/rust-lang/crates.io-index#two-ver@0.2.0
",
)
.run();
@@ -195,3 +200,88 @@ Did you mean one of these?
)
.run();
}
+
+// Not for `cargo pkgid` but the `PackageIdSpec` format
+#[cargo_test]
+fn multiple_git_same_version() {
+ // Test what happens if different packages refer to the same git repo with
+ // different refs, and the package version is the same.
+ let (xyz_project, xyz_repo) = git::new_repo("xyz", |project| {
+ project
+ .file("Cargo.toml", &basic_lib_manifest("xyz"))
+ .file("src/lib.rs", "fn example() {}")
+ });
+ let rev1 = xyz_repo.revparse_single("HEAD").unwrap().id();
+ xyz_project.change_file("src/lib.rs", "pub fn example() {}");
+ git::add(&xyz_repo);
+ let rev2 = git::commit(&xyz_repo);
+ // Both rev1 and rev2 point to version 0.1.0.
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ path = "bar" }}
+ xyz = {{ git = "{}", rev = "{}" }}
+
+ "#,
+ xyz_project.url(),
+ rev1
+ ),
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "bar/Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+
+ [dependencies]
+ xyz = {{ git = "{}", rev = "{}" }}
+ "#,
+ xyz_project.url(),
+ rev2
+ ),
+ )
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ p.cargo("check").run();
+ p.cargo("tree")
+ .with_stdout(&format!(
+ "\
+foo v0.1.0 ([..]/foo)
+├── bar v0.1.0 ([..]/foo/bar)
+│ └── xyz v0.5.0 (file://[..]/xyz?rev={}#{})
+└── xyz v0.5.0 (file://[..]/xyz?rev={}#{})
+",
+ rev2,
+ &rev2.to_string()[..8],
+ rev1,
+ &rev1.to_string()[..8]
+ ))
+ .run();
+ // FIXME: This fails since xyz is ambiguous, but the
+ // possible pkgids are also ambiguous.
+ p.cargo("pkgid xyz")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: There are multiple `xyz` packages in your project, and the specification `xyz` is ambiguous.
+Please re-run this command with one of the following specifications:
+ git+file://[..]/xyz?rev=[..]#0.5.0
+ git+file://[..]/xyz?rev=[..]#0.5.0
+",
+ )
+ .run();
+ // TODO, what should the `-p` value be here?
+ //p.cargo("update -p")
+}
diff --git a/src/tools/cargo/tests/testsuite/profile_config.rs b/src/tools/cargo/tests/testsuite/profile_config.rs
index 710a0d8ef..f8a9ae744 100644
--- a/src/tools/cargo/tests/testsuite/profile_config.rs
+++ b/src/tools/cargo/tests/testsuite/profile_config.rs
@@ -1,6 +1,6 @@
//! Tests for profiles defined in config files.
-use cargo::util::toml::schema::TomlDebugInfo;
+use cargo::util_schemas::manifest::TomlDebugInfo;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
use cargo_test_support::{basic_lib_manifest, paths, project};
@@ -428,8 +428,8 @@ fn named_config_profile() {
let profiles = Profiles::new(&ws, profile_name).unwrap();
let crates_io = cargo::core::SourceId::crates_io(&config).unwrap();
- let a_pkg = PackageId::new("a", "0.1.0", crates_io).unwrap();
- let dep_pkg = PackageId::new("dep", "0.1.0", crates_io).unwrap();
+ let a_pkg = PackageId::try_new("a", "0.1.0", crates_io).unwrap();
+ let dep_pkg = PackageId::try_new("dep", "0.1.0", crates_io).unwrap();
// normal package
let kind = CompileKind::Host;
diff --git a/src/tools/cargo/tests/testsuite/profile_custom.rs b/src/tools/cargo/tests/testsuite/profile_custom.rs
index f7139e552..cf9828d37 100644
--- a/src/tools/cargo/tests/testsuite/profile_custom.rs
+++ b/src/tools/cargo/tests/testsuite/profile_custom.rs
@@ -86,6 +86,10 @@ fn invalid_profile_name() {
[ERROR] failed to parse manifest at [..]
Caused by:
+ TOML parse error at line 7, column 26
+ |
+ 7 | [profile.'.release-lto']
+ | ^^^^^^^^^^^^^^
invalid character `.` in profile name `.release-lto`
Allowed characters are letters, numbers, underscore, and hyphen.
",
@@ -626,6 +630,7 @@ See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configur
),
);
+ let highlight = "^".repeat(name.len());
p.cargo("build")
.with_status(101)
.with_stderr(&format!(
@@ -633,11 +638,14 @@ See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configur
error: failed to parse manifest at `[ROOT]/foo/Cargo.toml`
Caused by:
- profile name `{}` is reserved
+ TOML parse error at line 6, column 30
+ |
+ 6 | [profile.{name}]
+ | {highlight}
+ profile name `{name}` is reserved
Please choose a different name.
See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles.
",
- name
))
.run();
}
@@ -663,6 +671,10 @@ Caused by:
error: failed to parse manifest at `[ROOT]/foo/Cargo.toml`
Caused by:
+ TOML parse error at line 7, column 25
+ |
+ 7 | [profile.debug]
+ | ^^^^^
profile name `debug` is reserved
To configure the default development profile, use the name `dev` as in [profile.dev]
See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles.
diff --git a/src/tools/cargo/tests/testsuite/profile_trim_paths.rs b/src/tools/cargo/tests/testsuite/profile_trim_paths.rs
index 1d24c159b..8a883a004 100644
--- a/src/tools/cargo/tests/testsuite/profile_trim_paths.rs
+++ b/src/tools/cargo/tests/testsuite/profile_trim_paths.rs
@@ -83,8 +83,8 @@ fn release_profile_default_to_object() {
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] release [..]",
)
.run();
@@ -121,8 +121,8 @@ fn one_option() {
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope={option} \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]",
))
.run();
@@ -158,8 +158,8 @@ fn multiple_options() {
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=diagnostics,macro,object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]",
)
.run();
@@ -193,8 +193,8 @@ fn profile_merge_works() {
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=diagnostics \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] custom [..]",
)
.run();
@@ -238,13 +238,13 @@ fn registry_dependency() {
[COMPILING] bar v0.0.1
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix={pkg_remap} [..]
+ --remap-path-prefix={pkg_remap} \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]
[RUNNING] `target/debug/foo[EXE]`"
))
@@ -292,13 +292,13 @@ fn git_dependency() {
[COMPILING] bar v0.0.1 ({url}[..])
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix={pkg_remap} [..]
+ --remap-path-prefix={pkg_remap} \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]
[RUNNING] `target/debug/foo[EXE]`"
))
@@ -338,13 +338,13 @@ fn path_dependency() {
[COMPILING] bar v0.0.1 ([..]/cocktail-bar)
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]
[RUNNING] `target/debug/foo[EXE]`"
))
@@ -387,13 +387,13 @@ fn path_dependency_outside_workspace() {
[COMPILING] bar v0.0.1 ([..]/bar)
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix={bar_path}=bar-0.0.1 [..]
+ --remap-path-prefix={bar_path}=bar-0.0.1 \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[COMPILING] foo v0.0.1 ([CWD])
[RUNNING] `rustc [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]
[RUNNING] `target/debug/foo[EXE]`"
))
@@ -439,31 +439,81 @@ fn diagnostics_works() {
"\
[RUNNING] [..]rustc [..]\
-Zremap-path-scope=diagnostics \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix={pkg_remap} [..]",
+ --remap-path-prefix={pkg_remap} \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]",
))
.with_stderr_contains(
"\
[RUNNING] [..]rustc [..]\
-Zremap-path-scope=diagnostics \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]",
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]",
)
.run();
}
+#[cfg(target_os = "macos")]
+mod object_works {
+ use super::*;
+
+ fn inspect_debuginfo(path: &std::path::Path) -> Vec<u8> {
+ std::process::Command::new("nm")
+ .arg("-pa")
+ .arg(path)
+ .output()
+ .expect("nm works")
+ .stdout
+ }
+
+ #[cargo_test(requires_nm, nightly, reason = "-Zremap-path-scope is unstable")]
+ fn with_split_debuginfo_off() {
+ object_works_helper("off", inspect_debuginfo);
+ }
+
+ #[cargo_test(requires_nm, nightly, reason = "-Zremap-path-scope is unstable")]
+ fn with_split_debuginfo_packed() {
+ object_works_helper("packed", inspect_debuginfo);
+ }
+
+ #[cargo_test(requires_nm, nightly, reason = "-Zremap-path-scope is unstable")]
+ fn with_split_debuginfo_unpacked() {
+ object_works_helper("unpacked", inspect_debuginfo);
+ }
+}
+
#[cfg(target_os = "linux")]
-#[cargo_test(requires_readelf, nightly, reason = "-Zremap-path-scope is unstable")]
-fn object_works() {
- use std::os::unix::ffi::OsStrExt;
+mod object_works {
+ use super::*;
- let run_readelf = |path| {
+ fn inspect_debuginfo(path: &std::path::Path) -> Vec<u8> {
std::process::Command::new("readelf")
- .arg("-wi")
+ .arg("--debug-dump=info")
+ .arg("--debug-dump=no-follow-links") // older version can't recognized but just a warning
.arg(path)
.output()
.expect("readelf works")
- };
+ .stdout
+ }
+
+ #[cargo_test(requires_readelf, nightly, reason = "-Zremap-path-scope is unstable")]
+ fn with_split_debuginfo_off() {
+ object_works_helper("off", inspect_debuginfo);
+ }
+
+ #[cargo_test(requires_readelf, nightly, reason = "-Zremap-path-scope is unstable")]
+ fn with_split_debuginfo_packed() {
+ object_works_helper("packed", inspect_debuginfo);
+ }
+
+ #[cargo_test(requires_readelf, nightly, reason = "-Zremap-path-scope is unstable")]
+ fn with_split_debuginfo_unpacked() {
+ object_works_helper("unpacked", inspect_debuginfo);
+ }
+}
+
+#[cfg(unix)]
+fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> Vec<u8>) {
+ use std::os::unix::ffi::OsStrExt;
let registry_src = paths::home().join(".cargo/registry/src");
let pkg_remap = format!("{}/[..]/bar-0.0.1=bar-0.0.1", registry_src.display());
@@ -478,14 +528,19 @@ fn object_works() {
let p = project()
.file(
"Cargo.toml",
- r#"
+ &format!(
+ r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = "0.0.1"
- "#,
+
+ [profile.dev]
+ split-debuginfo = "{split_debuginfo}"
+ "#
+ ),
)
.file("src/main.rs", "fn main() { bar::f(); }")
.build();
@@ -497,7 +552,7 @@ fn object_works() {
let bin_path = p.bin("foo");
assert!(bin_path.is_file());
- let stdout = run_readelf(bin_path).stdout;
+ let stdout = run(&bin_path);
// TODO: re-enable this check when rustc bootstrap disables remapping
// <https://github.com/rust-lang/cargo/pull/12625#discussion_r1371714791>
// assert!(memchr::memmem::find(&stdout, rust_src).is_some());
@@ -506,45 +561,69 @@ fn object_works() {
p.cargo("clean").run();
- p.change_file(
- "Cargo.toml",
- r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [dependencies]
- bar = "0.0.1"
-
- [profile.dev]
- trim-paths = "object"
- "#,
- );
-
p.cargo("build --verbose -Ztrim-paths")
+ .arg("--config")
+ .arg(r#"profile.dev.trim-paths="object""#)
.masquerade_as_nightly_cargo(&["-Ztrim-paths"])
.with_stderr(&format!(
"\
[COMPILING] bar v0.0.1
-[RUNNING] `rustc [..]\
+[RUNNING] `rustc [..]-C split-debuginfo={split_debuginfo} [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix={pkg_remap} [..]
+ --remap-path-prefix={pkg_remap} \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[COMPILING] foo v0.0.1 ([CWD])
-[RUNNING] `rustc [..]\
+[RUNNING] `rustc [..]-C split-debuginfo={split_debuginfo} [..]\
-Zremap-path-scope=object \
- --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] \
- --remap-path-prefix=[CWD]= [..]
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]
[FINISHED] dev [..]",
))
.run();
let bin_path = p.bin("foo");
assert!(bin_path.is_file());
- let stdout = run_readelf(bin_path).stdout;
+ let stdout = run(&bin_path);
assert!(memchr::memmem::find(&stdout, rust_src).is_none());
- assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_none());
- assert!(memchr::memmem::find(&stdout, pkg_root).is_none());
+ for line in stdout.split(|c| c == &b'\n') {
+ let registry = memchr::memmem::find(line, registry_src_bytes).is_none();
+ let local = memchr::memmem::find(line, pkg_root).is_none();
+ if registry && local {
+ continue;
+ }
+
+ #[cfg(target_os = "macos")]
+ {
+ // `OSO` symbols can't be trimmed at this moment.
+ // See <https://github.com/rust-lang/rust/issues/116948#issuecomment-1793617018>
+ if memchr::memmem::find(line, b" OSO ").is_some() {
+ continue;
+ }
+
+ // on macOS `SO` symbols are embedded in final binaries and should be trimmed.
+ // See rust-lang/rust#117652.
+ if memchr::memmem::find(line, b" SO ").is_some() {
+ continue;
+ }
+ }
+
+ #[cfg(target_os = "linux")]
+ {
+ // There is a bug in rustc `-Zremap-path-scope`.
+ // See rust-lang/rust/pull/118518
+ if memchr::memmem::find(line, b"DW_AT_comp_dir").is_some() {
+ continue;
+ }
+ if memchr::memmem::find(line, b"DW_AT_GNU_dwo_name").is_some() {
+ continue;
+ }
+ }
+
+ panic!(
+ "unexpected untrimmed symbol: {}",
+ String::from_utf8(line.into()).unwrap()
+ );
+ }
}
// TODO: might want to move to test/testsuite/build_script.rs once stabilized.
@@ -612,3 +691,69 @@ fn custom_build_env_var_trim_paths() {
.run();
}
}
+
+#[cfg(unix)]
+#[cargo_test(requires_lldb, nightly, reason = "-Zremap-path-scope is unstable")]
+fn lldb_works_after_trimmed() {
+ use cargo_test_support::compare::match_contains;
+
+ let run_lldb = |path| {
+ std::process::Command::new("lldb")
+ .args(["-o", "breakpoint set --file src/main.rs --line 4"])
+ .args(["-o", "run"])
+ .args(["-o", "continue"])
+ .args(["-o", "exit"])
+ .arg("--no-use-colors")
+ .arg(path)
+ .output()
+ .expect("lldb works")
+ };
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [profile.dev]
+ trim-paths = "object"
+ "#,
+ )
+ .file(
+ "src/main.rs",
+ r#"
+ fn main() {
+ let msg = "Hello, Ferris!";
+ println!("{msg}");
+ }
+ "#,
+ )
+ .build();
+
+ p.cargo("build --verbose -Ztrim-paths")
+ .masquerade_as_nightly_cargo(&["-Ztrim-paths"])
+ .with_stderr_contains(
+ "\
+[RUNNING] `rustc [..]\
+ -Zremap-path-scope=object \
+ --remap-path-prefix=[CWD]=. \
+ --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]",
+ )
+ .run();
+
+ let bin_path = p.bin("foo");
+ assert!(bin_path.is_file());
+ let stdout = String::from_utf8(run_lldb(bin_path).stdout).unwrap();
+ match_contains("[..]stopped[..]", &stdout, None).unwrap();
+ match_contains("[..]stop reason = breakpoint[..]", &stdout, None).unwrap();
+ match_contains(
+ "\
+(lldb) continue
+Hello, Ferris!",
+ &stdout,
+ None,
+ )
+ .unwrap();
+}
diff --git a/src/tools/cargo/tests/testsuite/pub_priv.rs b/src/tools/cargo/tests/testsuite/pub_priv.rs
index b2160e0fa..b3d87ce4c 100644
--- a/src/tools/cargo/tests/testsuite/pub_priv.rs
+++ b/src/tools/cargo/tests/testsuite/pub_priv.rs
@@ -199,7 +199,7 @@ Caused by:
}
#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
-fn workspace_dep_made_public() {
+fn workspace_pub_disallowed() {
Package::new("foo1", "0.1.0")
.file("src/lib.rs", "pub struct FromFoo;")
.publish();
@@ -244,5 +244,238 @@ fn workspace_dep_made_public() {
p.cargo("check")
.masquerade_as_nightly_cargo(&["public-dependency"])
+ .with_status(101)
+ .with_stderr(
+ "\
+error: failed to parse manifest at `[CWD]/Cargo.toml`
+
+Caused by:
+ foo2 is public, but workspace dependencies cannot be public
+",
+ )
+ .run()
+}
+
+#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
+fn allow_priv_in_tests() {
+ Package::new("priv_dep", "0.1.0")
+ .file("src/lib.rs", "pub struct FromPriv;")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ cargo-features = ["public-dependency"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ priv_dep = {version = "0.1.0", public = false}
+ "#,
+ )
+ .file(
+ "tests/mod.rs",
+ "
+ extern crate priv_dep;
+ pub fn use_priv(_: priv_dep::FromPriv) {}
+ ",
+ )
+ .build();
+
+ p.cargo("check --tests --message-format=short")
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] priv_dep v0.1.0 ([..])
+[CHECKING] priv_dep v0.1.0
+[CHECKING] foo v0.0.1 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run()
+}
+
+#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
+fn allow_priv_in_benchs() {
+ Package::new("priv_dep", "0.1.0")
+ .file("src/lib.rs", "pub struct FromPriv;")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ cargo-features = ["public-dependency"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ priv_dep = {version = "0.1.0", public = false}
+ "#,
+ )
+ .file(
+ "benches/mod.rs",
+ "
+ extern crate priv_dep;
+ pub fn use_priv(_: priv_dep::FromPriv) {}
+ ",
+ )
+ .build();
+
+ p.cargo("check --benches --message-format=short")
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] priv_dep v0.1.0 ([..])
+[CHECKING] priv_dep v0.1.0
+[CHECKING] foo v0.0.1 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run()
+}
+
+#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
+fn allow_priv_in_bins() {
+ Package::new("priv_dep", "0.1.0")
+ .file("src/lib.rs", "pub struct FromPriv;")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ cargo-features = ["public-dependency"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ priv_dep = {version = "0.1.0", public = false}
+ "#,
+ )
+ .file(
+ "src/main.rs",
+ "
+ extern crate priv_dep;
+ pub fn use_priv(_: priv_dep::FromPriv) {}
+ fn main() {}
+ ",
+ )
+ .build();
+
+ p.cargo("check --bins --message-format=short")
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] priv_dep v0.1.0 ([..])
+[CHECKING] priv_dep v0.1.0
+[CHECKING] foo v0.0.1 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run()
+}
+
+#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
+fn allow_priv_in_examples() {
+ Package::new("priv_dep", "0.1.0")
+ .file("src/lib.rs", "pub struct FromPriv;")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ cargo-features = ["public-dependency"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ priv_dep = {version = "0.1.0", public = false}
+ "#,
+ )
+ .file(
+ "examples/lib.rs",
+ "
+ extern crate priv_dep;
+ pub fn use_priv(_: priv_dep::FromPriv) {}
+ fn main() {}
+ ",
+ )
+ .build();
+
+ p.cargo("check --examples --message-format=short")
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] priv_dep v0.1.0 ([..])
+[CHECKING] priv_dep v0.1.0
+[CHECKING] foo v0.0.1 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run()
+}
+
+#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
+fn allow_priv_in_custom_build() {
+ Package::new("priv_dep", "0.1.0")
+ .file("src/lib.rs", "pub struct FromPriv;")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ cargo-features = ["public-dependency"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [build-dependencies]
+ priv_dep = "0.1.0"
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file(
+ "build.rs",
+ "
+ extern crate priv_dep;
+ pub fn use_priv(_: priv_dep::FromPriv) {}
+ fn main() {}
+ ",
+ )
+ .build();
+
+ p.cargo("check --all-targets --message-format=short")
+ .masquerade_as_nightly_cargo(&["public-dependency"])
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] priv_dep v0.1.0 ([..])
+[COMPILING] priv_dep v0.1.0
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
.run()
}
diff --git a/src/tools/cargo/tests/testsuite/publish_lockfile.rs b/src/tools/cargo/tests/testsuite/publish_lockfile.rs
index 35da5131f..0a7c23368 100644
--- a/src/tools/cargo/tests/testsuite/publish_lockfile.rs
+++ b/src/tools/cargo/tests/testsuite/publish_lockfile.rs
@@ -92,7 +92,17 @@ src/main.rs
",
)
.run();
- p.cargo("package").with_stdout("").run();
+ p.cargo("package")
+ .with_stderr(
+ "\
+[PACKAGING] foo v0.0.1 [..]
+[VERIFYING] foo v0.0.1 [..]
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] [..]
+[PACKAGED] 4 files, [..]
+",
+ )
+ .run();
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
validate_crate_contents(
diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs
index b5dff2746..6107b6f59 100644
--- a/src/tools/cargo/tests/testsuite/registry.rs
+++ b/src/tools/cargo/tests/testsuite/registry.rs
@@ -549,7 +549,7 @@ fn lockfile_locks() {
p.root().move_into_the_past();
Package::new("bar", "0.0.2").publish();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -602,7 +602,7 @@ fn lockfile_locks_transitively() {
Package::new("baz", "0.0.2").publish();
Package::new("bar", "0.0.2").dep("baz", "*").publish();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -739,7 +739,7 @@ fn yanks_in_lockfiles_are_ok() {
Package::new("bar", "0.0.1").yanked(true).publish();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
p.cargo("update")
.with_status(101)
@@ -792,7 +792,7 @@ fn yanks_in_lockfiles_are_ok_for_other_update() {
Package::new("bar", "0.0.1").yanked(true).publish();
Package::new("baz", "0.0.1").publish();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
Package::new("baz", "0.0.2").publish();
@@ -868,7 +868,18 @@ fn yanks_in_lockfiles_are_ok_with_new_dep() {
"#,
);
- p.cargo("check").with_stdout("").run();
+ p.cargo("check")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)
+[CHECKING] baz v0.0.1
+[CHECKING] foo v0.0.1 [..]
+[FINISHED] [..]
+",
+ )
+ .run();
}
#[cargo_test]
@@ -1272,7 +1283,7 @@ fn git_and_registry_dep() {
p.root().move_into_the_past();
println!("second");
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
diff --git a/src/tools/cargo/tests/testsuite/replace.rs b/src/tools/cargo/tests/testsuite/replace.rs
index b9de51d2f..6c31a023e 100644
--- a/src/tools/cargo/tests/testsuite/replace.rs
+++ b/src/tools/cargo/tests/testsuite/replace.rs
@@ -305,7 +305,7 @@ fn transitive() {
)
.run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -354,7 +354,7 @@ fn persists_across_rebuilds() {
)
.run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -530,7 +530,7 @@ fn override_adds_some_deps() {
)
.run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
Package::new("baz", "0.1.2").publish();
p.cargo("update")
@@ -550,7 +550,7 @@ fn override_adds_some_deps() {
)
.run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -601,8 +601,8 @@ fn locked_means_locked_yes_no_seriously_i_mean_locked() {
p.cargo("check").run();
- p.cargo("check").with_stdout("").run();
- p.cargo("check").with_stdout("").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
+ p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -1399,7 +1399,7 @@ fn override_respects_spec_metadata() {
[..]
[..]
[..]
-error: could not compile `foo` (lib) due to previous error
+error: could not compile `foo` (lib) due to 1 previous error
",
)
.with_status(101)
diff --git a/src/tools/cargo/tests/testsuite/rust_version.rs b/src/tools/cargo/tests/testsuite/rust_version.rs
index 21321b7c5..d0ea33c83 100644
--- a/src/tools/cargo/tests/testsuite/rust_version.rs
+++ b/src/tools/cargo/tests/testsuite/rust_version.rs
@@ -245,49 +245,81 @@ fn dependency_rust_version_newer_than_package() {
.file("src/main.rs", "fn main(){}")
.build();
+ p.cargo("check")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .run();
p.cargo("check --ignore-rust-version")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["msrv-policy"])
- // This shouldn't fail
- .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn dependency_rust_version_older_and_newer_than_package() {
+ Package::new("bar", "1.5.0")
+ .rust_version("1.55.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+ Package::new("bar", "1.6.0")
+ .rust_version("1.65.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust-version = "1.60.0"
+ [dependencies]
+ bar = "1.0.0"
+ "#,
+ )
+ .file("src/main.rs", "fn main(){}")
+ .build();
+
+ p.cargo("check --ignore-rust-version")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ // This should pick 1.6.0
.with_stderr(
"\
[UPDATING] `dummy-registry` index
-[ERROR] failed to select a version for the requirement `bar = \"^1.0.0\"`
-candidate versions found which didn't match: 1.6.0
-location searched: `dummy-registry` index (which is replacing registry `crates-io`)
-required by package `foo v0.0.1 ([CWD])`
-perhaps a crate was updated and forgotten to be re-vendored?
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.5.0 (registry `dummy-registry`)
+[CHECKING] bar v1.5.0
+[CHECKING] [..]
+[FINISHED] [..]
",
)
.run();
p.cargo("check")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["msrv-policy"])
- .with_status(101)
- // This should have a better error message
.with_stderr(
"\
-[UPDATING] `dummy-registry` index
-[ERROR] failed to select a version for the requirement `bar = \"^1.0.0\"`
-candidate versions found which didn't match: 1.6.0
-location searched: `dummy-registry` index (which is replacing registry `crates-io`)
-required by package `foo v0.0.1 ([CWD])`
-perhaps a crate was updated and forgotten to be re-vendored?
+[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
-fn dependency_rust_version_older_and_newer_than_package() {
- Package::new("bar", "1.5.0")
- .rust_version("1.55.0")
+fn dependency_rust_version_backtracking() {
+ Package::new("has-rust-version", "1.6.0")
+ .rust_version("1.65.0")
.file("src/lib.rs", "fn other_stuff() {}")
.publish();
- Package::new("bar", "1.6.0")
- .rust_version("1.65.0")
+ Package::new("no-rust-version", "2.1.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+ Package::new("no-rust-version", "2.2.0")
.file("src/lib.rs", "fn other_stuff() {}")
+ .dep("has-rust-version", "1.6.0")
.publish();
let p = project()
@@ -300,7 +332,7 @@ fn dependency_rust_version_older_and_newer_than_package() {
authors = []
rust-version = "1.60.0"
[dependencies]
- bar = "1.0.0"
+ no-rust-version = "2"
"#,
)
.file("src/main.rs", "fn main(){}")
@@ -309,13 +341,14 @@ fn dependency_rust_version_older_and_newer_than_package() {
p.cargo("check --ignore-rust-version")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["msrv-policy"])
- // This should pick 1.6.0
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
-[DOWNLOADED] bar v1.5.0 (registry `dummy-registry`)
-[CHECKING] bar v1.5.0
+[DOWNLOADED] no-rust-version v2.2.0 (registry `dummy-registry`)
+[DOWNLOADED] has-rust-version v1.6.0 (registry `dummy-registry`)
+[CHECKING] has-rust-version v1.6.0
+[CHECKING] no-rust-version v2.2.0
[CHECKING] [..]
[FINISHED] [..]
",
diff --git a/src/tools/cargo/tests/testsuite/rustflags.rs b/src/tools/cargo/tests/testsuite/rustflags.rs
index 6677beb04..788889951 100644
--- a/src/tools/cargo/tests/testsuite/rustflags.rs
+++ b/src/tools/cargo/tests/testsuite/rustflags.rs
@@ -456,7 +456,7 @@ fn env_rustflags_no_recompile() {
p.cargo("check").env("RUSTFLAGS", "--cfg foo").run();
p.cargo("check")
.env("RUSTFLAGS", "--cfg foo")
- .with_stdout("")
+ .with_stderr("[FINISHED] [..]")
.run();
}
@@ -944,7 +944,7 @@ fn build_rustflags_no_recompile() {
p.cargo("check").env("RUSTFLAGS", "--cfg foo").run();
p.cargo("check")
.env("RUSTFLAGS", "--cfg foo")
- .with_stdout("")
+ .with_stderr("[FINISHED] [..]")
.run();
}
@@ -1658,7 +1658,7 @@ fn host_config_rustflags_with_target() {
// regression test for https://github.com/rust-lang/cargo/issues/10206
let p = project()
.file("src/lib.rs", "")
- .file("build.rs.rs", "fn main() { assert!(cfg!(foo)); }")
+ .file("build.rs", "fn main() { assert!(cfg!(foo)); }")
.file(".cargo/config.toml", "target-applies-to-host = false")
.build();
diff --git a/src/tools/cargo/tests/testsuite/test.rs b/src/tools/cargo/tests/testsuite/test.rs
index 5f6528109..6357b950c 100644
--- a/src/tools/cargo/tests/testsuite/test.rs
+++ b/src/tools/cargo/tests/testsuite/test.rs
@@ -1433,7 +1433,7 @@ fn test_then_build() {
.with_stdout_contains("running 0 tests")
.run();
- p.cargo("build").with_stdout("").run();
+ p.cargo("build").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -2423,7 +2423,7 @@ fn dylib_doctest2() {
)
.build();
- p.cargo("test").with_stdout("").run();
+ p.cargo("test").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
@@ -3556,6 +3556,39 @@ fn cyclic_dev() {
}
#[cargo_test]
+fn cyclical_dep_with_missing_feature() {
+ // Checks for error handling when a cyclical dev-dependency specify a
+ // feature that doesn't exist.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dev-dependencies]
+ foo = { path = ".", features = ["missing"] }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "error: failed to select a version for `foo`.
+ ... required by package `foo v0.1.0 ([..]/foo)`
+versions that meet the requirements `*` are: 0.1.0
+
+the package `foo` depends on `foo`, with features: `missing` but `foo` does not have these features.
+
+
+failed to select a version for `foo` which could resolve this conflict",
+ )
+ .run();
+}
+
+#[cargo_test]
fn publish_a_crate_without_tests() {
Package::new("testless", "0.1.0")
.file(
diff --git a/src/tools/cargo/tests/testsuite/update.rs b/src/tools/cargo/tests/testsuite/update.rs
index e636435b0..40bc0b476 100644
--- a/src/tools/cargo/tests/testsuite/update.rs
+++ b/src/tools/cargo/tests/testsuite/update.rs
@@ -1091,11 +1091,8 @@ rustdns.workspace = true
p.cargo("update -p rootcrate")
.with_stderr(&format!(
"\
-[UPDATING] git repository `{}`
[UPDATING] rootcrate v2.29.8 ([CWD]/rootcrate) -> v2.29.81
-[UPDATING] rustdns v0.5.0 ([..]) -> [..]
[UPDATING] subcrate v2.29.8 ([CWD]/subcrate) -> v2.29.81",
- git_project.url(),
))
.run();
}
@@ -1182,11 +1179,96 @@ rustdns.workspace = true
p.cargo("update -p crate2")
.with_stderr(&format!(
"\
-[UPDATING] git repository `{}`
[UPDATING] crate1 v2.29.8 ([CWD]/crate1) -> v2.29.81
-[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81
-[UPDATING] rustdns v0.5.0 ([..]) -> [..]",
+[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81",
+ ))
+ .run();
+}
+
+#[cargo_test]
+fn update_only_members_with_workspace() {
+ let git_project = git::new("rustdns", |project| {
+ project
+ .file("Cargo.toml", &basic_lib_manifest("rustdns"))
+ .file("src/lib.rs", "pub fn bar() {}")
+ });
+
+ let workspace_toml = format!(
+ r#"
+[workspace.package]
+version = "2.29.8"
+edition = "2021"
+publish = false
+
+[workspace]
+members = [
+ "crate2",
+ "crate1",
+]
+resolver = "2"
+
+[workspace.dependencies]
+# Internal crates
+crate1 = {{ version = "*", path = "./crate1" }}
+
+# External dependencies
+rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
+ "#,
+ git_project.url()
+ );
+ let p = project()
+ .file("Cargo.toml", &workspace_toml)
+ .file(
+ "crate2/Cargo.toml",
+ r#"
+[package]
+name = "crate2"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+crate1.workspace = true
+"#,
+ )
+ .file("crate2/src/main.rs", "fn main() {}")
+ .file(
+ "crate1/Cargo.toml",
+ r#"
+[package]
+name = "crate1"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+rustdns.workspace = true
+"#,
+ )
+ .file("crate1/src/lib.rs", "pub foo() {}")
+ .build();
+
+ // First time around we should compile both foo and bar
+ p.cargo("generate-lockfile")
+ .with_stderr(&format!(
+ "[UPDATING] git repository `{}`\n",
git_project.url(),
))
.run();
+ // Modify a file manually, shouldn't trigger a recompile
+ git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
+ // Commit the changes and make sure we don't trigger a recompile because the
+ // lock file says not to change
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+ p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
+
+ p.cargo("update --workspace")
+ .with_stderr(
+ "\
+[UPDATING] crate1 v2.29.8 ([CWD]/crate1) -> v2.29.81
+[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81",
+ )
+ .run();
}
diff --git a/src/tools/cargo/tests/testsuite/workspaces.rs b/src/tools/cargo/tests/testsuite/workspaces.rs
index 94b5142f4..53ddc1616 100644
--- a/src/tools/cargo/tests/testsuite/workspaces.rs
+++ b/src/tools/cargo/tests/testsuite/workspaces.rs
@@ -2198,6 +2198,7 @@ fn ws_err_unused() {
"[features]",
"[target]",
"[badges]",
+ "[lints]",
] {
let p = project()
.file(