diff --git a/crates/cargo-util/src/paths.rs b/crates/cargo-util/src/paths.rs index 69df7a2096c..2724412dfdb 100644 --- a/crates/cargo-util/src/paths.rs +++ b/crates/cargo-util/src/paths.rs @@ -368,10 +368,10 @@ pub struct PathAncestors<'a> { impl<'a> PathAncestors<'a> { fn new(path: &'a Path, stop_root_at: Option<&Path>) -> PathAncestors<'a> { - let stop_at = env::var("__CARGO_TEST_ROOT") - .ok() - .map(PathBuf::from) - .or_else(|| stop_root_at.map(|p| p.to_path_buf())); + let stop_at = stop_root_at + .map(|p| p.to_path_buf()) + .or_else(|| env::var("__CARGO_TEST_ROOT").ok().map(PathBuf::from)); + PathAncestors { current: Some(path), //HACK: avoid reading `~/.cargo/config` when testing Cargo itself. diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index 790bfd2d7bc..354e6d8caf7 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -90,7 +90,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { if let Some(path) = &path { config.reload_rooted_at(path)?; } else { - // TODO: Consider calling set_search_stop_path(home). + config.set_search_stop_path(config.home().clone().into_path_unlocked()); config.reload_rooted_at(config.home().clone().into_path_unlocked())?; } diff --git a/src/bin/cargo/commands/uninstall.rs b/src/bin/cargo/commands/uninstall.rs index 46654b66897..95505bde592 100644 --- a/src/bin/cargo/commands/uninstall.rs +++ b/src/bin/cargo/commands/uninstall.rs @@ -14,6 +14,10 @@ pub fn cli() -> Command { } pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { + // Ignore local configuration, same as `cargo install` does + config.set_search_stop_path(config.home().clone().into_path_unlocked()); + config.reload_rooted_at(config.home().clone().into_path_unlocked())?; + let root = args.get_one::("root").map(String::as_str); if args.is_present_with_zero_values("package") { diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs index b5c781efddd..dd64f6b4110 100644 --- a/src/cargo/util/config/mod.rs +++ b/src/cargo/util/config/mod.rs @@ -532,9 +532,7 @@ impl Config { /// Sets the path where ancestor config file searching will stop. The /// given path is included, but its ancestors are not. pub fn set_search_stop_path>(&mut self, path: P) { - let path = path.into(); - debug_assert!(self.cwd.starts_with(&path)); - self.search_stop_path = Some(path); + self.search_stop_path = Some(path.into()); } /// Reloads on-disk configuration values, starting at the given path and diff --git a/src/doc/man/cargo-install.md b/src/doc/man/cargo-install.md index 14c2296c228..4cf36429551 100644 --- a/src/doc/man/cargo-install.md +++ b/src/doc/man/cargo-install.md @@ -75,7 +75,8 @@ available. This command operates on system or user level, not project level. This means that the local [configuration discovery] is ignored. -Instead, the configuration discovery begins at `$CARGO_HOME/config.toml`. +Instead, this command will only consider the global configuration from the +`$CARGO_HOME/config.toml` file. If the package is installed with `--path $PATH`, the local configuration will be used, beginning discovery at `$PATH/.cargo/config.toml`. diff --git a/src/doc/man/cargo-uninstall.md b/src/doc/man/cargo-uninstall.md index b2ebd097fc3..06d1fc30ca4 100644 --- a/src/doc/man/cargo-uninstall.md +++ b/src/doc/man/cargo-uninstall.md @@ -19,6 +19,15 @@ By default all binaries are removed for a crate but the `--bin` and {{> description-install-root }} +### Configuration Discovery + +This command operates on system or user level, not on project level. +This means that the local [configuration discovery] is ignored. +Instead, this command will only consider the global configuration from the +`$CARGO_HOME/config.toml` file. + +[configuration discovery]: ../reference/config.html#hierarchical-structure + ## OPTIONS ### Install Options diff --git a/src/doc/man/generated_txt/cargo-install.txt b/src/doc/man/generated_txt/cargo-install.txt index a285a1b6890..6b6acb8c074 100644 --- a/src/doc/man/generated_txt/cargo-install.txt +++ b/src/doc/man/generated_txt/cargo-install.txt @@ -84,10 +84,10 @@ DESCRIPTION This command operates on system or user level, not project level. This means that the local configuration discovery - is ignored. Instead, the configuration discovery begins at - $CARGO_HOME/config.toml. If the package is installed with --path $PATH, - the local configuration will be used, beginning discovery at - $PATH/.cargo/config.toml. + is ignored. Instead, this command will only consider the global + configuration from the $CARGO_HOME/config.toml file. If the package is + installed with --path $PATH, the local configuration will be used, + beginning discovery at $PATH/.cargo/config.toml. OPTIONS Install Options diff --git a/src/doc/man/generated_txt/cargo-uninstall.txt b/src/doc/man/generated_txt/cargo-uninstall.txt index dcf3d55f75a..23cc99a893d 100644 --- a/src/doc/man/generated_txt/cargo-uninstall.txt +++ b/src/doc/man/generated_txt/cargo-uninstall.txt @@ -27,6 +27,13 @@ DESCRIPTION o $HOME/.cargo + Configuration Discovery + This command operates on system or user level, not on project level. + This means that the local configuration discovery + + is ignored. Instead, this command will only consider the global + configuration from the $CARGO_HOME/config.toml file. + OPTIONS Install Options -p, --package spec… diff --git a/src/doc/src/commands/cargo-install.md b/src/doc/src/commands/cargo-install.md index 1601872ed8b..569ae62517b 100644 --- a/src/doc/src/commands/cargo-install.md +++ b/src/doc/src/commands/cargo-install.md @@ -82,7 +82,8 @@ available. This command operates on system or user level, not project level. This means that the local [configuration discovery] is ignored. -Instead, the configuration discovery begins at `$CARGO_HOME/config.toml`. +Instead, this command will only consider the global configuration from the +`$CARGO_HOME/config.toml` file. If the package is installed with `--path $PATH`, the local configuration will be used, beginning discovery at `$PATH/.cargo/config.toml`. diff --git a/src/doc/src/commands/cargo-uninstall.md b/src/doc/src/commands/cargo-uninstall.md index 2fb7490b901..328cd689b0c 100644 --- a/src/doc/src/commands/cargo-uninstall.md +++ b/src/doc/src/commands/cargo-uninstall.md @@ -26,6 +26,15 @@ The installation root is determined, in order of precedence: - `$HOME/.cargo` +### Configuration Discovery + +This command operates on system or user level, not on project level. +This means that the local [configuration discovery] is ignored. +Instead, this command will only consider the global configuration from the +`$CARGO_HOME/config.toml` file. + +[configuration discovery]: ../reference/config.html#hierarchical-structure + ## OPTIONS ### Install Options diff --git a/src/etc/man/cargo-install.1 b/src/etc/man/cargo-install.1 index 32b2bf4c95a..d0c1a842e21 100644 --- a/src/etc/man/cargo-install.1 +++ b/src/etc/man/cargo-install.1 @@ -104,7 +104,8 @@ available. .SS "Configuration Discovery" This command operates on system or user level, not project level. This means that the local \fIconfiguration discovery\fR is ignored. -Instead, the configuration discovery begins at \fB$CARGO_HOME/config.toml\fR\&. +Instead, this command will only consider the global configuration from the +\fB$CARGO_HOME/config.toml\fR file. If the package is installed with \fB\-\-path $PATH\fR, the local configuration will be used, beginning discovery at \fB$PATH/.cargo/config.toml\fR\&. .SH "OPTIONS" diff --git a/src/etc/man/cargo-uninstall.1 b/src/etc/man/cargo-uninstall.1 index d3ead109267..6eb1fd5a0bc 100644 --- a/src/etc/man/cargo-uninstall.1 +++ b/src/etc/man/cargo-uninstall.1 @@ -36,6 +36,11 @@ The installation root is determined, in order of precedence: .RS 4 \h'-04'\(bu\h'+02'\fB$HOME/.cargo\fR .RE +.SS "Configuration Discovery" +This command operates on system or user level, not on project level. +This means that the local \fIconfiguration discovery\fR is ignored. +Instead, this command will only consider the global configuration from the +\fB$CARGO_HOME/config.toml\fR file. .SH "OPTIONS" .SS "Install Options" .sp diff --git a/tests/testsuite/directory.rs b/tests/testsuite/directory.rs index 0e28de03942..97c35cd6084 100644 --- a/tests/testsuite/directory.rs +++ b/tests/testsuite/directory.rs @@ -8,22 +8,25 @@ use serde::Serialize; use cargo_test_support::cargo_process; use cargo_test_support::git; +use cargo_test_support::install::cargo_home; use cargo_test_support::paths; use cargo_test_support::registry::{cksum, Package}; use cargo_test_support::{basic_manifest, project, t, ProjectBuilder}; fn setup() { - let root = paths::root(); - t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::create_dir_all(cargo_home())); t!(fs::write( - root.join(".cargo/config"), - r#" + cargo_home().join("config"), + &format!( + " [source.crates-io] replace-with = 'my-awesome-local-registry' [source.my-awesome-local-registry] - directory = 'index' - "# + directory = '{}/index' + ", + paths::root().display(), + ) )); } diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index b06f3d3818e..a4ab208e500 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -407,6 +407,12 @@ fn install_location_precedence() { assert_has_installed_exe(&t1, "foo"); assert_has_not_installed_exe(&t2, "foo"); + cargo_process("uninstall foo --root") + .arg(&t1) + .env("CARGO_INSTALL_ROOT", &t2) + .run(); + assert_has_not_installed_exe(&t1, "foo"); + println!("install CARGO_INSTALL_ROOT"); cargo_process("install foo") @@ -415,18 +421,22 @@ fn install_location_precedence() { assert_has_installed_exe(&t2, "foo"); assert_has_not_installed_exe(&t3, "foo"); - println!("install install.root"); - - cargo_process("install foo").run(); - assert_has_installed_exe(&t3, "foo"); - assert_has_not_installed_exe(&t4, "foo"); - - fs::remove_file(root.join(".cargo/config")).unwrap(); + cargo_process("uninstall foo") + .env("CARGO_INSTALL_ROOT", &t2) + .run(); + assert_has_not_installed_exe(&t2, "foo"); - println!("install cargo home"); + // The `install.root` config value in `root/.cargo/config` is ignored by + // `cargo install` and `cargo uninstall`, because they only consider the + // global configuration file `$CARGO_HOME/config`. + println!("install install.root"); cargo_process("install foo").run(); assert_has_installed_exe(&t4, "foo"); + assert_has_not_installed_exe(&t3, "foo"); + + cargo_process("uninstall foo").run(); + assert_has_not_installed_exe(&t4, "foo"); } #[cargo_test] @@ -1837,6 +1847,39 @@ fn install_path_config() { .run(); } +#[cargo_test] +fn uninstall_should_ignore_local_config() { + let project = project() + .file( + ".cargo/config", + r#" + [install] + root = './' + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // Will install `foo` binary to `/path/to/foo/bin/foo` + cargo_process("install --path foo").run(); + + assert_has_installed_exe(project.root(), "foo"); + + // Won't find the `foo` executable, because `cargo uninstall` + // ignores the config resolution chain of the current work directory + cargo_process("uninstall foo") + .cwd("foo") + .with_status(101) + .with_stderr_contains( + "[..]error: package ID specification `foo` did not match any packages[..]", + ) + .run(); + + cargo_process("uninstall foo --root foo").run(); + + assert_has_not_installed_exe(project.root(), "foo"); +} + #[cargo_test] fn install_version_req() { // Try using a few versionreq styles.