mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-05-04 11:10:02 +00:00
Refactor: Extract new crate binstalk-types plus other misc refactor and optimization (#535)
* Refactor: Extract new crate binstalk-types * Optimize: Rm field `CrateInfo::other` which also removes dep serde-tuple-vec-map and serde-json from binstalk-types. This also makes `CrateInfo` easier to use, more generic and can be used over any `Serializer`, not just `serde_json::Value`. * Mark all errors in `binstalk-manifests` as non_exhaustive * Reduce size of `CvsParseError` by using `Box<str>` instead of `String` for variant `UnknownSourceType`. * Reduce size of `CratesTomlParseError` to 16 bytes on 64bit platform by boxing variants `TomlWrite` and `CvsParse` as these two fields are significantly larger than other variants. * Unify import style in mod `binstall_crates_v1` * Replace dep binstalk-manifests with binstalk-types in binstalk-downloader to reduce its transitive dependencies and enables binstalk-downloader to be built in parallel to binstak-manifests. * Replace dep binstalk-manifests with binstalk-types in binstalk to reduce transitive dependencies and enables binstalk to be built in parallel to binstalk-manifests. This is benefitial because binstalk-manifests pulls in toml_edit, which could takes up to 15s to be built on M1 (7-9s for codegen). * Add dep binstalk-manifests to crates/bin * Update dependabot and GHA release-pr Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
58326a6085
commit
d9cc3ce219
24 changed files with 372 additions and 76 deletions
112
crates/binstalk-types/src/cargo_toml_binstall.rs
Normal file
112
crates/binstalk-types/src/cargo_toml_binstall.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
//! The format of the `[package.metadata.binstall]` manifest.
|
||||
//!
|
||||
//! This manifest defines how a particular binary crate may be installed by Binstall.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod package_formats;
|
||||
#[doc(inline)]
|
||||
pub use package_formats::*;
|
||||
|
||||
/// `binstall` metadata container
|
||||
///
|
||||
/// Required to nest metadata under `package.metadata.binstall`
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Meta {
|
||||
pub binstall: Option<PkgMeta>,
|
||||
}
|
||||
|
||||
/// Metadata for binary installation use.
|
||||
///
|
||||
/// Exposed via `[package.metadata]` in `Cargo.toml`
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", default)]
|
||||
pub struct PkgMeta {
|
||||
/// URL template for package downloads
|
||||
pub pkg_url: Option<String>,
|
||||
|
||||
/// Format for package downloads
|
||||
pub pkg_fmt: Option<PkgFmt>,
|
||||
|
||||
/// Path template for binary files in packages
|
||||
pub bin_dir: Option<String>,
|
||||
|
||||
/// Public key for package verification (base64 encoded)
|
||||
pub pub_key: Option<String>,
|
||||
|
||||
/// Target specific overrides
|
||||
pub overrides: BTreeMap<String, PkgOverride>,
|
||||
}
|
||||
|
||||
impl PkgMeta {
|
||||
/// Merge configuration overrides into object
|
||||
pub fn merge(&mut self, pkg_override: &PkgOverride) {
|
||||
if let Some(o) = &pkg_override.pkg_url {
|
||||
self.pkg_url = Some(o.clone());
|
||||
}
|
||||
if let Some(o) = &pkg_override.pkg_fmt {
|
||||
self.pkg_fmt = Some(*o);
|
||||
}
|
||||
if let Some(o) = &pkg_override.bin_dir {
|
||||
self.bin_dir = Some(o.clone());
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge configuration overrides into object
|
||||
///
|
||||
/// * `pkg_overrides` - ordered in preference
|
||||
pub fn merge_overrides<'a, It>(&self, pkg_overrides: It) -> Self
|
||||
where
|
||||
It: IntoIterator<Item = &'a PkgOverride> + Clone,
|
||||
{
|
||||
Self {
|
||||
pkg_url: pkg_overrides
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find_map(|pkg_override| pkg_override.pkg_url.clone())
|
||||
.or_else(|| self.pkg_url.clone()),
|
||||
|
||||
pkg_fmt: pkg_overrides
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find_map(|pkg_override| pkg_override.pkg_fmt)
|
||||
.or(self.pkg_fmt),
|
||||
|
||||
bin_dir: pkg_overrides
|
||||
.into_iter()
|
||||
.find_map(|pkg_override| pkg_override.bin_dir.clone())
|
||||
.or_else(|| self.bin_dir.clone()),
|
||||
|
||||
pub_key: self.pub_key.clone(),
|
||||
overrides: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Target specific overrides for binary installation
|
||||
///
|
||||
/// Exposed via `[package.metadata.TARGET]` in `Cargo.toml`
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", default)]
|
||||
pub struct PkgOverride {
|
||||
/// URL template override for package downloads
|
||||
pub pkg_url: Option<String>,
|
||||
|
||||
/// Format override for package downloads
|
||||
pub pkg_fmt: Option<PkgFmt>,
|
||||
|
||||
/// Path template override for binary files in packages
|
||||
pub bin_dir: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct BinMeta {
|
||||
/// Binary name
|
||||
pub name: String,
|
||||
/// Binary template path (within package)
|
||||
pub path: String,
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum_macros::{Display, EnumIter, EnumString};
|
||||
|
||||
/// Binary format enumeration
|
||||
#[derive(
|
||||
Debug, Display, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, EnumString, EnumIter,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(ascii_case_insensitive)]
|
||||
pub enum PkgFmt {
|
||||
/// Download format is TAR (uncompressed)
|
||||
Tar,
|
||||
/// Download format is TAR + Bzip2
|
||||
Tbz2,
|
||||
/// Download format is TGZ (TAR + GZip)
|
||||
Tgz,
|
||||
/// Download format is TAR + XZ
|
||||
Txz,
|
||||
/// Download format is TAR + Zstd
|
||||
Tzstd,
|
||||
/// Download format is Zip
|
||||
Zip,
|
||||
/// Download format is raw / binary
|
||||
Bin,
|
||||
}
|
||||
|
||||
impl Default for PkgFmt {
|
||||
fn default() -> Self {
|
||||
Self::Tgz
|
||||
}
|
||||
}
|
||||
|
||||
impl PkgFmt {
|
||||
/// If self is one of the tar based formats, return Some.
|
||||
pub fn decompose(self) -> PkgFmtDecomposed {
|
||||
match self {
|
||||
PkgFmt::Tar => PkgFmtDecomposed::Tar(TarBasedFmt::Tar),
|
||||
PkgFmt::Tbz2 => PkgFmtDecomposed::Tar(TarBasedFmt::Tbz2),
|
||||
PkgFmt::Tgz => PkgFmtDecomposed::Tar(TarBasedFmt::Tgz),
|
||||
PkgFmt::Txz => PkgFmtDecomposed::Tar(TarBasedFmt::Txz),
|
||||
PkgFmt::Tzstd => PkgFmtDecomposed::Tar(TarBasedFmt::Tzstd),
|
||||
PkgFmt::Bin => PkgFmtDecomposed::Bin,
|
||||
PkgFmt::Zip => PkgFmtDecomposed::Zip,
|
||||
}
|
||||
}
|
||||
|
||||
/// List of possible file extensions for the format
|
||||
/// (with prefix `.`).
|
||||
pub fn extensions(self) -> &'static [&'static str] {
|
||||
match self {
|
||||
PkgFmt::Tar => &[".tar"],
|
||||
PkgFmt::Tbz2 => &[".tbz2", ".tar.bz2"],
|
||||
PkgFmt::Tgz => &[".tgz", ".tar.gz"],
|
||||
PkgFmt::Txz => &[".txz", ".tar.xz"],
|
||||
PkgFmt::Tzstd => &[".tzstd", ".tzst", ".tar.zst"],
|
||||
PkgFmt::Bin => &[".bin", ".exe", ""],
|
||||
PkgFmt::Zip => &[".zip"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum PkgFmtDecomposed {
|
||||
Tar(TarBasedFmt),
|
||||
Bin,
|
||||
Zip,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum TarBasedFmt {
|
||||
/// Download format is TAR (uncompressed)
|
||||
Tar,
|
||||
/// Download format is TAR + Bzip2
|
||||
Tbz2,
|
||||
/// Download format is TGZ (TAR + GZip)
|
||||
Tgz,
|
||||
/// Download format is TAR + XZ
|
||||
Txz,
|
||||
/// Download format is TAR + Zstd
|
||||
Tzstd,
|
||||
}
|
||||
|
||||
impl From<TarBasedFmt> for PkgFmt {
|
||||
fn from(fmt: TarBasedFmt) -> Self {
|
||||
match fmt {
|
||||
TarBasedFmt::Tar => PkgFmt::Tar,
|
||||
TarBasedFmt::Tbz2 => PkgFmt::Tbz2,
|
||||
TarBasedFmt::Tgz => PkgFmt::Tgz,
|
||||
TarBasedFmt::Txz => PkgFmt::Txz,
|
||||
TarBasedFmt::Tzstd => PkgFmt::Tzstd,
|
||||
}
|
||||
}
|
||||
}
|
82
crates/binstalk-types/src/crate_info.rs
Normal file
82
crates/binstalk-types/src/crate_info.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
//! Common structure for crate information for post-install manifests.
|
||||
|
||||
use std::{borrow, cmp, hash};
|
||||
|
||||
use compact_str::CompactString;
|
||||
use once_cell::sync::Lazy;
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
pub fn cratesio_url() -> &'static Url {
|
||||
static CRATESIO: Lazy<Url, fn() -> Url> =
|
||||
Lazy::new(|| Url::parse("https://github.com/rust-lang/crates.io-index").unwrap());
|
||||
|
||||
&CRATESIO
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CrateInfo {
|
||||
pub name: CompactString,
|
||||
pub version_req: CompactString,
|
||||
pub current_version: Version,
|
||||
pub source: CrateSource,
|
||||
pub target: CompactString,
|
||||
pub bins: Vec<CompactString>,
|
||||
}
|
||||
|
||||
impl borrow::Borrow<str> for CrateInfo {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CrateInfo {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
||||
impl Eq for CrateInfo {}
|
||||
|
||||
impl PartialOrd for CrateInfo {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||
self.name.partial_cmp(&other.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for CrateInfo {
|
||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||
self.name.cmp(&other.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl hash::Hash for CrateInfo {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: hash::Hasher,
|
||||
{
|
||||
self.name.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||
pub enum SourceType {
|
||||
Git,
|
||||
Path,
|
||||
Registry,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CrateSource {
|
||||
pub source_type: SourceType,
|
||||
pub url: Url,
|
||||
}
|
||||
|
||||
impl CrateSource {
|
||||
pub fn cratesio_registry() -> CrateSource {
|
||||
Self {
|
||||
source_type: SourceType::Registry,
|
||||
url: cratesio_url().clone(),
|
||||
}
|
||||
}
|
||||
}
|
2
crates/binstalk-types/src/lib.rs
Normal file
2
crates/binstalk-types/src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod cargo_toml_binstall;
|
||||
pub mod crate_info;
|
Loading…
Add table
Add a link
Reference in a new issue