mirror of
https://github.com/rust-lang/cargo
synced 2024-08-25 10:35:53 +00:00
787 lines
26 KiB
Rust
787 lines
26 KiB
Rust
use cargo::core::PackageId;
|
|
use std::collections::BTreeSet;
|
|
use std::env;
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
|
|
use crate::support::install::{cargo_home, exe};
|
|
use crate::support::paths::CargoPathExt;
|
|
use crate::support::registry::Package;
|
|
use crate::support::{
|
|
basic_manifest, cargo_process, cross_compile, execs, git, process, project, Execs,
|
|
};
|
|
|
|
// Helper for publishing a package.
|
|
fn pkg(name: &str, vers: &str) {
|
|
Package::new(name, vers)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"fn main() { println!("{}", env!("CARGO_PKG_VERSION")) }"#,
|
|
)
|
|
.publish();
|
|
}
|
|
|
|
fn v1_path() -> PathBuf {
|
|
cargo_home().join(".crates.toml")
|
|
}
|
|
|
|
fn v2_path() -> PathBuf {
|
|
cargo_home().join(".crates2.json")
|
|
}
|
|
|
|
fn load_crates1() -> toml::Value {
|
|
toml::from_str(&fs::read_to_string(v1_path()).unwrap()).unwrap()
|
|
}
|
|
|
|
fn load_crates2() -> serde_json::Value {
|
|
serde_json::from_str(&fs::read_to_string(v2_path()).unwrap()).unwrap()
|
|
}
|
|
|
|
fn installed_exe(name: &str) -> PathBuf {
|
|
cargo_home().join("bin").join(exe(name))
|
|
}
|
|
|
|
/// Helper for executing binaries installed by cargo.
|
|
fn installed_process(name: &str) -> Execs {
|
|
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
|
thread_local!(static UNIQUE_ID: usize = NEXT_ID.fetch_add(1, Ordering::SeqCst));
|
|
|
|
// This copies the executable to a unique name so that it may be safely
|
|
// replaced on Windows. See Project::rename_run for details.
|
|
let src = installed_exe(name);
|
|
let dst = installed_exe(&UNIQUE_ID.with(|my_id| format!("{}-{}", name, my_id)));
|
|
// Note: Cannot use copy. On Linux, file descriptors may be left open to
|
|
// the executable as other tests in other threads are constantly spawning
|
|
// new processes (see https://github.com/rust-lang/cargo/pull/5557 for
|
|
// more).
|
|
fs::rename(&src, &dst)
|
|
.unwrap_or_else(|e| panic!("Failed to rename `{:?}` to `{:?}`: {}", src, dst, e));
|
|
// Leave behind a fake file so that reinstall duplicate check works.
|
|
fs::write(src, "").unwrap();
|
|
let p = process(dst);
|
|
execs().with_process_builder(p)
|
|
}
|
|
|
|
/// Check that the given package name/version has the following bins listed in
|
|
/// the trackers. Also verifies that both trackers are in sync and valid.
|
|
fn validate_trackers(name: &str, version: &str, bins: &[&str]) {
|
|
let v1 = load_crates1();
|
|
let v1_table = v1.get("v1").unwrap().as_table().unwrap();
|
|
let v2 = load_crates2();
|
|
let v2_table = v2["installs"].as_object().unwrap();
|
|
assert_eq!(v1_table.len(), v2_table.len());
|
|
// Convert `bins` to a BTreeSet.
|
|
let bins: BTreeSet<String> = bins
|
|
.iter()
|
|
.map(|b| format!("{}{}", b, env::consts::EXE_SUFFIX))
|
|
.collect();
|
|
// Check every entry matches between v1 and v2.
|
|
for (pkg_id_str, v1_bins) in v1_table {
|
|
let pkg_id: PackageId = toml::Value::from(pkg_id_str.to_string())
|
|
.try_into()
|
|
.unwrap();
|
|
let v1_bins: BTreeSet<String> = v1_bins
|
|
.as_array()
|
|
.unwrap()
|
|
.iter()
|
|
.map(|b| b.as_str().unwrap().to_string())
|
|
.collect();
|
|
if pkg_id.name().as_str() == name && pkg_id.version().to_string() == version {
|
|
assert_eq!(bins, v1_bins);
|
|
}
|
|
let pkg_id_value = serde_json::to_value(&pkg_id).unwrap();
|
|
let pkg_id_str = pkg_id_value.as_str().unwrap();
|
|
let v2_info = v2_table
|
|
.get(pkg_id_str)
|
|
.expect("v2 missing v1 pkg")
|
|
.as_object()
|
|
.unwrap();
|
|
let v2_bins = v2_info["bins"].as_array().unwrap();
|
|
let v2_bins: BTreeSet<String> = v2_bins
|
|
.iter()
|
|
.map(|b| b.as_str().unwrap().to_string())
|
|
.collect();
|
|
assert_eq!(v1_bins, v2_bins);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn registry_upgrade() {
|
|
// Installing and upgrading from a registry.
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] foo v1.0.0 (registry [..])
|
|
[INSTALLING] foo v1.0.0
|
|
[COMPILING] foo v1.0.0
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
|
|
[INSTALLED] package `foo v1.0.0` (executable `foo[EXE]`)
|
|
[WARNING] be sure to add [..]
|
|
",
|
|
)
|
|
.run();
|
|
installed_process("foo").with_stdout("1.0.0").run();
|
|
validate_trackers("foo", "1.0.0", &["foo"]);
|
|
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[IGNORED] package `foo v1.0.0` is already installed[..]
|
|
[WARNING] be sure to add [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
pkg("foo", "1.0.1");
|
|
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] foo v1.0.1 (registry [..])
|
|
[INSTALLING] foo v1.0.1
|
|
[COMPILING] foo v1.0.1
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[REPLACING] [CWD]/home/.cargo/bin/foo[EXE]
|
|
[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`)
|
|
[WARNING] be sure to add [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
installed_process("foo").with_stdout("1.0.1").run();
|
|
validate_trackers("foo", "1.0.1", &["foo"]);
|
|
|
|
cargo_process("install foo --version=1.0.0 -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[COMPILING] foo v1.0.0")
|
|
.run();
|
|
installed_process("foo").with_stdout("1.0.0").run();
|
|
validate_trackers("foo", "1.0.0", &["foo"]);
|
|
|
|
cargo_process("install foo --version=^1.0 -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[COMPILING] foo v1.0.1")
|
|
.run();
|
|
installed_process("foo").with_stdout("1.0.1").run();
|
|
validate_trackers("foo", "1.0.1", &["foo"]);
|
|
|
|
cargo_process("install foo --version=^1.0 -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[IGNORED] package `foo v1.0.1` is already installed[..]")
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn uninstall() {
|
|
// Basic uninstall test.
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
cargo_process("uninstall foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
let data = load_crates2();
|
|
assert_eq!(data["installs"].as_object().unwrap().len(), 0);
|
|
let v1_table = load_crates1();
|
|
assert_eq!(v1_table.get("v1").unwrap().as_table().unwrap().len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn upgrade_force() {
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
cargo_process("install foo -Z install-upgrade --force")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[INSTALLING] foo v1.0.0
|
|
[COMPILING] foo v1.0.0
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[REPLACING] [..]/.cargo/bin/foo[EXE]
|
|
[REPLACED] package `foo v1.0.0` with `foo v1.0.0` (executable `foo[EXE]`)
|
|
[WARNING] be sure to add `[..]/.cargo/bin` to your PATH [..]
|
|
",
|
|
)
|
|
.run();
|
|
validate_trackers("foo", "1.0.0", &["foo"]);
|
|
}
|
|
|
|
#[test]
|
|
fn ambiguous_version_no_longer_allowed() {
|
|
// Non-semver-requirement is not allowed for `--version`.
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo --version=1.0 -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[ERROR] the `--vers` provided, `1.0`, is not a valid semver version: cannot parse '1.0' as a semver
|
|
|
|
if you want to specify semver range, add an explicit qualifier, like ^1.0
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn path_is_always_dirty() {
|
|
// --path should always reinstall.
|
|
let p = project().file("src/main.rs", "fn main() {}").build();
|
|
p.cargo("install --path . -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
p.cargo("install --path . -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[REPLACING] [..]/foo[EXE]")
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn fails_for_conflicts_unknown() {
|
|
// If an untracked file is in the way, it should fail.
|
|
pkg("foo", "1.0.0");
|
|
let exe = installed_exe("foo");
|
|
exe.parent().unwrap().mkdir_p();
|
|
fs::write(exe, "").unwrap();
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[ERROR] binary `foo[EXE]` already exists in destination")
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn fails_for_conflicts_known() {
|
|
// If the same binary exists in another package, it should fail.
|
|
pkg("foo", "1.0.0");
|
|
Package::new("bar", "1.0.0")
|
|
.file("src/bin/foo.rs", "fn main() {}")
|
|
.publish();
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
cargo_process("install bar -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains(
|
|
"[ERROR] binary `foo[EXE]` already exists in destination as part of `foo v1.0.0`",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn supports_multiple_binary_names() {
|
|
// Can individually install with --bin or --example
|
|
Package::new("foo", "1.0.0")
|
|
.file("src/main.rs", r#"fn main() { println!("foo"); }"#)
|
|
.file("src/bin/a.rs", r#"fn main() { println!("a"); }"#)
|
|
.file("examples/ex1.rs", r#"fn main() { println!("ex1"); }"#)
|
|
.publish();
|
|
cargo_process("install foo -Z install-upgrade --bin foo")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("foo").run();
|
|
assert!(!installed_exe("a").exists());
|
|
assert!(!installed_exe("ex1").exists());
|
|
validate_trackers("foo", "1.0.0", &["foo"]);
|
|
cargo_process("install foo -Z install-upgrade --bin a")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("a").with_stdout("a").run();
|
|
assert!(!installed_exe("ex1").exists());
|
|
validate_trackers("foo", "1.0.0", &["a", "foo"]);
|
|
cargo_process("install foo -Z install-upgrade --example ex1")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("ex1").with_stdout("ex1").run();
|
|
validate_trackers("foo", "1.0.0", &["a", "ex1", "foo"]);
|
|
cargo_process("uninstall foo -Z install-upgrade --bin foo")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
assert!(!installed_exe("foo").exists());
|
|
assert!(installed_exe("ex1").exists());
|
|
validate_trackers("foo", "1.0.0", &["a", "ex1"]);
|
|
cargo_process("uninstall foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
assert!(!installed_exe("ex1").exists());
|
|
assert!(!installed_exe("a").exists());
|
|
}
|
|
|
|
#[test]
|
|
fn v1_already_installed_fresh() {
|
|
// Install with v1, then try to install again with v2.
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo").run();
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.with_stderr_contains("[IGNORED] package `foo v1.0.0` is already installed[..]")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn v1_already_installed_dirty() {
|
|
// Install with v1, then install a new version with v2.
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo").run();
|
|
pkg("foo", "1.0.1");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.with_stderr_contains("[COMPILING] foo v1.0.1")
|
|
.with_stderr_contains("[REPLACING] [..]/foo[EXE]")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
validate_trackers("foo", "1.0.1", &["foo"]);
|
|
}
|
|
|
|
#[test]
|
|
fn change_features_rebuilds() {
|
|
Package::new("foo", "1.0.0")
|
|
.file(
|
|
"src/main.rs",
|
|
r#"fn main() {
|
|
if cfg!(feature = "f1") {
|
|
println!("f1");
|
|
}
|
|
if cfg!(feature = "f2") {
|
|
println!("f2");
|
|
}
|
|
}"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.0.0"
|
|
|
|
[features]
|
|
f1 = []
|
|
f2 = []
|
|
default = ["f1"]
|
|
"#,
|
|
)
|
|
.publish();
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("f1").run();
|
|
cargo_process("install foo -Z install-upgrade --no-default-features")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("").run();
|
|
cargo_process("install foo -Z install-upgrade --all-features")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("f1\nf2").run();
|
|
cargo_process("install foo -Z install-upgrade --no-default-features --features=f1")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("f1").run();
|
|
}
|
|
|
|
#[test]
|
|
fn change_profile_rebuilds() {
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
cargo_process("install foo -Z install-upgrade --debug")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[COMPILING] foo v1.0.0")
|
|
.with_stderr_contains("[REPLACING] [..]foo[EXE]")
|
|
.run();
|
|
cargo_process("install foo -Z install-upgrade --debug")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[IGNORED] package `foo v1.0.0` is already installed[..]")
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn change_target_rebuilds() {
|
|
if cross_compile::disabled() {
|
|
return;
|
|
}
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
let target = cross_compile::alternate();
|
|
cargo_process("install foo -v -Z install-upgrade --target")
|
|
.arg(&target)
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[COMPILING] foo v1.0.0")
|
|
.with_stderr_contains("[REPLACING] [..]foo[EXE]")
|
|
.with_stderr_contains(&format!("[..]--target {}[..]", target))
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn change_bin_sets_rebuilds() {
|
|
// Changing which bins in a multi-bin project should reinstall.
|
|
Package::new("foo", "1.0.0")
|
|
.file("src/main.rs", "fn main() { }")
|
|
.file("src/bin/x.rs", "fn main() { }")
|
|
.file("src/bin/y.rs", "fn main() { }")
|
|
.publish();
|
|
cargo_process("install foo -Z install-upgrade --bin x")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
assert!(installed_exe("x").exists());
|
|
assert!(!installed_exe("y").exists());
|
|
assert!(!installed_exe("foo").exists());
|
|
validate_trackers("foo", "1.0.0", &["x"]);
|
|
cargo_process("install foo -Z install-upgrade --bin y")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[INSTALLED] package `foo v1.0.0` (executable `y[EXE]`)")
|
|
.run();
|
|
assert!(installed_exe("x").exists());
|
|
assert!(installed_exe("y").exists());
|
|
assert!(!installed_exe("foo").exists());
|
|
validate_trackers("foo", "1.0.0", &["x", "y"]);
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[INSTALLED] package `foo v1.0.0` (executable `foo[EXE]`)")
|
|
.with_stderr_contains(
|
|
"[REPLACED] package `foo v1.0.0` with `foo v1.0.0` (executables `x[EXE]`, `y[EXE]`)",
|
|
)
|
|
.run();
|
|
assert!(installed_exe("x").exists());
|
|
assert!(installed_exe("y").exists());
|
|
assert!(installed_exe("foo").exists());
|
|
validate_trackers("foo", "1.0.0", &["foo", "x", "y"]);
|
|
}
|
|
|
|
#[test]
|
|
fn forwards_compatible() {
|
|
// Unknown fields should be preserved.
|
|
pkg("foo", "1.0.0");
|
|
pkg("bar", "1.0.0");
|
|
cargo_process("install foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
let key = "foo 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)";
|
|
let v2 = cargo_home().join(".crates2.json");
|
|
let mut data = load_crates2();
|
|
data["newfield"] = serde_json::Value::Bool(true);
|
|
data["installs"][key]["moreinfo"] = serde_json::Value::String("shazam".to_string());
|
|
fs::write(&v2, serde_json::to_string(&data).unwrap()).unwrap();
|
|
cargo_process("install bar -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
let data: serde_json::Value = serde_json::from_str(&fs::read_to_string(&v2).unwrap()).unwrap();
|
|
assert_eq!(data["newfield"].as_bool().unwrap(), true);
|
|
assert_eq!(
|
|
data["installs"][key]["moreinfo"].as_str().unwrap(),
|
|
"shazam"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn v2_syncs() {
|
|
// V2 inherits the installs from V1.
|
|
pkg("one", "1.0.0");
|
|
pkg("two", "1.0.0");
|
|
pkg("three", "1.0.0");
|
|
let p = project()
|
|
.file("src/bin/x.rs", "fn main() {}")
|
|
.file("src/bin/y.rs", "fn main() {}")
|
|
.build();
|
|
cargo_process("install one -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
validate_trackers("one", "1.0.0", &["one"]);
|
|
p.cargo("install -Z install-upgrade --path .")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
validate_trackers("foo", "1.0.0", &["x", "y"]);
|
|
// v1 add/remove
|
|
cargo_process("install two").run();
|
|
cargo_process("uninstall one").run();
|
|
// This should pick up that `two` was added, `one` was removed.
|
|
cargo_process("install three -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
validate_trackers("three", "1.0.0", &["three"]);
|
|
cargo_process("install --list")
|
|
.with_stdout(
|
|
"\
|
|
foo v0.0.1 ([..]/foo):
|
|
x[EXE]
|
|
y[EXE]
|
|
three v1.0.0:
|
|
three[EXE]
|
|
two v1.0.0:
|
|
two[EXE]
|
|
",
|
|
)
|
|
.run();
|
|
cargo_process("install one -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("one").with_stdout("1.0.0").run();
|
|
validate_trackers("one", "1.0.0", &["one"]);
|
|
cargo_process("install two -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[IGNORED] package `two v1.0.0` is already installed[..]")
|
|
.run();
|
|
// v1 remove
|
|
p.cargo("uninstall --bin x").run();
|
|
pkg("x", "1.0.0");
|
|
pkg("y", "1.0.0");
|
|
// This should succeed because `x` was removed in V1.
|
|
cargo_process("install x -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
validate_trackers("x", "1.0.0", &["x"]);
|
|
// This should fail because `y` still exists in a different package.
|
|
cargo_process("install y -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains(
|
|
"[ERROR] binary `y[EXE]` already exists in destination \
|
|
as part of `foo v0.0.1 ([..])`",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn upgrade_git() {
|
|
let git_project =
|
|
git::new("foo", |project| project.file("src/main.rs", "fn main() {}")).unwrap();
|
|
// install
|
|
cargo_process("install -Z install-upgrade --git")
|
|
.arg(git_project.url().to_string())
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
// Check install stays fresh.
|
|
cargo_process("install -Z install-upgrade --git")
|
|
.arg(git_project.url().to_string())
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains(
|
|
"[IGNORED] package `foo v0.0.1 (file://[..]/foo#[..])` is \
|
|
already installed,[..]",
|
|
)
|
|
.run();
|
|
// Modify a file.
|
|
let repo = git2::Repository::open(git_project.root()).unwrap();
|
|
git_project.change_file("src/main.rs", r#"fn main() {println!("onomatopoeia");}"#);
|
|
git::add(&repo);
|
|
git::commit(&repo);
|
|
// Install should reinstall.
|
|
cargo_process("install -Z install-upgrade --git")
|
|
.arg(git_project.url().to_string())
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[COMPILING] foo v0.0.1 ([..])")
|
|
.with_stderr_contains("[REPLACING] [..]/foo[EXE]")
|
|
.run();
|
|
installed_process("foo").with_stdout("onomatopoeia").run();
|
|
// Check install stays fresh.
|
|
cargo_process("install -Z install-upgrade --git")
|
|
.arg(git_project.url().to_string())
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains(
|
|
"[IGNORED] package `foo v0.0.1 (file://[..]/foo#[..])` is \
|
|
already installed,[..]",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn switch_sources() {
|
|
// Installing what appears to be the same thing, but from different
|
|
// sources should reinstall.
|
|
pkg("foo", "1.0.0");
|
|
Package::new("foo", "1.0.0")
|
|
.file("src/main.rs", r#"fn main() { println!("alt"); }"#)
|
|
.alternative(true)
|
|
.publish();
|
|
let p = project()
|
|
.at("foo-local") // so it doesn't use the same directory as the git project
|
|
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
|
|
.file("src/main.rs", r#"fn main() { println!("local"); }"#)
|
|
.build();
|
|
let git_project = git::new("foo", |project| {
|
|
project.file("src/main.rs", r#"fn main() { println!("git"); }"#)
|
|
})
|
|
.unwrap();
|
|
|
|
cargo_process("install -Z install-upgrade foo")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("1.0.0").run();
|
|
cargo_process("install -Z install-upgrade foo --registry alternative")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("alt").run();
|
|
p.cargo("install -Z install-upgrade --path .")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("local").run();
|
|
cargo_process("install -Z install-upgrade --git")
|
|
.arg(git_project.url().to_string())
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
installed_process("foo").with_stdout("git").run();
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_report() {
|
|
// Testing the full output that indicates installed/ignored/replaced/summary.
|
|
pkg("one", "1.0.0");
|
|
pkg("two", "1.0.0");
|
|
fn three(vers: &str) {
|
|
Package::new("three", vers)
|
|
.file("src/main.rs", "fn main() { }")
|
|
.file("src/bin/x.rs", "fn main() { }")
|
|
.file("src/bin/y.rs", "fn main() { }")
|
|
.publish();
|
|
}
|
|
three("1.0.0");
|
|
cargo_process("install -Z install-upgrade one two three")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] one v1.0.0 (registry `[..]`)
|
|
[INSTALLING] one v1.0.0
|
|
[COMPILING] one v1.0.0
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[INSTALLING] [..]/.cargo/bin/one[EXE]
|
|
[INSTALLED] package `one v1.0.0` (executable `one[EXE]`)
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] two v1.0.0 (registry `[..]`)
|
|
[INSTALLING] two v1.0.0
|
|
[COMPILING] two v1.0.0
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[INSTALLING] [..]/.cargo/bin/two[EXE]
|
|
[INSTALLED] package `two v1.0.0` (executable `two[EXE]`)
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] three v1.0.0 (registry `[..]`)
|
|
[INSTALLING] three v1.0.0
|
|
[COMPILING] three v1.0.0
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[INSTALLING] [..]/.cargo/bin/three[EXE]
|
|
[INSTALLING] [..]/.cargo/bin/x[EXE]
|
|
[INSTALLING] [..]/.cargo/bin/y[EXE]
|
|
[INSTALLED] package `three v1.0.0` (executables `three[EXE]`, `x[EXE]`, `y[EXE]`)
|
|
[SUMMARY] Successfully installed one, two, three!
|
|
[WARNING] be sure to add `[..]/.cargo/bin` to your PATH [..]
|
|
",
|
|
)
|
|
.run();
|
|
pkg("foo", "1.0.1");
|
|
pkg("bar", "1.0.1");
|
|
three("1.0.1");
|
|
cargo_process("install -Z install-upgrade one two three")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[IGNORED] package `one v1.0.0` is already installed, use --force to override
|
|
[IGNORED] package `two v1.0.0` is already installed, use --force to override
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] three v1.0.1 (registry `[..]`)
|
|
[INSTALLING] three v1.0.1
|
|
[COMPILING] three v1.0.1
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[REPLACING] [..]/.cargo/bin/three[EXE]
|
|
[REPLACING] [..]/.cargo/bin/x[EXE]
|
|
[REPLACING] [..]/.cargo/bin/y[EXE]
|
|
[REPLACED] package `three v1.0.0` with `three v1.0.1` (executables `three[EXE]`, `x[EXE]`, `y[EXE]`)
|
|
[SUMMARY] Successfully installed one, two, three!
|
|
[WARNING] be sure to add `[..]/.cargo/bin` to your PATH [..]
|
|
",
|
|
)
|
|
.run();
|
|
cargo_process("uninstall -Z install-upgrade three")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[REMOVING] [..]/.cargo/bin/three[EXE]
|
|
[REMOVING] [..]/.cargo/bin/x[EXE]
|
|
[REMOVING] [..]/.cargo/bin/y[EXE]
|
|
",
|
|
)
|
|
.run();
|
|
cargo_process("install -Z install-upgrade three --bin x")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[INSTALLING] three v1.0.1
|
|
[COMPILING] three v1.0.1
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[INSTALLING] [..]/.cargo/bin/x[EXE]
|
|
[INSTALLED] package `three v1.0.1` (executable `x[EXE]`)
|
|
[WARNING] be sure to add `[..]/.cargo/bin` to your PATH [..]
|
|
",
|
|
)
|
|
.run();
|
|
cargo_process("install -Z install-upgrade three")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[INSTALLING] three v1.0.1
|
|
[COMPILING] three v1.0.1
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
[INSTALLING] [..]/.cargo/bin/three[EXE]
|
|
[INSTALLING] [..]/.cargo/bin/y[EXE]
|
|
[REPLACING] [..]/.cargo/bin/x[EXE]
|
|
[INSTALLED] package `three v1.0.1` (executables `three[EXE]`, `y[EXE]`)
|
|
[REPLACED] package `three v1.0.1` with `three v1.0.1` (executable `x[EXE]`)
|
|
[WARNING] be sure to add `[..]/.cargo/bin` to your PATH [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn no_track_gated() {
|
|
cargo_process("install --no-track foo")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"[ERROR] `--no-track` flag is unstable, pass `-Z install-upgrade` to enable it",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[test]
|
|
fn no_track() {
|
|
pkg("foo", "1.0.0");
|
|
cargo_process("install --no-track foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
assert!(!v1_path().exists());
|
|
assert!(!v2_path().exists());
|
|
cargo_process("install --no-track foo -Z install-upgrade")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `[..]` index
|
|
[ERROR] binary `foo[EXE]` already exists in destination
|
|
Add --force to overwrite
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|