2019-11-25 02:42:45 +00:00
|
|
|
//! Tests for custom cargo commands and other global command features.
|
|
|
|
|
2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2021-08-06 00:19:42 +00:00
|
|
|
use std::fs;
|
2020-05-12 15:03:35 +00:00
|
|
|
use std::io::Read;
|
2015-02-27 01:04:25 +00:00
|
|
|
use std::path::{Path, PathBuf};
|
2020-05-12 15:03:35 +00:00
|
|
|
use std::process::Stdio;
|
2014-08-21 16:24:34 +00:00
|
|
|
use std::str;
|
|
|
|
|
2022-08-25 19:15:34 +00:00
|
|
|
use cargo_test_support::basic_manifest;
|
|
|
|
use cargo_test_support::paths::CargoPathExt;
|
2019-09-12 17:14:29 +00:00
|
|
|
use cargo_test_support::registry::Package;
|
2021-08-09 17:01:04 +00:00
|
|
|
use cargo_test_support::tools::echo_subcommand;
|
|
|
|
use cargo_test_support::{
|
|
|
|
basic_bin_manifest, cargo_exe, cargo_process, paths, project, project_in_home,
|
|
|
|
};
|
2022-08-25 19:15:34 +00:00
|
|
|
use cargo_util::paths::join_paths;
|
2014-08-09 05:37:50 +00:00
|
|
|
|
2015-02-27 01:04:25 +00:00
|
|
|
fn path() -> Vec<PathBuf> {
|
2017-09-24 14:26:37 +00:00
|
|
|
env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
|
2014-08-12 04:22:29 +00:00
|
|
|
}
|
2015-02-06 07:27:53 +00:00
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2018-07-26 11:08:39 +00:00
|
|
|
fn list_commands_with_descriptions() {
|
|
|
|
let p = project().build();
|
2018-08-28 22:11:30 +00:00
|
|
|
p.cargo("--list")
|
2018-12-08 11:19:47 +00:00
|
|
|
.with_stdout_contains(
|
|
|
|
" build Compile a local package and all of its dependencies",
|
|
|
|
)
|
2019-02-03 04:01:23 +00:00
|
|
|
// Assert that `read-manifest` prints the right one-line description followed by another
|
|
|
|
// command, indented.
|
2018-12-08 11:19:47 +00:00
|
|
|
.with_stdout_contains(
|
|
|
|
" read-manifest Print a JSON representation of a Cargo.toml manifest.",
|
|
|
|
)
|
2018-08-28 22:11:30 +00:00
|
|
|
.run();
|
2018-07-26 11:08:39 +00:00
|
|
|
}
|
|
|
|
|
2020-07-24 21:40:49 +00:00
|
|
|
#[cargo_test]
|
2021-08-05 01:04:24 +00:00
|
|
|
fn list_builtin_aliases_with_descriptions() {
|
2020-07-24 21:40:49 +00:00
|
|
|
let p = project().build();
|
|
|
|
p.cargo("--list")
|
|
|
|
.with_stdout_contains(" b alias: build")
|
|
|
|
.with_stdout_contains(" c alias: check")
|
|
|
|
.with_stdout_contains(" r alias: run")
|
|
|
|
.with_stdout_contains(" t alias: test")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2021-08-05 01:04:24 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn list_custom_aliases_with_descriptions() {
|
|
|
|
let p = project_in_home("proj")
|
|
|
|
.file(
|
|
|
|
&paths::home().join(".cargo").join("config"),
|
|
|
|
r#"
|
|
|
|
[alias]
|
|
|
|
myaliasstr = "foo --bar"
|
|
|
|
myaliasvec = ["foo", "--bar"]
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("--list")
|
2021-12-06 22:02:21 +00:00
|
|
|
.with_stdout_contains(" myaliasstr alias: foo --bar")
|
|
|
|
.with_stdout_contains(" myaliasvec alias: foo --bar")
|
2021-08-05 01:04:24 +00:00
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2021-08-07 07:11:01 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn list_dedupe() {
|
|
|
|
let p = project()
|
|
|
|
.executable(Path::new("path-test-1").join("cargo-dupe"), "")
|
|
|
|
.executable(Path::new("path-test-2").join("cargo-dupe"), "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let mut path = path();
|
|
|
|
path.push(p.root().join("path-test-1"));
|
|
|
|
path.push(p.root().join("path-test-2"));
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
|
|
|
p.cargo("--list")
|
|
|
|
.env("PATH", &path)
|
|
|
|
.with_stdout_contains_n(" dupe", 1)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2016-05-25 20:55:42 +00:00
|
|
|
fn list_command_looks_at_path() {
|
2021-08-06 00:19:42 +00:00
|
|
|
let proj = project()
|
|
|
|
.executable(Path::new("path-test").join("cargo-1"), "")
|
|
|
|
.build();
|
2014-08-09 05:37:50 +00:00
|
|
|
|
2015-01-14 08:19:27 +00:00
|
|
|
let mut path = path();
|
2014-08-12 04:22:29 +00:00
|
|
|
path.push(proj.root().join("path-test"));
|
2015-02-06 07:27:53 +00:00
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
2018-12-08 11:19:47 +00:00
|
|
|
let output = cargo_process("-v --list")
|
|
|
|
.env("PATH", &path)
|
|
|
|
.exec_with_output()
|
|
|
|
.unwrap();
|
2018-08-29 00:04:28 +00:00
|
|
|
let output = str::from_utf8(&output.stdout).unwrap();
|
|
|
|
assert!(
|
|
|
|
output.contains("\n 1 "),
|
|
|
|
"missing 1: {}",
|
|
|
|
output
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-11-06 02:05:01 +00:00
|
|
|
|
2023-03-09 18:31:04 +00:00
|
|
|
#[cfg(windows)]
|
|
|
|
#[cargo_test]
|
|
|
|
fn list_command_looks_at_path_case_mismatch() {
|
|
|
|
let proj = project()
|
|
|
|
.executable(Path::new("path-test").join("cargo-1"), "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let mut path = path();
|
|
|
|
path.push(proj.root().join("path-test"));
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
|
|
|
// See issue #11814: Environment variable names are case-insensitive on Windows.
|
|
|
|
// We need to check that having "Path" instead of "PATH" is okay.
|
|
|
|
let output = cargo_process("-v --list")
|
|
|
|
.env("Path", &path)
|
|
|
|
.env_remove("PATH")
|
|
|
|
.exec_with_output()
|
|
|
|
.unwrap();
|
|
|
|
let output = str::from_utf8(&output.stdout).unwrap();
|
|
|
|
assert!(
|
|
|
|
output.contains("\n 1 "),
|
|
|
|
"missing 1: {}",
|
|
|
|
output
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-08-27 19:20:55 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn list_command_handles_known_external_commands() {
|
|
|
|
let p = project()
|
|
|
|
.executable(Path::new("path-test").join("cargo-fmt"), "")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let fmt_desc = " fmt Formats all bin and lib files of the current crate using rustfmt.";
|
|
|
|
|
|
|
|
// Without path - fmt isn't there
|
|
|
|
p.cargo("--list")
|
|
|
|
.env("PATH", "")
|
|
|
|
.with_stdout_does_not_contain(fmt_desc)
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// With path - fmt is there with known description
|
|
|
|
let mut path = path();
|
|
|
|
path.push(p.root().join("path-test"));
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
|
|
|
p.cargo("--list")
|
|
|
|
.env("PATH", &path)
|
|
|
|
.with_stdout_contains(fmt_desc)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2016-05-25 20:55:42 +00:00
|
|
|
fn list_command_resolves_symlinks() {
|
2021-08-06 00:19:42 +00:00
|
|
|
let proj = project()
|
|
|
|
.symlink(cargo_exe(), Path::new("path-test").join("cargo-2"))
|
|
|
|
.build();
|
2016-04-19 19:00:30 +00:00
|
|
|
|
|
|
|
let mut path = path();
|
|
|
|
path.push(proj.root().join("path-test"));
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
2018-12-08 11:19:47 +00:00
|
|
|
let output = cargo_process("-v --list")
|
|
|
|
.env("PATH", &path)
|
|
|
|
.exec_with_output()
|
|
|
|
.unwrap();
|
2018-08-29 00:04:28 +00:00
|
|
|
let output = str::from_utf8(&output.stdout).unwrap();
|
|
|
|
assert!(
|
|
|
|
output.contains("\n 2 "),
|
|
|
|
"missing 2: {}",
|
|
|
|
output
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2016-04-19 19:00:30 +00:00
|
|
|
|
2021-12-21 11:56:28 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn find_closest_capital_c_to_c() {
|
|
|
|
cargo_process("C")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains(
|
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `C`
|
2021-12-21 11:56:28 +00:00
|
|
|
|
|
|
|
<tab>Did you mean `c`?
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
2022-05-07 17:07:28 +00:00
|
|
|
fn find_closest_capital_b_to_b() {
|
2021-12-21 11:56:28 +00:00
|
|
|
cargo_process("B")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains(
|
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `B`
|
2021-12-21 11:56:28 +00:00
|
|
|
|
|
|
|
<tab>Did you mean `b`?
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2016-05-25 20:55:42 +00:00
|
|
|
fn find_closest_biuld_to_build() {
|
2018-08-28 09:20:03 +00:00
|
|
|
cargo_process("biuld")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains(
|
2018-03-14 15:17:44 +00:00
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `biuld`
|
2018-03-19 20:13:04 +00:00
|
|
|
|
|
|
|
<tab>Did you mean `build`?
|
2018-03-14 15:17:44 +00:00
|
|
|
",
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.run();
|
2018-03-19 20:13:04 +00:00
|
|
|
|
|
|
|
// But, if we actually have `biuld`, it must work!
|
|
|
|
// https://github.com/rust-lang/cargo/issues/5201
|
|
|
|
Package::new("cargo-biuld", "1.0.0")
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
2020-09-27 00:59:58 +00:00
|
|
|
fn main() {
|
|
|
|
println!("Similar, but not identical to, build");
|
|
|
|
}
|
|
|
|
"#,
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.publish();
|
2018-08-28 09:20:03 +00:00
|
|
|
|
|
|
|
cargo_process("install cargo-biuld").run();
|
|
|
|
cargo_process("biuld")
|
|
|
|
.with_stdout("Similar, but not identical to, build\n")
|
|
|
|
.run();
|
|
|
|
cargo_process("--list")
|
|
|
|
.with_stdout_contains(
|
|
|
|
" build Compile a local package and all of its dependencies\n",
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.with_stdout_contains(" biuld\n")
|
2018-08-28 09:20:03 +00:00
|
|
|
.run();
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-11-06 02:05:01 +00:00
|
|
|
|
2019-10-05 15:44:26 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn find_closest_alias() {
|
|
|
|
let root = paths::root();
|
|
|
|
let my_home = root.join("my_home");
|
|
|
|
fs::create_dir(&my_home).unwrap();
|
2020-04-17 04:10:11 +00:00
|
|
|
fs::write(
|
|
|
|
&my_home.join("config"),
|
|
|
|
r#"
|
|
|
|
[alias]
|
|
|
|
myalias = "build"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2019-10-05 15:44:26 +00:00
|
|
|
|
|
|
|
cargo_process("myalais")
|
|
|
|
.env("CARGO_HOME", &my_home)
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains(
|
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `myalais`
|
2019-10-05 15:44:26 +00:00
|
|
|
|
|
|
|
<tab>Did you mean `myalias`?
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
|
|
|
|
// But, if no alias is defined, it must not suggest one!
|
|
|
|
cargo_process("myalais")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr_contains(
|
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `myalais`
|
2019-10-05 15:44:26 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.with_stderr_does_not_contain(
|
|
|
|
"\
|
|
|
|
<tab>Did you mean `myalias`?
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2019-02-03 04:01:23 +00:00
|
|
|
// If a subcommand is more than an edit distance of 3 away, we don't make a suggestion.
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2016-05-25 20:55:42 +00:00
|
|
|
fn find_closest_dont_correct_nonsense() {
|
2018-08-28 09:20:03 +00:00
|
|
|
cargo_process("there-is-no-way-that-there-is-a-command-close-to-this")
|
|
|
|
.cwd(&paths::root())
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
2022-08-03 00:43:16 +00:00
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
[ERROR] no such command: `there-is-no-way-that-there-is-a-command-close-to-this`
|
2022-08-03 00:43:16 +00:00
|
|
|
|
2023-10-17 19:46:30 +00:00
|
|
|
<tab>View all installed commands with `cargo --list`
|
|
|
|
<tab>Find a package to install `there-is-no-way-that-there-is-a-command-close-to-this` with `cargo search cargo-there-is-no-way-that-there-is-a-command-close-to-this`
|
|
|
|
",
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.run();
|
2016-07-05 12:09:11 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2016-07-05 12:09:11 +00:00
|
|
|
fn displays_subcommand_on_error() {
|
2018-08-28 09:20:03 +00:00
|
|
|
cargo_process("invalid-command")
|
|
|
|
.with_status(101)
|
2022-08-02 23:23:55 +00:00
|
|
|
.with_stderr(
|
2022-08-03 00:43:16 +00:00
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
[ERROR] no such command: `invalid-command`
|
2022-08-03 00:43:16 +00:00
|
|
|
|
2023-10-17 19:46:30 +00:00
|
|
|
<tab>View all installed commands with `cargo --list`
|
|
|
|
<tab>Find a package to install `invalid-command` with `cargo search cargo-invalid-command`
|
|
|
|
",
|
2022-08-02 23:23:55 +00:00
|
|
|
)
|
2018-08-28 09:20:03 +00:00
|
|
|
.run();
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-12-22 21:58:24 +00:00
|
|
|
|
2021-03-20 08:45:19 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn override_cargo_home() {
|
|
|
|
let root = paths::root();
|
|
|
|
let my_home = root.join("my_home");
|
|
|
|
fs::create_dir(&my_home).unwrap();
|
|
|
|
fs::write(
|
|
|
|
&my_home.join("config"),
|
|
|
|
r#"
|
|
|
|
[cargo-new]
|
|
|
|
vcs = "none"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
cargo_process("new foo").env("CARGO_HOME", &my_home).run();
|
|
|
|
|
|
|
|
assert!(!paths::root().join("foo/.git").is_dir());
|
|
|
|
|
|
|
|
cargo_process("new foo2").run();
|
|
|
|
|
|
|
|
assert!(paths::root().join("foo2/.git").is_dir());
|
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2017-03-02 06:38:54 +00:00
|
|
|
fn cargo_subcommand_env() {
|
2018-03-14 15:17:44 +00:00
|
|
|
let src = format!(
|
|
|
|
r#"
|
2017-03-02 06:38:54 +00:00
|
|
|
use std::env;
|
|
|
|
|
|
|
|
fn main() {{
|
|
|
|
println!("{{}}", env::var("{}").unwrap());
|
|
|
|
}}
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
cargo::CARGO_ENV
|
|
|
|
);
|
2017-03-02 06:38:54 +00:00
|
|
|
|
2018-08-28 09:20:03 +00:00
|
|
|
let p = project()
|
|
|
|
.at("cargo-envtest")
|
2017-03-02 06:38:54 +00:00
|
|
|
.file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
|
2017-07-22 03:12:21 +00:00
|
|
|
.file("src/main.rs", &src)
|
|
|
|
.build();
|
2017-03-02 06:38:54 +00:00
|
|
|
|
|
|
|
let target_dir = p.target_debug_dir();
|
|
|
|
|
2018-08-28 09:20:03 +00:00
|
|
|
p.cargo("build").run();
|
2018-08-29 06:11:10 +00:00
|
|
|
assert!(p.bin("cargo-envtest").is_file());
|
2017-03-02 06:38:54 +00:00
|
|
|
|
|
|
|
let cargo = cargo_exe().canonicalize().unwrap();
|
|
|
|
let mut path = path();
|
Make cargo forward pre-existing CARGO if set
Currently, Cargo will always set `$CARGO` to point to what it detects
its own path to be (using `std::env::current_exe`). Unfortunately, this
runs into trouble when Cargo is used as a library, or when `current_exe`
is not actually the binary itself (e.g., when invoked through Valgrind
or `ld.so`), since `$CARGO` will not point at something that can be used
as `cargo`. This, in turn, means that users can't currently rely on
`$CARGO` to do the right thing, and will sometimes have to invoke
`cargo` directly from `$PATH` instead, which may not reflect the `cargo`
that's currently in use.
This patch makes Cargo re-use the existing value of `$CARGO` if it's
already set in the environment. For Cargo subcommands, this will mean
that the initial invocation of `cargo` in `cargo foo` will set `$CARGO`,
and then Cargo-as-a-library inside of `cargo-foo` will inherit that
(correct) value instead of overwriting it with the incorrect value
`cargo-foo`. For other execution environments that do not have `cargo`
in their call stack, it gives them the opportunity to set a working
value for `$CARGO`.
One note about the implementation of this is that the test suite now
needs to override `$CARGO` explicitly so that the _user's_ `$CARGO` does
not interfere with the contents of the tests. It _could_ remove `$CARGO`
instead, but overriding it seemed less error-prone.
Fixes #10119.
Fixes #10113.
2022-10-25 18:49:23 +00:00
|
|
|
path.push(target_dir.clone());
|
2017-03-02 06:38:54 +00:00
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
2018-08-28 09:20:03 +00:00
|
|
|
cargo_process("envtest")
|
|
|
|
.env("PATH", &path)
|
|
|
|
.with_stdout(cargo.to_str().unwrap())
|
|
|
|
.run();
|
Make cargo forward pre-existing CARGO if set
Currently, Cargo will always set `$CARGO` to point to what it detects
its own path to be (using `std::env::current_exe`). Unfortunately, this
runs into trouble when Cargo is used as a library, or when `current_exe`
is not actually the binary itself (e.g., when invoked through Valgrind
or `ld.so`), since `$CARGO` will not point at something that can be used
as `cargo`. This, in turn, means that users can't currently rely on
`$CARGO` to do the right thing, and will sometimes have to invoke
`cargo` directly from `$PATH` instead, which may not reflect the `cargo`
that's currently in use.
This patch makes Cargo re-use the existing value of `$CARGO` if it's
already set in the environment. For Cargo subcommands, this will mean
that the initial invocation of `cargo` in `cargo foo` will set `$CARGO`,
and then Cargo-as-a-library inside of `cargo-foo` will inherit that
(correct) value instead of overwriting it with the incorrect value
`cargo-foo`. For other execution environments that do not have `cargo`
in their call stack, it gives them the opportunity to set a working
value for `$CARGO`.
One note about the implementation of this is that the test suite now
needs to override `$CARGO` explicitly so that the _user's_ `$CARGO` does
not interfere with the contents of the tests. It _could_ remove `$CARGO`
instead, but overriding it seemed less error-prone.
Fixes #10119.
Fixes #10113.
2022-10-25 18:49:23 +00:00
|
|
|
|
2023-01-11 02:03:11 +00:00
|
|
|
// Check that subcommands inherit an overridden $CARGO
|
Make cargo forward pre-existing CARGO if set
Currently, Cargo will always set `$CARGO` to point to what it detects
its own path to be (using `std::env::current_exe`). Unfortunately, this
runs into trouble when Cargo is used as a library, or when `current_exe`
is not actually the binary itself (e.g., when invoked through Valgrind
or `ld.so`), since `$CARGO` will not point at something that can be used
as `cargo`. This, in turn, means that users can't currently rely on
`$CARGO` to do the right thing, and will sometimes have to invoke
`cargo` directly from `$PATH` instead, which may not reflect the `cargo`
that's currently in use.
This patch makes Cargo re-use the existing value of `$CARGO` if it's
already set in the environment. For Cargo subcommands, this will mean
that the initial invocation of `cargo` in `cargo foo` will set `$CARGO`,
and then Cargo-as-a-library inside of `cargo-foo` will inherit that
(correct) value instead of overwriting it with the incorrect value
`cargo-foo`. For other execution environments that do not have `cargo`
in their call stack, it gives them the opportunity to set a working
value for `$CARGO`.
One note about the implementation of this is that the test suite now
needs to override `$CARGO` explicitly so that the _user's_ `$CARGO` does
not interfere with the contents of the tests. It _could_ remove `$CARGO`
instead, but overriding it seemed less error-prone.
Fixes #10119.
Fixes #10113.
2022-10-25 18:49:23 +00:00
|
|
|
let envtest_bin = target_dir
|
|
|
|
.join("cargo-envtest")
|
|
|
|
.with_extension(std::env::consts::EXE_EXTENSION)
|
|
|
|
.canonicalize()
|
|
|
|
.unwrap();
|
|
|
|
let envtest_bin = envtest_bin.to_str().unwrap();
|
|
|
|
cargo_process("envtest")
|
|
|
|
.env("PATH", &path)
|
|
|
|
.env(cargo::CARGO_ENV, &envtest_bin)
|
|
|
|
.with_stdout(envtest_bin)
|
|
|
|
.run();
|
2017-03-02 06:38:54 +00:00
|
|
|
}
|
|
|
|
|
2022-08-25 19:15:34 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn cargo_cmd_bins_vs_explicit_path() {
|
|
|
|
// Set up `cargo-foo` binary in two places: inside `$HOME/.cargo/bin` and outside of it
|
|
|
|
//
|
|
|
|
// Return paths to both places
|
|
|
|
fn set_up_cargo_foo() -> (PathBuf, PathBuf) {
|
|
|
|
let p = project()
|
|
|
|
.at("cargo-foo")
|
|
|
|
.file("Cargo.toml", &basic_manifest("cargo-foo", "1.0.0"))
|
|
|
|
.file(
|
|
|
|
"src/bin/cargo-foo.rs",
|
|
|
|
r#"fn main() { println!("INSIDE"); }"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/bin/cargo-foo2.rs",
|
|
|
|
r#"fn main() { println!("OUTSIDE"); }"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
p.cargo("build").run();
|
|
|
|
let cargo_bin_dir = paths::home().join(".cargo/bin");
|
|
|
|
cargo_bin_dir.mkdir_p();
|
|
|
|
let root_bin_dir = paths::root().join("bin");
|
|
|
|
root_bin_dir.mkdir_p();
|
|
|
|
let exe_name = format!("cargo-foo{}", env::consts::EXE_SUFFIX);
|
|
|
|
fs::rename(p.bin("cargo-foo"), cargo_bin_dir.join(&exe_name)).unwrap();
|
|
|
|
fs::rename(p.bin("cargo-foo2"), root_bin_dir.join(&exe_name)).unwrap();
|
|
|
|
|
|
|
|
(root_bin_dir, cargo_bin_dir)
|
|
|
|
}
|
|
|
|
|
|
|
|
let (outside_dir, inside_dir) = set_up_cargo_foo();
|
|
|
|
|
|
|
|
// If `$CARGO_HOME/bin` is not in a path, prefer it over anything in `$PATH`.
|
|
|
|
//
|
|
|
|
// This is the historical behavior we don't want to break.
|
|
|
|
cargo_process("foo").with_stdout_contains("INSIDE").run();
|
|
|
|
|
|
|
|
// When `$CARGO_HOME/bin` is in the `$PATH`
|
|
|
|
// use only `$PATH` so the user-defined ordering is respected.
|
|
|
|
{
|
|
|
|
cargo_process("foo")
|
|
|
|
.env(
|
|
|
|
"PATH",
|
|
|
|
join_paths(&[&inside_dir, &outside_dir], "PATH").unwrap(),
|
|
|
|
)
|
|
|
|
.with_stdout_contains("INSIDE")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
cargo_process("foo")
|
|
|
|
// Note: trailing slash
|
|
|
|
.env(
|
|
|
|
"PATH",
|
|
|
|
join_paths(&[inside_dir.join(""), outside_dir.join("")], "PATH").unwrap(),
|
|
|
|
)
|
|
|
|
.with_stdout_contains("INSIDE")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
cargo_process("foo")
|
|
|
|
.env(
|
|
|
|
"PATH",
|
|
|
|
join_paths(&[&outside_dir, &inside_dir], "PATH").unwrap(),
|
|
|
|
)
|
|
|
|
.with_stdout_contains("OUTSIDE")
|
|
|
|
.run();
|
|
|
|
|
|
|
|
cargo_process("foo")
|
|
|
|
// Note: trailing slash
|
|
|
|
.env(
|
|
|
|
"PATH",
|
|
|
|
join_paths(&[outside_dir.join(""), inside_dir.join("")], "PATH").unwrap(),
|
|
|
|
)
|
|
|
|
.with_stdout_contains("OUTSIDE")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2018-03-19 21:31:37 +00:00
|
|
|
fn cargo_subcommand_args() {
|
2021-08-09 17:01:04 +00:00
|
|
|
let p = echo_subcommand();
|
|
|
|
let cargo_foo_bin = p.bin("cargo-echo");
|
2018-08-29 06:11:10 +00:00
|
|
|
assert!(cargo_foo_bin.is_file());
|
2018-03-19 21:31:37 +00:00
|
|
|
|
|
|
|
let mut path = path();
|
|
|
|
path.push(p.target_debug_dir());
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
2021-08-09 17:01:04 +00:00
|
|
|
cargo_process("echo bar -v --help")
|
2018-08-28 09:20:03 +00:00
|
|
|
.env("PATH", &path)
|
2021-08-09 17:01:04 +00:00
|
|
|
.with_stdout("echo bar -v --help")
|
2018-11-18 13:38:33 +00:00
|
|
|
.run();
|
2018-03-19 21:31:37 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 18:52:53 +00:00
|
|
|
#[cargo_test]
|
2016-05-25 20:55:42 +00:00
|
|
|
fn explain() {
|
2018-08-28 09:20:03 +00:00
|
|
|
cargo_process("--explain E0001")
|
|
|
|
.with_stdout_contains(
|
2018-03-14 15:43:41 +00:00
|
|
|
"This error suggests that the expression arm corresponding to the noted pattern",
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.run();
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2018-03-31 09:19:28 +00:00
|
|
|
|
2020-05-12 15:03:35 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn closed_output_ok() {
|
|
|
|
// Checks that closed output doesn't cause an error.
|
|
|
|
let mut p = cargo_process("--list").build_command();
|
|
|
|
p.stdout(Stdio::piped()).stderr(Stdio::piped());
|
|
|
|
let mut child = p.spawn().unwrap();
|
|
|
|
// Close stdout
|
|
|
|
drop(child.stdout.take());
|
|
|
|
// Read stderr
|
|
|
|
let mut s = String::new();
|
|
|
|
child
|
|
|
|
.stderr
|
|
|
|
.as_mut()
|
|
|
|
.unwrap()
|
|
|
|
.read_to_string(&mut s)
|
|
|
|
.unwrap();
|
|
|
|
let status = child.wait().unwrap();
|
|
|
|
assert!(status.success());
|
2021-02-06 17:40:42 +00:00
|
|
|
assert!(s.is_empty(), "{}", s);
|
2020-05-12 15:03:35 +00:00
|
|
|
}
|
2022-08-03 16:07:17 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn subcommand_leading_plus_output_contains() {
|
|
|
|
cargo_process("+nightly")
|
|
|
|
.with_status(101)
|
2022-08-03 16:38:41 +00:00
|
|
|
.with_stderr(
|
2022-08-03 16:07:17 +00:00
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `+nightly`
|
2022-08-03 16:38:41 +00:00
|
|
|
|
|
|
|
<tab>Cargo does not handle `+toolchain` directives.
|
|
|
|
<tab>Did you mean to invoke `cargo` through `rustup` instead?",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn full_did_you_mean() {
|
|
|
|
cargo_process("bluid")
|
|
|
|
.with_status(101)
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
2022-09-20 18:19:46 +00:00
|
|
|
error: no such command: `bluid`
|
2022-08-03 16:38:41 +00:00
|
|
|
|
|
|
|
<tab>Did you mean `build`?
|
|
|
|
|
2023-10-17 19:46:30 +00:00
|
|
|
<tab>View all installed commands with `cargo --list`
|
|
|
|
<tab>Find a package to install `bluid` with `cargo search cargo-bluid`
|
|
|
|
",
|
2022-08-03 16:07:17 +00:00
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|