mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-19 20:18:43 +00:00
Optimize bins::BinFile
(#422)
* Extract `infer_bin_dir_template` and call it once in `collect_bin_files` * Ensure `product.name.is_some()` is true * Avoid cloning `str` in `BinFile::from_product` * Optimize: Take reference in `bins::Data` * Optimize: Construct `CompactString` only when needed Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
3da5cb9d9c
commit
2cc12f9b69
3 changed files with 81 additions and 64 deletions
|
@ -28,6 +28,40 @@ fn is_valid_path(path: &Path) -> bool {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Must be called after the archive is downloaded and extracted.
|
||||||
|
/// This function might uses blocking I/O.
|
||||||
|
pub fn infer_bin_dir_template(data: &Data) -> Cow<'static, str> {
|
||||||
|
let name = &data.name;
|
||||||
|
let target = &data.target;
|
||||||
|
let version = &data.version;
|
||||||
|
|
||||||
|
// Make sure to update
|
||||||
|
// fetchers::gh_crate_meta::hosting::{FULL_FILENAMES,
|
||||||
|
// NOVERSION_FILENAMES} if you update this array.
|
||||||
|
let possible_dirs = [
|
||||||
|
format!("{name}-{target}-v{version}"),
|
||||||
|
format!("{name}-{target}-{version}"),
|
||||||
|
format!("{name}-{version}-{target}"),
|
||||||
|
format!("{name}-v{version}-{target}"),
|
||||||
|
format!("{name}-{target}"),
|
||||||
|
name.to_string(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let default_bin_dir_template = Cow::Borrowed("{ bin }{ binary_ext }");
|
||||||
|
|
||||||
|
possible_dirs
|
||||||
|
.into_iter()
|
||||||
|
.find(|dirname| Path::new(dirname).is_dir())
|
||||||
|
.map(|mut dir| {
|
||||||
|
dir.reserve_exact(1 + default_bin_dir_template.len());
|
||||||
|
dir += "/";
|
||||||
|
dir += &default_bin_dir_template;
|
||||||
|
Cow::Owned(dir)
|
||||||
|
})
|
||||||
|
// Fallback to no dir
|
||||||
|
.unwrap_or(default_bin_dir_template)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BinFile {
|
pub struct BinFile {
|
||||||
pub base_name: CompactString,
|
pub base_name: CompactString,
|
||||||
pub source: PathBuf,
|
pub source: PathBuf,
|
||||||
|
@ -36,10 +70,12 @@ pub struct BinFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinFile {
|
impl BinFile {
|
||||||
/// Must be called after the archive is downloaded and extracted.
|
pub fn from_product(
|
||||||
/// This function might uses blocking I/O.
|
data: &Data<'_>,
|
||||||
pub fn from_product(data: &Data, product: &Product) -> Result<Self, BinstallError> {
|
product: &Product,
|
||||||
let base_name = CompactString::from(product.name.clone().unwrap());
|
bin_dir: &str,
|
||||||
|
) -> Result<Self, BinstallError> {
|
||||||
|
let base_name = product.name.as_deref().unwrap();
|
||||||
|
|
||||||
let binary_ext = if data.target.contains("windows") {
|
let binary_ext = if data.target.contains("windows") {
|
||||||
".exe"
|
".exe"
|
||||||
|
@ -48,63 +84,34 @@ impl BinFile {
|
||||||
};
|
};
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
name: &data.name,
|
name: data.name,
|
||||||
repo: data.repo.as_ref().map(|s| &s[..]),
|
repo: data.repo,
|
||||||
target: &data.target,
|
target: data.target,
|
||||||
version: &data.version,
|
version: data.version,
|
||||||
bin: &base_name,
|
bin: base_name,
|
||||||
format: binary_ext,
|
format: binary_ext,
|
||||||
binary_ext,
|
binary_ext,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate install paths
|
// Generate install paths
|
||||||
// Source path is the download dir + the generated binary path
|
// Source path is the download dir + the generated binary path
|
||||||
let source_file_path = if let Some(bin_dir) = &data.meta.bin_dir {
|
let path = ctx.render(bin_dir)?;
|
||||||
let path = ctx.render(bin_dir)?;
|
|
||||||
let path_normalized = Path::new(&path).normalize();
|
|
||||||
|
|
||||||
if path_normalized.components().next().is_none() {
|
let path_normalized = Path::new(&path).normalize();
|
||||||
return Err(BinstallError::EmptySourceFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !is_valid_path(&path_normalized) {
|
if path_normalized.components().next().is_none() {
|
||||||
return Err(BinstallError::InvalidSourceFilePath {
|
return Err(BinstallError::EmptySourceFilePath);
|
||||||
path: path_normalized.into_owned(),
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
match path_normalized {
|
if !is_valid_path(&path_normalized) {
|
||||||
Cow::Borrowed(..) => path,
|
return Err(BinstallError::InvalidSourceFilePath {
|
||||||
Cow::Owned(path) => path.to_string_lossy().into_owned(),
|
path: path_normalized.into_owned(),
|
||||||
}
|
});
|
||||||
} else {
|
}
|
||||||
let name = ctx.name;
|
|
||||||
let target = ctx.target;
|
|
||||||
let version = ctx.version;
|
|
||||||
let bin = ctx.bin;
|
|
||||||
|
|
||||||
// Make sure to update
|
let source_file_path = match path_normalized {
|
||||||
// fetchers::gh_crate_meta::hosting::{FULL_FILENAMES,
|
Cow::Borrowed(..) => path,
|
||||||
// NOVERSION_FILENAMES} if you update this array.
|
Cow::Owned(path) => path.to_string_lossy().into_owned(),
|
||||||
let possible_dirs = [
|
|
||||||
format!("{name}-{target}-v{version}"),
|
|
||||||
format!("{name}-{target}-{version}"),
|
|
||||||
format!("{name}-{version}-{target}"),
|
|
||||||
format!("{name}-v{version}-{target}"),
|
|
||||||
format!("{name}-{target}"),
|
|
||||||
name.to_string(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let dir = possible_dirs
|
|
||||||
.into_iter()
|
|
||||||
.find(|dirname| Path::new(dirname).is_dir())
|
|
||||||
.map(Cow::Owned)
|
|
||||||
// Fallback to no dir
|
|
||||||
.unwrap_or_else(|| Cow::Borrowed("."));
|
|
||||||
|
|
||||||
debug!("Using dir = {dir}");
|
|
||||||
|
|
||||||
format!("{dir}/{bin}{binary_ext}")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let source = if data.meta.pkg_fmt == Some(PkgFmt::Bin) {
|
let source = if data.meta.pkg_fmt == Some(PkgFmt::Bin) {
|
||||||
|
@ -123,7 +130,7 @@ impl BinFile {
|
||||||
.join(&ctx.render("{ bin }{ binary-ext }")?);
|
.join(&ctx.render("{ bin }{ binary-ext }")?);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
base_name,
|
base_name: CompactString::from(base_name),
|
||||||
source,
|
source,
|
||||||
dest,
|
dest,
|
||||||
link,
|
link,
|
||||||
|
@ -199,11 +206,11 @@ impl BinFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data required to get bin paths
|
/// Data required to get bin paths
|
||||||
pub struct Data {
|
pub struct Data<'a> {
|
||||||
pub name: String,
|
pub name: &'a str,
|
||||||
pub target: String,
|
pub target: &'a str,
|
||||||
pub version: String,
|
pub version: &'a str,
|
||||||
pub repo: Option<String>,
|
pub repo: Option<&'a str>,
|
||||||
pub meta: PkgMeta,
|
pub meta: PkgMeta,
|
||||||
pub bin_path: PathBuf,
|
pub bin_path: PathBuf,
|
||||||
pub install_path: PathBuf,
|
pub install_path: PathBuf,
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub enum RepositoryHost {
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make sure to update possible_dirs in `bins::BinFile`
|
/// Make sure to update possible_dirs in `bins::infer_bin_dir_template`
|
||||||
/// if you modified FULL_FILENAMES or NOVERSION_FILENAMES.
|
/// if you modified FULL_FILENAMES or NOVERSION_FILENAMES.
|
||||||
pub const FULL_FILENAMES: &[&str] = &[
|
pub const FULL_FILENAMES: &[&str] = &[
|
||||||
"{ name }-{ target }-v{ version }.{ archive-format }",
|
"{ name }-{ target }-v{ version }.{ archive-format }",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
collections::BTreeSet,
|
collections::BTreeSet,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
@ -168,7 +169,7 @@ async fn resolve_inner(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (meta, binaries) = (
|
let (meta, mut binaries) = (
|
||||||
package
|
package
|
||||||
.metadata
|
.metadata
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -177,6 +178,8 @@ async fn resolve_inner(
|
||||||
manifest.bin,
|
manifest.bin,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
binaries.retain(|product| product.name.is_some());
|
||||||
|
|
||||||
// Check binaries
|
// Check binaries
|
||||||
if binaries.is_empty() {
|
if binaries.is_empty() {
|
||||||
return Err(BinstallError::UnspecifiedBinaries);
|
return Err(BinstallError::UnspecifiedBinaries);
|
||||||
|
@ -342,19 +345,26 @@ fn collect_bin_files(
|
||||||
// List files to be installed
|
// List files to be installed
|
||||||
// based on those found via Cargo.toml
|
// based on those found via Cargo.toml
|
||||||
let bin_data = bins::Data {
|
let bin_data = bins::Data {
|
||||||
name: package.name.clone(),
|
name: &package.name,
|
||||||
target: fetcher.target().to_string(),
|
target: fetcher.target(),
|
||||||
version: package.version.clone(),
|
version: &package.version,
|
||||||
repo: package.repository.clone(),
|
repo: package.repository.as_deref(),
|
||||||
meta,
|
meta,
|
||||||
bin_path,
|
bin_path,
|
||||||
install_path,
|
install_path,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let bin_dir = bin_data
|
||||||
|
.meta
|
||||||
|
.bin_dir
|
||||||
|
.as_deref()
|
||||||
|
.map(Cow::Borrowed)
|
||||||
|
.unwrap_or_else(|| bins::infer_bin_dir_template(&bin_data));
|
||||||
|
|
||||||
// Create bin_files
|
// Create bin_files
|
||||||
let bin_files = binaries
|
let bin_files = binaries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| bins::BinFile::from_product(&bin_data, p))
|
.map(|p| bins::BinFile::from_product(&bin_data, p, &bin_dir))
|
||||||
.collect::<Result<Vec<_>, BinstallError>>()?;
|
.collect::<Result<Vec<_>, BinstallError>>()?;
|
||||||
|
|
||||||
let mut source_set = BTreeSet::new();
|
let mut source_set = BTreeSet::new();
|
||||||
|
|
Loading…
Add table
Reference in a new issue