Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow banning multiple versions of a specific crate #365

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/bans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ pub fn check(
let ValidConfig {
file_id,
denied,
denied_multiple_versions,
allowed,
skipped,
multiple_versions,
Expand Down Expand Up @@ -313,8 +314,13 @@ pub fn check(
}
} else if !tree_skipper.matches(krate, &mut pack) {
if multi_detector.name != krate.name {
if multi_detector.dupes.len() > 1 && multiple_versions != LintLevel::Allow {
let severity = match multiple_versions {
let lint_level = match matches(&denied_multiple_versions, krate) {
Some(_) => LintLevel::Deny,
None => multiple_versions,
};

if multi_detector.dupes.len() > 1 && lint_level != LintLevel::Allow {
let severity = match lint_level {
LintLevel::Warn => Severity::Warning,
LintLevel::Deny => Severity::Error,
LintLevel::Allow => unreachable!(),
Expand Down
58 changes: 53 additions & 5 deletions src/bans/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ pub struct CrateId {

#[derive(Deserialize, Clone)]
#[cfg_attr(test, derive(Debug, PartialEq))]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct CrateBan {
pub name: Spanned<String>,
#[serde(default = "any")]
pub version: VersionReq,
/// One or more crates that will allow this crate to be used if it is a
/// direct dependency
#[serde(default)]
pub wrappers: Vec<Spanned<String>>,
pub wrappers: Option<Spanned<Vec<Spanned<String>>>>,
/// Setting this to true will only emit an error if multiple
// versions of the crate are found
#[serde(default)]
pub multiple_versions: Option<Spanned<bool>>,
}

#[derive(Deserialize, Clone)]
Expand Down Expand Up @@ -128,8 +132,15 @@ impl crate::cfg::UnvalidatedConfig for Config {
)
};

let denied: Vec<_> = self
.deny
let (deny_multiple_versions, deny): (Vec<_>, Vec<_>) =
self.deny.into_iter().partition(|kb| {
kb.multiple_versions
.as_ref()
.map(|spanned| spanned.value)
.unwrap_or(false)
});

let denied: Vec<_> = deny
.into_iter()
.map(|cb| KrateBan {
id: Skrate::new(
Expand All @@ -139,7 +150,42 @@ impl crate::cfg::UnvalidatedConfig for Config {
},
cb.name.span,
),
wrappers: cb.wrappers,
wrappers: cb
.wrappers
.map(|spanned| spanned.value)
.unwrap_or_else(Vec::new),
})
.collect();

let denied_multiple_versions: Vec<_> = deny_multiple_versions
.into_iter()
.map(|cb| {
let wrappers = cb.wrappers.filter(|spanned| !spanned.value.is_empty());
if let Some(wrappers) = wrappers {
// cb.multiple_versions is guaranteed to be Some(_) by the
// earlier call to `partition`
let multiple_versions = cb.multiple_versions.unwrap();
diags.push(
Diagnostic::error()
.with_message(
"a crate ban was specified with both `wrappers` and `multiple-versions`",
)
.with_labels(vec![
Label::secondary(cfg_file, wrappers.span)
.with_message("has one or more `wrappers`"),
Label::secondary(cfg_file, multiple_versions.span)
.with_message("has `multiple-versions` set to true"),
]),
);
}

Skrate::new(
KrateId {
name: cb.name.value,
version: cb.version,
},
cb.name.span,
)
})
.collect();

Expand Down Expand Up @@ -182,6 +228,7 @@ impl crate::cfg::UnvalidatedConfig for Config {
multiple_versions: self.multiple_versions,
highlight: self.highlight,
denied,
denied_multiple_versions,
allowed,
skipped,
wildcards: self.wildcards,
Expand Down Expand Up @@ -212,6 +259,7 @@ pub struct ValidConfig {
pub multiple_versions: LintLevel,
pub highlight: GraphHighlight,
pub(crate) denied: Vec<KrateBan>,
pub(crate) denied_multiple_versions: Vec<Skrate>,
pub(crate) allowed: Vec<Skrate>,
pub(crate) skipped: Vec<Skrate>,
pub(crate) tree_skipped: Vec<Spanned<TreeSkip>>,
Expand Down