diff --git a/crates/bin/src/args.rs b/crates/bin/src/args.rs index e81f1970..4f7cf65a 100644 --- a/crates/bin/src/args.rs +++ b/crates/bin/src/args.rs @@ -13,12 +13,12 @@ use binstalk::{ ops::resolve::{CrateName, VersionReqExt}, registry::Registry, }; -use clap::{error::ErrorKind, CommandFactory, Parser, ValueEnum}; +use binstalk_manifests::cargo_toml_binstall::Strategy; +use clap::{builder::PossibleValue, error::ErrorKind, CommandFactory, Parser, ValueEnum}; use compact_str::CompactString; use log::LevelFilter; use semver::VersionReq; use strum::EnumCount; -use strum_macros::EnumCount; use zeroize::Zeroizing; #[derive(Debug, Parser)] @@ -162,13 +162,13 @@ pub struct Args { value_delimiter(','), env = "BINSTALL_STRATEGIES" )] - pub(crate) strategies: Vec<Strategy>, + pub(crate) strategies: Vec<StrategyWrapped>, /// Disable the strategies specified. /// If a strategy is specified in `--strategies` and `--disable-strategies`, /// then it will be removed. #[clap(help_heading = "Overrides", long, value_delimiter(','))] - pub(crate) disable_strategies: Vec<Strategy>, + pub(crate) disable_strategies: Vec<StrategyWrapped>, /// If `--github-token` or environment variable `GITHUB_TOKEN`/`GH_TOKEN` /// is not specified, then cargo-binstall will try to extract github token from @@ -431,16 +431,20 @@ impl Default for RateLimit { } /// Strategy for installing the package -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, ValueEnum, EnumCount)] -#[repr(u8)] -pub(crate) enum Strategy { - /// Attempt to download official pre-built artifacts using - /// information provided in `Cargo.toml`. - CrateMetaData, - /// Query third-party QuickInstall for the crates. - QuickInstall, - /// Build the crates from source using `cargo-build`. - Compile, +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub(crate) struct StrategyWrapped(pub(crate) Strategy); + +impl ValueEnum for StrategyWrapped { + fn value_variants<'a>() -> &'a [Self] { + &[ + Self(Strategy::CrateMetaData), + Self(Strategy::QuickInstall), + Self(Strategy::Compile), + ] + } + fn to_possible_value(&self) -> Option<PossibleValue> { + Some(PossibleValue::new(self.0.to_str())) + } } pub fn parse() -> Args { @@ -532,7 +536,7 @@ You cannot use --{option} and specify multiple packages at the same time. Do one let mut is_variant_present = [false; Strategy::COUNT]; for strategy in &opts.strategies { - let index = *strategy as u8 as usize; + let index = strategy.0 as u8 as usize; if is_variant_present[index] { new_dup_strategy_err().exit() } else { @@ -543,9 +547,9 @@ You cannot use --{option} and specify multiple packages at the same time. Do one // Default strategies if empty if opts.strategies.is_empty() { opts.strategies = vec![ - Strategy::CrateMetaData, - Strategy::QuickInstall, - Strategy::Compile, + StrategyWrapped(Strategy::CrateMetaData), + StrategyWrapped(Strategy::QuickInstall), + StrategyWrapped(Strategy::Compile), ]; } @@ -573,7 +577,8 @@ You cannot use --{option} and specify multiple packages at the same time. Do one } // Ensure that Strategy::Compile is specified as the last strategy - if opts.strategies[..(opts.strategies.len() - 1)].contains(&Strategy::Compile) { + if opts.strategies[..(opts.strategies.len() - 1)].contains(&StrategyWrapped(Strategy::Compile)) + { command .error( ErrorKind::InvalidValue, diff --git a/crates/bin/src/entry.rs b/crates/bin/src/entry.rs index 48288aa2..3ae83141 100644 --- a/crates/bin/src/entry.rs +++ b/crates/bin/src/entry.rs @@ -21,7 +21,9 @@ use binstalk::{ }, }; use binstalk_manifests::{ - cargo_config::Config, cargo_toml_binstall::PkgOverride, crates_manifests::Manifests, + cargo_config::Config, + cargo_toml_binstall::{PkgOverride, Strategy}, + crates_manifests::Manifests, }; use file_format::FileFormat; use home::cargo_home; @@ -30,11 +32,7 @@ use miette::{miette, Report, Result, WrapErr}; use tokio::task::block_in_place; use tracing::{debug, error, info, warn}; -use crate::{ - args::{Args, Strategy}, - gh_token, git_credentials, install_path, - ui::confirm, -}; +use crate::{args::Args, gh_token, git_credentials, install_path, ui::confirm}; pub fn install_crates( args: Args, @@ -46,7 +44,7 @@ pub fn install_crates( let resolvers: Vec<_> = args .strategies .into_iter() - .filter_map(|strategy| match strategy { + .filter_map(|strategy| match strategy.0 { Strategy::CrateMetaData => Some(GhCrateMeta::new as Resolver), Strategy::QuickInstall => Some(QuickInstall::new as Resolver), Strategy::Compile => { diff --git a/crates/binstalk-types/src/cargo_toml_binstall.rs b/crates/binstalk-types/src/cargo_toml_binstall.rs index 2c9af131..02c504f7 100644 --- a/crates/binstalk-types/src/cargo_toml_binstall.rs +++ b/crates/binstalk-types/src/cargo_toml_binstall.rs @@ -5,6 +5,7 @@ use std::{borrow::Cow, collections::BTreeMap}; use serde::{Deserialize, Serialize}; +use strum_macros::{EnumCount, VariantArray}; mod package_formats; #[doc(inline)] @@ -19,6 +20,41 @@ pub struct Meta { pub binstall: Option<PkgMeta>, } +/// Strategies to use for binary discovery +#[derive( + Debug, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + EnumCount, + VariantArray, + Deserialize, + Serialize, +)] +#[serde(rename_all = "kebab-case")] +pub enum Strategy { + /// Attempt to download official pre-built artifacts using + /// information provided in `Cargo.toml`. + CrateMetaData, + /// Query third-party QuickInstall for the crates. + QuickInstall, + /// Build the crates from source using `cargo-build`. + Compile, +} + +impl Strategy { + pub const fn to_str(self) -> &'static str { + match self { + Strategy::CrateMetaData => "crate-meta-data", + Strategy::QuickInstall => "quick-install", + Strategy::Compile => "compile", + } + } +} + /// Metadata for binary installation use. /// /// Exposed via `[package.metadata]` in `Cargo.toml`