mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-20 04:28:43 +00:00

* Refactor: Extract `GhCrateMeta::find_baseline` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Update `Cargo.lock`: Update dep `compact_str` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Fix use of `fetchers`: Set `meta.pkg_fmt` using `fetcher.pkg_fmt()` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Derive `strum_macors::{Display, EnumIter}` for `PkgFmt` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Set typeof field `PkgMeta::pkg_fmt` to be `Option<PkgFmt>` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Optimize `Fetcher::new` to take `&Arc<Data>` instead of `&Data` To avoid unnecessary `Data::clone` call in `GhCrateMeta` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Optimize `GhCrateMeta::find_baseline`: Avoid unnecessary spawning for `let Err(_) = url` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Optimize spawning in `GhCrateMeta::find_baseline` Ret `Option<Url>` instead of `(Url, bool)` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Add new method `target_meta` to trait `Fetcher` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Simplify `resolve_inner` using `Fetcher::target_meta` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Optimize loop in `resolve_inner`: Avoid cloning `PkgOverride` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Impl `PkgMeta::clone_without_overrides` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Optimize `resolve_inner` loop: Use `PkgMeta::clone_without_overrides` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Refactor: Simplify `Context::from_data` impl Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Refactor: Extract `launch_baseline_find_tasks` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Refactor: Simplify `<GhCrateMeta as Fetcher>::find` Instead of launching tasks in an opaque manner in `Self::find_baseline`, the new design returns an iterator which launches the tasks and thus have a unified `.await` point for all these tasks. Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Add `warn!`ing to report failure of `Context::render_url` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
162 lines
4.2 KiB
Rust
162 lines
4.2 KiB
Rust
use std::path::{Path, PathBuf};
|
|
|
|
use cargo_toml::Product;
|
|
use compact_str::CompactString;
|
|
use log::debug;
|
|
use serde::Serialize;
|
|
use tinytemplate::TinyTemplate;
|
|
|
|
use crate::{
|
|
errors::BinstallError,
|
|
fs::{atomic_install, atomic_symlink_file},
|
|
manifests::cargo_toml_binstall::{PkgFmt, PkgMeta},
|
|
};
|
|
|
|
pub struct BinFile {
|
|
pub base_name: CompactString,
|
|
pub source: PathBuf,
|
|
pub dest: PathBuf,
|
|
pub link: PathBuf,
|
|
}
|
|
|
|
impl BinFile {
|
|
pub fn from_product(data: &Data, product: &Product) -> Result<Self, BinstallError> {
|
|
let base_name = CompactString::from(product.name.clone().unwrap());
|
|
|
|
let binary_ext = if data.target.contains("windows") {
|
|
".exe"
|
|
} else {
|
|
""
|
|
};
|
|
|
|
let ctx = Context {
|
|
name: &data.name,
|
|
repo: data.repo.as_ref().map(|s| &s[..]),
|
|
target: &data.target,
|
|
version: &data.version,
|
|
bin: &base_name,
|
|
format: binary_ext,
|
|
binary_ext,
|
|
};
|
|
|
|
// Generate install paths
|
|
// Source path is the download dir + the generated binary path
|
|
let source_file_path = ctx.render(&data.meta.bin_dir)?;
|
|
let source = if data.meta.pkg_fmt == Some(PkgFmt::Bin) {
|
|
data.bin_path.clone()
|
|
} else {
|
|
data.bin_path.join(&source_file_path)
|
|
};
|
|
|
|
// Destination path is the install dir + base-name-version{.extension}
|
|
let dest_file_path = ctx.render("{ bin }-v{ version }{ binary-ext }")?;
|
|
let dest = data.install_path.join(dest_file_path);
|
|
|
|
// Link at install dir + base-name{.extension}
|
|
let link = data
|
|
.install_path
|
|
.join(&ctx.render("{ bin }{ binary-ext }")?);
|
|
|
|
Ok(Self {
|
|
base_name,
|
|
source,
|
|
dest,
|
|
link,
|
|
})
|
|
}
|
|
|
|
pub fn preview_bin(&self) -> String {
|
|
format!(
|
|
"{} ({} -> {})",
|
|
self.base_name,
|
|
self.source.file_name().unwrap().to_string_lossy(),
|
|
self.dest.display()
|
|
)
|
|
}
|
|
|
|
pub fn preview_link(&self) -> String {
|
|
format!(
|
|
"{} ({} -> {})",
|
|
self.base_name,
|
|
self.link.display(),
|
|
self.link_dest().display()
|
|
)
|
|
}
|
|
|
|
pub fn install_bin(&self) -> Result<(), BinstallError> {
|
|
if !self.source.try_exists()? {
|
|
return Err(BinstallError::BinFileNotFound(self.source.clone()));
|
|
}
|
|
|
|
debug!(
|
|
"Atomically install file from '{}' to '{}'",
|
|
self.source.display(),
|
|
self.dest.display()
|
|
);
|
|
atomic_install(&self.source, &self.dest)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn install_link(&self) -> Result<(), BinstallError> {
|
|
// Remove existing symlink
|
|
// TODO: check if existing symlink is correct
|
|
if self.link.exists() {
|
|
debug!("Remove link '{}'", self.link.display());
|
|
std::fs::remove_file(&self.link)?;
|
|
}
|
|
|
|
let dest = self.link_dest();
|
|
debug!(
|
|
"Create link '{}' pointing to '{}'",
|
|
self.link.display(),
|
|
dest.display()
|
|
);
|
|
atomic_symlink_file(dest, &self.link)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn link_dest(&self) -> &Path {
|
|
if cfg!(target_family = "unix") {
|
|
Path::new(self.dest.file_name().unwrap())
|
|
} else {
|
|
&self.dest
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Data required to get bin paths
|
|
pub struct Data {
|
|
pub name: String,
|
|
pub target: String,
|
|
pub version: String,
|
|
pub repo: Option<String>,
|
|
pub meta: PkgMeta,
|
|
pub bin_path: PathBuf,
|
|
pub install_path: PathBuf,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
struct Context<'c> {
|
|
pub name: &'c str,
|
|
pub repo: Option<&'c str>,
|
|
pub target: &'c str,
|
|
pub version: &'c str,
|
|
pub bin: &'c str,
|
|
|
|
/// Soft-deprecated alias for binary-ext
|
|
pub format: &'c str,
|
|
|
|
/// Filename extension on the binary, i.e. .exe on Windows, nothing otherwise
|
|
#[serde(rename = "binary-ext")]
|
|
pub binary_ext: &'c str,
|
|
}
|
|
|
|
impl<'c> Context<'c> {
|
|
fn render(&self, template: &str) -> Result<String, BinstallError> {
|
|
let mut tt = TinyTemplate::new();
|
|
tt.add_template("path", template)?;
|
|
Ok(tt.render("path", self)?)
|
|
}
|
|
}
|