2015-02-06 07:27:53 +00:00
|
|
|
use std::env;
|
2015-02-27 01:04:25 +00:00
|
|
|
use std::fs::{self, File};
|
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::path::{Path, PathBuf};
|
2014-08-21 16:24:34 +00:00
|
|
|
use std::str;
|
|
|
|
|
2018-02-08 16:30:58 +00:00
|
|
|
use cargo;
|
2016-05-26 00:06:25 +00:00
|
|
|
use cargotest::cargo_process;
|
|
|
|
use cargotest::support::paths::{self, CargoPathExt};
|
2018-03-19 20:13:04 +00:00
|
|
|
use cargotest::support::registry::Package;
|
2018-03-19 21:31:37 +00:00
|
|
|
use cargotest::support::{basic_bin_manifest, cargo_exe, execs, project, Project};
|
2017-03-02 06:38:54 +00:00
|
|
|
use hamcrest::{assert_that, existing_file};
|
2014-08-09 05:37:50 +00:00
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
#[cfg_attr(windows, allow(dead_code))]
|
2016-04-19 19:00:30 +00:00
|
|
|
enum FakeKind<'a> {
|
|
|
|
Executable,
|
2018-03-14 15:17:44 +00:00
|
|
|
Symlink { target: &'a Path },
|
2016-04-19 19:00:30 +00:00
|
|
|
}
|
|
|
|
|
2014-08-09 05:37:50 +00:00
|
|
|
/// Add an empty file with executable flags (and platform-dependent suffix).
|
2017-07-22 03:12:21 +00:00
|
|
|
/// TODO: move this to `Project` if other cases using this emerge.
|
|
|
|
fn fake_file(proj: Project, dir: &Path, name: &str, kind: &FakeKind) -> Project {
|
2018-03-14 15:17:44 +00:00
|
|
|
let path = proj.root()
|
|
|
|
.join(dir)
|
|
|
|
.join(&format!("{}{}", name, env::consts::EXE_SUFFIX));
|
2016-05-26 00:06:25 +00:00
|
|
|
path.parent().unwrap().mkdir_p();
|
2017-09-24 14:26:37 +00:00
|
|
|
match *kind {
|
2016-04-19 19:00:30 +00:00
|
|
|
FakeKind::Executable => {
|
|
|
|
File::create(&path).unwrap();
|
|
|
|
make_executable(&path);
|
2018-03-14 15:17:44 +00:00
|
|
|
}
|
|
|
|
FakeKind::Symlink { target } => {
|
|
|
|
make_symlink(&path, target);
|
2016-04-19 19:00:30 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-27 01:04:25 +00:00
|
|
|
return proj;
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
fn make_executable(p: &Path) {
|
|
|
|
use std::os::unix::prelude::*;
|
|
|
|
|
2016-04-19 18:59:55 +00:00
|
|
|
let mut perms = fs::metadata(p).unwrap().permissions();
|
2015-02-27 01:04:25 +00:00
|
|
|
let mode = perms.mode();
|
|
|
|
perms.set_mode(mode | 0o111);
|
|
|
|
fs::set_permissions(p, perms).unwrap();
|
|
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
|
|
fn make_executable(_: &Path) {}
|
2016-04-19 19:00:30 +00:00
|
|
|
#[cfg(unix)]
|
|
|
|
fn make_symlink(p: &Path, t: &Path) {
|
2018-03-14 15:17:44 +00:00
|
|
|
::std::os::unix::fs::symlink(t, p).expect("Failed to create symlink");
|
2016-04-19 19:00:30 +00:00
|
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
|
|
fn make_symlink(_: &Path, _: &Path) {
|
|
|
|
panic!("Not supported")
|
|
|
|
}
|
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
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn list_command_looks_at_path() {
|
2018-07-20 11:47:47 +00:00
|
|
|
let proj = project().at("list-non-overlapping").build();
|
2018-03-14 15:17:44 +00:00
|
|
|
let proj = fake_file(
|
|
|
|
proj,
|
|
|
|
Path::new("path-test"),
|
|
|
|
"cargo-1",
|
|
|
|
&FakeKind::Executable,
|
|
|
|
);
|
2015-12-17 17:53:14 +00:00
|
|
|
let mut pr = cargo_process();
|
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-03-14 15:17:44 +00:00
|
|
|
let output = pr.arg("-v").arg("--list").env("PATH", &path);
|
2014-12-21 23:19:44 +00:00
|
|
|
let output = output.exec_with_output().unwrap();
|
2015-02-27 01:04:25 +00:00
|
|
|
let output = str::from_utf8(&output.stdout).unwrap();
|
2018-03-14 15:17:44 +00:00
|
|
|
assert!(
|
|
|
|
output.contains("\n 1 "),
|
|
|
|
"missing 1: {}",
|
|
|
|
output
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-11-06 02:05:01 +00:00
|
|
|
|
2016-04-19 19:00:30 +00:00
|
|
|
// windows and symlinks don't currently agree that well
|
|
|
|
#[cfg(unix)]
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn list_command_resolves_symlinks() {
|
2018-07-20 11:47:47 +00:00
|
|
|
let proj = project().at("list-non-overlapping").build();
|
2018-03-14 15:17:44 +00:00
|
|
|
let proj = fake_file(
|
|
|
|
proj,
|
|
|
|
Path::new("path-test"),
|
|
|
|
"cargo-2",
|
|
|
|
&FakeKind::Symlink {
|
|
|
|
target: &cargo_exe(),
|
|
|
|
},
|
|
|
|
);
|
2016-04-19 19:00:30 +00:00
|
|
|
let mut pr = cargo_process();
|
|
|
|
|
|
|
|
let mut path = path();
|
|
|
|
path.push(proj.root().join("path-test"));
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
2018-03-14 15:17:44 +00:00
|
|
|
let output = pr.arg("-v").arg("--list").env("PATH", &path);
|
2016-04-19 19:00:30 +00:00
|
|
|
let output = output.exec_with_output().unwrap();
|
|
|
|
let output = str::from_utf8(&output.stdout).unwrap();
|
2018-03-14 15:17:44 +00:00
|
|
|
assert!(
|
|
|
|
output.contains("\n 2 "),
|
|
|
|
"missing 2: {}",
|
|
|
|
output
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2016-04-19 19:00:30 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn find_closest_biuld_to_build() {
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(
|
2018-03-19 20:13:04 +00:00
|
|
|
cargo_process().arg("biuld"),
|
|
|
|
execs().with_status(101).with_stderr_contains(
|
2018-03-14 15:17:44 +00:00
|
|
|
"\
|
2018-03-19 20:13:04 +00:00
|
|
|
error: no such subcommand: `biuld`
|
|
|
|
|
|
|
|
<tab>Did you mean `build`?
|
2018-03-14 15:17:44 +00:00
|
|
|
",
|
|
|
|
),
|
|
|
|
);
|
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#"
|
|
|
|
fn main() {
|
|
|
|
println!("Similar, but not identical to, build");
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("install").arg("cargo-biuld"),
|
|
|
|
execs().with_status(0),
|
|
|
|
);
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("biuld"),
|
|
|
|
execs()
|
|
|
|
.with_status(0)
|
|
|
|
.with_stdout("Similar, but not identical to, build\n"),
|
|
|
|
);
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("--list"),
|
|
|
|
execs()
|
|
|
|
.with_status(0)
|
|
|
|
.with_stdout_contains(" build\n")
|
|
|
|
.with_stdout_contains(" biuld\n"),
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-11-06 02:05:01 +00:00
|
|
|
|
|
|
|
// if a subcommand is more than 3 edit distance away, we don't make a suggestion
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn find_closest_dont_correct_nonsense() {
|
2015-12-17 17:53:14 +00:00
|
|
|
let mut pr = cargo_process();
|
2016-04-08 20:30:45 +00:00
|
|
|
pr.arg("there-is-no-way-that-there-is-a-command-close-to-this")
|
2018-03-14 15:17:44 +00:00
|
|
|
.cwd(&paths::root());
|
2014-11-06 02:05:01 +00:00
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(
|
|
|
|
pr,
|
|
|
|
execs().with_status(101).with_stderr(
|
|
|
|
"[ERROR] no such subcommand: \
|
2016-07-05 12:49:01 +00:00
|
|
|
`there-is-no-way-that-there-is-a-command-close-to-this`
|
2018-03-14 15:17:44 +00:00
|
|
|
",
|
|
|
|
),
|
|
|
|
);
|
2016-07-05 12:09:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn displays_subcommand_on_error() {
|
|
|
|
let mut pr = cargo_process();
|
|
|
|
pr.arg("invalid-command");
|
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(
|
|
|
|
pr,
|
|
|
|
execs().with_status(101).with_stderr(
|
|
|
|
"[ERROR] no such subcommand: `invalid-command`
|
|
|
|
",
|
|
|
|
),
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2014-12-22 21:58:24 +00:00
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn override_cargo_home() {
|
2014-12-22 21:58:24 +00:00
|
|
|
let root = paths::root();
|
|
|
|
let my_home = root.join("my_home");
|
2015-02-27 01:04:25 +00:00
|
|
|
fs::create_dir(&my_home).unwrap();
|
2018-03-14 15:17:44 +00:00
|
|
|
File::create(&my_home.join("config"))
|
|
|
|
.unwrap()
|
|
|
|
.write_all(
|
|
|
|
br#"
|
2014-12-22 21:58:24 +00:00
|
|
|
[cargo-new]
|
|
|
|
name = "foo"
|
|
|
|
email = "bar"
|
|
|
|
git = false
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2014-12-22 21:58:24 +00:00
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(
|
|
|
|
cargo_process()
|
|
|
|
.arg("new")
|
|
|
|
.arg("foo")
|
|
|
|
.env("USER", "foo")
|
|
|
|
.env("CARGO_HOME", &my_home),
|
|
|
|
execs().with_status(0),
|
|
|
|
);
|
2014-12-22 21:58:24 +00:00
|
|
|
|
|
|
|
let toml = paths::root().join("foo/Cargo.toml");
|
2015-02-27 01:04:25 +00:00
|
|
|
let mut contents = String::new();
|
2018-03-14 15:17:44 +00:00
|
|
|
File::open(&toml)
|
|
|
|
.unwrap()
|
|
|
|
.read_to_string(&mut contents)
|
|
|
|
.unwrap();
|
2015-02-27 01:04:25 +00:00
|
|
|
assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2015-03-16 13:32:50 +00:00
|
|
|
|
2017-03-02 06:38:54 +00:00
|
|
|
#[test]
|
|
|
|
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-07-20 11:47:47 +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();
|
|
|
|
|
2017-07-22 03:12:21 +00:00
|
|
|
assert_that(p.cargo("build"), execs().with_status(0));
|
2017-03-02 06:38:54 +00:00
|
|
|
assert_that(&p.bin("cargo-envtest"), existing_file());
|
|
|
|
|
|
|
|
let mut pr = cargo_process();
|
|
|
|
let cargo = cargo_exe().canonicalize().unwrap();
|
|
|
|
let mut path = path();
|
|
|
|
path.push(target_dir);
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(
|
|
|
|
pr.arg("envtest").env("PATH", &path),
|
|
|
|
execs().with_status(0).with_stdout(cargo.to_str().unwrap()),
|
|
|
|
);
|
2017-03-02 06:38:54 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:31:37 +00:00
|
|
|
#[test]
|
|
|
|
fn cargo_subcommand_args() {
|
2018-07-20 11:47:47 +00:00
|
|
|
let p = project().at("cargo-foo")
|
2018-03-19 21:31:37 +00:00
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "cargo-foo"
|
|
|
|
version = "0.0.1"
|
|
|
|
authors = []
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
let args: Vec<_> = ::std::env::args().collect();
|
|
|
|
println!("{:?}", args);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_that(p.cargo("build"), execs().with_status(0));
|
|
|
|
let cargo_foo_bin = p.bin("cargo-foo");
|
|
|
|
assert_that(&cargo_foo_bin, existing_file());
|
|
|
|
|
|
|
|
let mut path = path();
|
|
|
|
path.push(p.target_debug_dir());
|
|
|
|
let path = env::join_paths(path.iter()).unwrap();
|
|
|
|
|
|
|
|
assert_that(
|
|
|
|
cargo_process()
|
|
|
|
.env("PATH", &path)
|
|
|
|
.arg("foo")
|
|
|
|
.arg("bar")
|
|
|
|
.arg("-v")
|
|
|
|
.arg("--help"),
|
|
|
|
execs().with_status(0).with_stdout(format!(
|
|
|
|
r#"[{:?}, "foo", "bar", "-v", "--help"]"#,
|
|
|
|
cargo_foo_bin
|
|
|
|
)),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn cargo_help() {
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(cargo_process(), execs().with_status(0));
|
|
|
|
assert_that(cargo_process().arg("help"), execs().with_status(0));
|
|
|
|
assert_that(cargo_process().arg("-h"), execs().with_status(0));
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("help").arg("build"),
|
|
|
|
execs().with_status(0),
|
|
|
|
);
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("build").arg("-h"),
|
|
|
|
execs().with_status(0),
|
|
|
|
);
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("help").arg("help"),
|
|
|
|
execs().with_status(0),
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2016-04-08 00:27:49 +00:00
|
|
|
|
2018-07-11 21:14:41 +00:00
|
|
|
#[test]
|
|
|
|
fn cargo_help_external_subcommand() {
|
|
|
|
Package::new("cargo-fake-help", "1.0.0")
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
if ::std::env::args().nth(2) == Some(String::from("--help")) {
|
|
|
|
println!("fancy help output");
|
|
|
|
}
|
|
|
|
}"#,
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
assert_that(
|
|
|
|
cargo_process().args(&["install", "cargo-fake-help"]),
|
|
|
|
execs().with_status(0),
|
|
|
|
);
|
|
|
|
assert_that(
|
|
|
|
cargo_process().args(&["help", "fake-help"]),
|
|
|
|
execs().with_status(0).with_stdout("fancy help output\n")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-05-25 20:55:42 +00:00
|
|
|
#[test]
|
|
|
|
fn explain() {
|
2018-03-14 15:17:44 +00:00
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("--explain").arg("E0001"),
|
|
|
|
execs().with_status(0).with_stdout_contains(
|
2018-03-14 15:43:41 +00:00
|
|
|
"This error suggests that the expression arm corresponding to the noted pattern",
|
2018-03-14 15:17:44 +00:00
|
|
|
),
|
|
|
|
);
|
2016-05-25 20:55:42 +00:00
|
|
|
}
|
2018-03-31 09:19:28 +00:00
|
|
|
|
|
|
|
// Test that the output of 'cargo -Z help' shows a different help screen with
|
|
|
|
// all the -Z flags.
|
|
|
|
#[test]
|
|
|
|
fn z_flags_help() {
|
|
|
|
assert_that(
|
|
|
|
cargo_process().arg("-Z").arg("help"),
|
2018-03-31 09:33:14 +00:00
|
|
|
execs().with_status(0).with_stdout_contains(
|
|
|
|
" -Z unstable-options -- Allow the usage of unstable options such as --registry",
|
|
|
|
),
|
2018-03-31 09:19:28 +00:00
|
|
|
);
|
|
|
|
}
|