mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-20 20:48:43 +00:00
Improve GhCrateMeta
: Detect cases where pkg-fmt is not specified (#757)
* Fix fmt of mod `<GhCrateMeta as Fetcher>::find` * Add new variant `BinstallError::InvalidPkgFmt` * Impl new fn `PkgFmt::guess_pkg_format` * Improve `GhCrateMeta`: Detect cases where `pkg-fmt` is not specified but `pkg-url` also does not contain format, archive-format or archive-suffix which is required for automatically deducing the pkg-fmt. In these cases, we would call `PkgFmt::guess_pkg_format` to try out best to figure out the pkg-fmt, otherwise we just return an error. Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
5c02581569
commit
e510511487
3 changed files with 98 additions and 14 deletions
|
@ -57,6 +57,38 @@ impl PkgFmt {
|
|||
PkgFmt::Zip => &[".zip"],
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the pkg-url template, guess the possible pkg-fmt.
|
||||
pub fn guess_pkg_format(pkg_url: &str) -> Option<Self> {
|
||||
let mut it = pkg_url.rsplitn(3, '.');
|
||||
|
||||
let guess = match it.next()? {
|
||||
"tar" => Some(PkgFmt::Tar),
|
||||
|
||||
"tbz2" => Some(PkgFmt::Tbz2),
|
||||
"bz2" if it.next() == Some("tar") => Some(PkgFmt::Tbz2),
|
||||
|
||||
"tgz" => Some(PkgFmt::Tgz),
|
||||
"gz" if it.next() == Some("tar") => Some(PkgFmt::Tgz),
|
||||
|
||||
"txz" => Some(PkgFmt::Txz),
|
||||
"xz" if it.next() == Some("tar") => Some(PkgFmt::Txz),
|
||||
|
||||
"tzstd" | "tzst" => Some(PkgFmt::Tzstd),
|
||||
"zst" if it.next() == Some("tar") => Some(PkgFmt::Tzstd),
|
||||
|
||||
"exe" | "bin" => Some(PkgFmt::Bin),
|
||||
"zip" => Some(PkgFmt::Zip),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if it.next().is_some() {
|
||||
guess
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
|
|
|
@ -41,6 +41,16 @@ pub struct CrateContextError {
|
|||
err: BinstallError,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("Invalid pkg-url {pkg_url} for {crate_name}@{version} on {target}: {reason}")]
|
||||
pub struct InvalidPkgFmtError {
|
||||
pub crate_name: CompactString,
|
||||
pub version: CompactString,
|
||||
pub target: String,
|
||||
pub pkg_url: String,
|
||||
pub reason: &'static str,
|
||||
}
|
||||
|
||||
/// Error kinds emitted by cargo-binstall.
|
||||
#[derive(Error, Diagnostic, Debug)]
|
||||
#[non_exhaustive]
|
||||
|
@ -291,6 +301,14 @@ pub enum BinstallError {
|
|||
#[diagnostic(severity(error), code(binstall::no_fallback_to_cargo_install))]
|
||||
NoFallbackToCargoInstall,
|
||||
|
||||
/// Fallback to `cargo-install` is disabled.
|
||||
///
|
||||
/// - Code: `binstall::invalid_pkg_fmt`
|
||||
/// - Exit: 95
|
||||
#[error(transparent)]
|
||||
#[diagnostic(severity(error), code(binstall::invalid_pkg_fmt))]
|
||||
InvalidPkgFmt(Box<InvalidPkgFmtError>),
|
||||
|
||||
/// A wrapped error providing the context of which crate the error is about.
|
||||
#[error(transparent)]
|
||||
#[diagnostic(transparent)]
|
||||
|
@ -324,6 +342,7 @@ impl BinstallError {
|
|||
InvalidSourceFilePath { .. } => 91,
|
||||
EmptySourceFilePath => 92,
|
||||
NoFallbackToCargoInstall => 94,
|
||||
InvalidPkgFmt(..) => 95,
|
||||
CrateContext(context) => context.err.exit_number(),
|
||||
};
|
||||
|
||||
|
@ -428,3 +447,9 @@ impl From<CargoTomlError> for BinstallError {
|
|||
BinstallError::CargoManifest(Box::new(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidPkgFmtError> for BinstallError {
|
||||
fn from(e: InvalidPkgFmtError) -> Self {
|
||||
BinstallError::InvalidPkgFmt(Box::new(e))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use tracing::{debug, warn};
|
|||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
errors::BinstallError,
|
||||
errors::{BinstallError, InvalidPkgFmtError},
|
||||
helpers::{
|
||||
download::Download,
|
||||
remote::{Client, Method},
|
||||
|
@ -99,7 +99,34 @@ impl super::Fetcher for GhCrateMeta {
|
|||
None
|
||||
};
|
||||
|
||||
let mut pkg_fmt = self.target_data.meta.pkg_fmt;
|
||||
|
||||
let pkg_urls = if let Some(pkg_url) = self.target_data.meta.pkg_url.as_deref() {
|
||||
if pkg_fmt.is_none()
|
||||
&& !(pkg_url.contains("format")
|
||||
|| pkg_url.contains("archive-format")
|
||||
|| pkg_url.contains("archive-suffix"))
|
||||
{
|
||||
// The crate does not specify the pkg-fmt, yet its pkg-url
|
||||
// template doesn't contains format, archive-format or
|
||||
// archive-suffix which is required for automatically
|
||||
// deducing the pkg-fmt.
|
||||
//
|
||||
// We will attempt to guess the pkg-fmt there, but this is
|
||||
// just a best-effort
|
||||
pkg_fmt = PkgFmt::guess_pkg_format(pkg_url);
|
||||
|
||||
if pkg_fmt.is_none() {
|
||||
return Err(InvalidPkgFmtError {
|
||||
crate_name: self.data.name.clone(),
|
||||
version: self.data.version.clone(),
|
||||
target: self.target_data.target.clone(),
|
||||
pkg_url: pkg_url.to_string(),
|
||||
reason: "pkg-fmt is not specified, yet pkg-url does not contain format, archive-format or archive-suffix which is required for automatically deducing pkg-fmt",
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
Either::Left(iter::once(Cow::Borrowed(pkg_url)))
|
||||
} else if let Some(repo) = repo.as_ref() {
|
||||
if let Some(pkg_urls) =
|
||||
|
@ -137,7 +164,7 @@ impl super::Fetcher for GhCrateMeta {
|
|||
// launch_baseline_find_tasks which moves `this`
|
||||
let this = &self;
|
||||
|
||||
let pkg_fmts = if let Some(pkg_fmt) = self.target_data.meta.pkg_fmt {
|
||||
let pkg_fmts = if let Some(pkg_fmt) = pkg_fmt {
|
||||
Either::Left(iter::once(pkg_fmt))
|
||||
} else {
|
||||
Either::Right(PkgFmt::iter())
|
||||
|
|
Loading…
Add table
Reference in a new issue