mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-20 20:48:43 +00:00
Enforce strict strategies parsing rule: Reject duplicate strategy in --strategies
(#545)
`cargo-binstall` should reject duplicate strategy in `--strategies` as it is illegal input and it cannot be interpreted reasonably. * Reject duplicate strategy in `--strategies` * Optimize `compute_resolvers`: Use `Vec::retain` instead of `Iterator::filter` plus collecting into `Vec`. * Optimize `compute_resolvers`: Reject `strategies.len() > Strategy::COUNT` * Improve err msg for cases where user disabled all strategies * Simplify `BinstallError::InvalidStrategies`: Takes `&'static str` instead of `&'static &'static str` since other variants are larger than 8B. Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
bdb4b2070d
commit
83b2de3ea2
3 changed files with 31 additions and 25 deletions
|
@ -298,6 +298,7 @@ impl Default for RateLimit {
|
||||||
|
|
||||||
/// Strategy for installing the package
|
/// Strategy for installing the package
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, ValueEnum, EnumCount)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, ValueEnum, EnumCount)]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum Strategy {
|
pub enum Strategy {
|
||||||
/// Attempt to download official pre-built artifacts using
|
/// Attempt to download official pre-built artifacts using
|
||||||
/// information provided in `Cargo.toml`.
|
/// information provided in `Cargo.toml`.
|
||||||
|
|
|
@ -185,22 +185,27 @@ pub async fn install_crates(args: Args, jobserver_client: LazyJobserverClient) -
|
||||||
|
|
||||||
/// Return (resolvers, cargo_install_fallback)
|
/// Return (resolvers, cargo_install_fallback)
|
||||||
fn compute_resolvers(
|
fn compute_resolvers(
|
||||||
input_strategies: Vec<Strategy>,
|
mut strategies: Vec<Strategy>,
|
||||||
mut disable_strategies: Vec<Strategy>,
|
mut disable_strategies: Vec<Strategy>,
|
||||||
) -> Result<(Vec<Resolver>, bool), BinstallError> {
|
) -> Result<(Vec<Resolver>, bool), BinstallError> {
|
||||||
// Compute strategies
|
let dup_strategy_err =
|
||||||
let mut strategies = vec![];
|
BinstallError::InvalidStrategies("--strategies should not contain duplicate strategy");
|
||||||
|
|
||||||
// Remove duplicate strategies
|
if strategies.len() > Strategy::COUNT {
|
||||||
for strategy in input_strategies {
|
// If len of strategies is larger than number of variants of Strategy,
|
||||||
if strategies.len() == Strategy::COUNT {
|
// then there must be duplicates by pigeon hole principle.
|
||||||
// All variants of Strategy is present in strategies,
|
return Err(dup_strategy_err);
|
||||||
// there is no need to continue since all the remaining
|
|
||||||
// args.strategies must be present in stratetgies.
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if !strategies.contains(&strategy) {
|
|
||||||
strategies.push(strategy);
|
// Whether specific variant of Strategy is present
|
||||||
|
let mut is_variant_present = [false; Strategy::COUNT];
|
||||||
|
|
||||||
|
for strategy in &strategies {
|
||||||
|
let index = *strategy as u8 as usize;
|
||||||
|
if is_variant_present[index] {
|
||||||
|
return Err(dup_strategy_err);
|
||||||
|
} else {
|
||||||
|
is_variant_present[index] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,22 +218,22 @@ fn compute_resolvers(
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut strategies: Vec<Strategy> = if !disable_strategies.is_empty() {
|
// Filter out all disabled strategies
|
||||||
|
if !disable_strategies.is_empty() {
|
||||||
// Since order doesn't matter, we can sort it and remove all duplicates
|
// Since order doesn't matter, we can sort it and remove all duplicates
|
||||||
// to speedup checking.
|
// to speedup checking.
|
||||||
disable_strategies.sort_unstable();
|
disable_strategies.sort_unstable();
|
||||||
disable_strategies.dedup();
|
disable_strategies.dedup();
|
||||||
|
|
||||||
strategies
|
// disable_strategies.len() <= Strategy::COUNT, of which is faster
|
||||||
.into_iter()
|
// to just use [T]::contains rather than [T]::binary_search
|
||||||
.filter(|strategy| !disable_strategies.contains(strategy))
|
strategies.retain(|strategy| !disable_strategies.contains(strategy));
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
strategies
|
|
||||||
};
|
|
||||||
|
|
||||||
if strategies.is_empty() {
|
if strategies.is_empty() {
|
||||||
return Err(BinstallError::InvalidStrategies(&"No strategy is provided"));
|
return Err(BinstallError::InvalidStrategies(
|
||||||
|
"You have disabled all strategies",
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cargo_install_fallback = *strategies.last().unwrap() == Strategy::Compile;
|
let cargo_install_fallback = *strategies.last().unwrap() == Strategy::Compile;
|
||||||
|
@ -243,7 +248,7 @@ fn compute_resolvers(
|
||||||
Strategy::CrateMetaData => Ok(GhCrateMeta::new as Resolver),
|
Strategy::CrateMetaData => Ok(GhCrateMeta::new as Resolver),
|
||||||
Strategy::QuickInstall => Ok(QuickInstall::new as Resolver),
|
Strategy::QuickInstall => Ok(QuickInstall::new as Resolver),
|
||||||
Strategy::Compile => Err(BinstallError::InvalidStrategies(
|
Strategy::Compile => Err(BinstallError::InvalidStrategies(
|
||||||
&"Compile strategy must be the last one",
|
"Compile strategy must be the last one",
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, BinstallError>>()?;
|
.collect::<Result<Vec<_>, BinstallError>>()?;
|
||||||
|
|
|
@ -291,7 +291,7 @@ pub enum BinstallError {
|
||||||
/// - Exit: 93
|
/// - Exit: 93
|
||||||
#[error("Invalid strategies configured: {0}")]
|
#[error("Invalid strategies configured: {0}")]
|
||||||
#[diagnostic(severity(error), code(binstall::strategies))]
|
#[diagnostic(severity(error), code(binstall::strategies))]
|
||||||
InvalidStrategies(&'static &'static str),
|
InvalidStrategies(&'static str),
|
||||||
|
|
||||||
/// Fallback to `cargo-install` is disabled.
|
/// Fallback to `cargo-install` is disabled.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Add table
Reference in a new issue