use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
};
use crate::{receipt::get_config_paths, ReleaseSourceType};
static RECEIPT_TEMPLATE: &str = r#"{"binaries":[BINARIES],"install_prefix":"INSTALL_PREFIX","provider":{"source":"cargo-dist","version":"0.10.0-prerelease.1"},"source":{"app_name":"APP_NAME","name":"PACKAGE","owner":"OWNER","release_type":"RELEASE_TYPE"},"version":"VERSION"}"#;
fn install_receipt(
app_name: &str,
package: &str,
owner: &str,
binaries: &[String],
version: &str,
prefix: &str,
release_type: &ReleaseSourceType,
) -> String {
let binaries = binaries
.iter()
.map(|name| format!(r#""{name}""#))
.collect::<Vec<String>>()
.join(", ");
RECEIPT_TEMPLATE
.replace("BINARIES", &binaries)
.replace("PACKAGE", package)
.replace("OWNER", owner)
.replace("APP_NAME", app_name)
.replace("INSTALL_PREFIX", &prefix.replace('\\', "\\\\"))
.replace("VERSION", version)
.replace("RELEASE_TYPE", &release_type.to_string())
}
#[allow(clippy::too_many_arguments)]
fn write_receipt(
app_name: &str,
package: &str,
owner: &str,
binaries: &[String],
version: &str,
prefix: &Path,
config_path: &PathBuf,
release_type: &ReleaseSourceType,
) -> std::io::Result<PathBuf> {
let contents = install_receipt(
app_name,
package,
owner,
binaries,
version,
&prefix.to_string_lossy(),
release_type,
);
let receipt_name = config_path.join(format!("{package}-receipt.json"));
std::fs::create_dir_all(config_path)?;
std::fs::write(&receipt_name, contents)?;
Ok(receipt_name)
}
pub struct RuntestArgs {
pub app_name: String,
pub package: String,
pub owner: String,
pub bin: PathBuf,
pub binaries: Vec<String>,
pub args: Vec<String>,
pub release_type: ReleaseSourceType,
}
pub fn perform_runtest(runtest_args: &RuntestArgs) -> PathBuf {
let RuntestArgs {
app_name,
package,
owner,
bin,
binaries,
args,
release_type,
} = runtest_args;
let basename = bin.file_name().unwrap();
let home = homedir::my_home().unwrap().unwrap();
let app_home = &home.join(".cargo").join("bin");
let app_path = &app_home.join(basename);
let config_path = get_config_paths(app_name)
.unwrap()
.first()
.expect("no possible legal config paths found!?")
.to_owned()
.into_std_path_buf();
if app_path.exists() {
std::fs::remove_file(app_path).unwrap();
}
assert!(!app_path.exists());
std::fs::copy(bin, app_path).unwrap();
write_receipt(
app_name,
package,
owner,
binaries.as_slice(),
"0.0.1",
app_home,
&config_path,
release_type,
)
.unwrap();
let output = Command::new(app_path)
.args(args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.unwrap();
let out_str = String::from_utf8_lossy(&output.stdout);
let err_str = String::from_utf8_lossy(&output.stderr);
assert!(
output.status.success(),
"status code: {}, stdout: {out_str}; stderr: {err_str}",
output.status
);
app_path.to_owned()
}
#[test]
fn test_receipt_generation() {
let expected = r#"{"binaries":["cargo-dist"],"install_prefix":"/tmp/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":"0.5.0"}"#;
let actual = install_receipt(
"cargo-dist",
"cargo-dist",
"axodotdev",
&["cargo-dist".to_owned()],
"0.5.0",
"/tmp/prefix",
&ReleaseSourceType::GitHub,
);
assert_eq!(expected, actual);
}
#[test]
fn test_receipt_different_app_package() {
let expected = r#"{"binaries":["axolotlsay"],"install_prefix":"/tmp/prefix","provider":{"source":"cargo-dist","version":"0.10.0-prerelease.1"},"source":{"app_name":"axolotlsay","name":"cargodisttest","owner":"mistydemeo","release_type":"github"},"version":"0.5.0"}"#;
let actual = install_receipt(
"axolotlsay",
"cargodisttest",
"mistydemeo",
&["axolotlsay".to_owned()],
"0.5.0",
"/tmp/prefix",
&ReleaseSourceType::GitHub,
);
assert_eq!(expected, actual);
}
#[test]
fn test_receipt_multiple_binaries() {
let expected = r#"{"binaries":["bin1", "bin2"],"install_prefix":"/tmp/prefix","provider":{"source":"cargo-dist","version":"0.10.0-prerelease.1"},"source":{"app_name":"axolotlsay","name":"cargodisttest","owner":"mistydemeo","release_type":"github"},"version":"0.5.0"}"#;
let actual = install_receipt(
"axolotlsay",
"cargodisttest",
"mistydemeo",
&["bin1".to_owned(), "bin2".to_owned()],
"0.5.0",
"/tmp/prefix",
&ReleaseSourceType::GitHub,
);
assert_eq!(expected, actual);
}
#[test]
fn test_receipt_different_alternate_release_type() {
let expected = r#"{"binaries":["axolotlsay"],"install_prefix":"/tmp/prefix","provider":{"source":"cargo-dist","version":"0.10.0-prerelease.1"},"source":{"app_name":"axolotlsay","name":"cargodisttest","owner":"mistydemeo","release_type":"axodotdev"},"version":"0.5.0"}"#;
let actual = install_receipt(
"axolotlsay",
"cargodisttest",
"mistydemeo",
&["axolotlsay".to_owned()],
"0.5.0",
"/tmp/prefix",
&ReleaseSourceType::Axo,
);
assert_eq!(expected, actual);
}