diff --git a/Cargo.lock b/Cargo.lock index a67f1d50e..d1b6ba53c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,6 +447,7 @@ dependencies = [ "flate2", "gazenot", "goblin", + "homedir", "include_dir", "insta", "itertools 0.12.1", diff --git a/cargo-dist/Cargo.toml b/cargo-dist/Cargo.toml index e1c060bb1..f1f68a7fe 100644 --- a/cargo-dist/Cargo.toml +++ b/cargo-dist/Cargo.toml @@ -67,6 +67,7 @@ tokio = { version = "1.36.0", features = ["full"] } temp-dir = "0.1.13" [dev-dependencies] +homedir = "0.2.1" insta = { version = "1.38.0", features = ["filters"] } tar = "0.4.38" flate2 = "1.0.24" diff --git a/cargo-dist/tests/cli-tests.rs b/cargo-dist/tests/cli-tests.rs index 984765f1c..f3f7395bb 100644 --- a/cargo-dist/tests/cli-tests.rs +++ b/cargo-dist/tests/cli-tests.rs @@ -1,9 +1,12 @@ use std::process::{Command, Output, Stdio}; static BIN: &str = env!("CARGO_BIN_EXE_cargo-dist"); +const ENV_RUIN_ME: &str = "RUIN_MY_COMPUTER_WITH_INSTALLERS"; #[allow(dead_code)] mod gallery; +use axoasset::LocalAsset; +use camino::Utf8PathBuf; use gallery::*; fn format_outputs(output: &Output) -> String { @@ -191,3 +194,62 @@ fn test_markdown_help() { }); assert!(output.status.success(), "{}", output.status); } + +static RECEIPT_TEMPLATE: &str = r#"{"binaries":["cargo-dist"],"install_prefix":"INSTALL_PREFIX","provider":{"source":"cargo-dist","version":"0.10.0-prerelease.1"},"source":{"app_name":"cargo-dist","name":"cargo-dist","owner":"axodotdev","release_type":"github"},"version":"VERSION"}"#; + +fn install_receipt(version: &str, prefix: &Utf8PathBuf) -> String { + RECEIPT_TEMPLATE + .replace("INSTALL_PREFIX", &prefix.to_string().replace('\\', "\\\\")) + .replace("VERSION", version) +} + +fn write_receipt(version: &str, prefix: &Utf8PathBuf, config_path: &Utf8PathBuf) { + let contents = install_receipt(version, prefix); + let receipt_name = config_path.join("cargo-dist-receipt.json"); + LocalAsset::write_new(&contents, receipt_name).unwrap(); +} + +#[test] +fn test_self_update() { + // Only do this if RUIN_MY_COMPUTER_WITH_INSTALLERS is set + // Also keep it to Mac/Linux until I remember how Windows paths work + #[cfg(target_family = "unix")] + if std::env::var(ENV_RUIN_ME) + .map(|s| !s.is_empty()) + .unwrap_or(false) + { + let dist_home = Utf8PathBuf::from_path_buf( + homedir::get_my_home() + .unwrap() + .unwrap() + .join(".cargo") + .join("bin"), + ) + .unwrap(); + let dist_path = &dist_home.join("cargo-dist"); + let config_path = Utf8PathBuf::from_path_buf( + homedir::get_my_home() + .unwrap() + .unwrap() + .join(".config") + .join("cargo-dist"), + ) + .unwrap(); + + // Install to the home directory + std::fs::copy(BIN, dist_path).unwrap(); + + // Create a fake install receipt + write_receipt("0.13.0", &dist_home, &config_path); + + let output = Command::new(dist_path) + .arg("dist") + .arg("update") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .unwrap(); + + assert!(output.status.success()); + } +}