use rtb_vcs::{Release, ReleaseAsset};
use crate::error::UpdateError;
pub const DEFAULT_PATTERN: &str = "{name}-{version}-{target}{ext}";
#[must_use]
#[allow(clippy::literal_string_with_formatting_args)]
pub fn render_pattern(pattern: &str, name: &str, version: &str) -> String {
let (os, arch, target, ext) = host_substitutions();
let version_no_v = version.strip_prefix('v').unwrap_or(version);
pattern
.replace("{name}", name)
.replace("{version}", version_no_v)
.replace("{target}", target)
.replace("{os}", os)
.replace("{arch}", arch)
.replace("{ext}", ext)
}
#[must_use]
pub const fn host_substitutions() -> (&'static str, &'static str, &'static str, &'static str) {
let os = std::env::consts::OS;
let arch = std::env::consts::ARCH;
let target = match (os.as_bytes(), arch.as_bytes()) {
(b"linux", b"x86_64") => "x86_64-unknown-linux-gnu",
(b"linux", b"aarch64") => "aarch64-unknown-linux-gnu",
(b"macos", b"x86_64") => "x86_64-apple-darwin",
(b"macos", b"aarch64") => "aarch64-apple-darwin",
(b"windows", b"x86_64") => "x86_64-pc-windows-msvc",
(b"windows", b"aarch64") => "aarch64-pc-windows-msvc",
_ => "",
};
let ext = match os.as_bytes() {
b"windows" => ".zip",
_ => ".tar.gz",
};
(os, arch, target, ext)
}
pub fn pick_asset<'a>(
release: &'a Release,
expected: &str,
) -> crate::error::Result<&'a ReleaseAsset> {
if let Some(exact) = release.assets.iter().find(|a| a.name == expected) {
return Ok(exact);
}
let expected_lower = expected.to_ascii_lowercase();
if let Some(fuzzy) = release.assets.iter().find(|a| {
let name = a.name.to_ascii_lowercase();
name.starts_with(&expected_lower[..prefix_len(&expected_lower)])
}) {
return Ok(fuzzy);
}
Err(UpdateError::NoMatchingAsset { target: expected.to_string() })
}
fn prefix_len(name: &str) -> usize {
for sep in [".tar.gz", ".zip", ".tgz"] {
if let Some(idx) = name.find(sep) {
return idx;
}
}
name.len()
}
#[must_use]
pub fn pick_signature<'a>(release: &'a Release, asset: &ReleaseAsset) -> Option<&'a ReleaseAsset> {
let minisig_name = format!("{}.minisig", asset.name);
if let Some(a) = release.assets.iter().find(|a| a.name == minisig_name) {
return Some(a);
}
let sig_name = format!("{}.sig", asset.name);
release.assets.iter().find(|a| a.name == sig_name)
}