Skip to content

Commit

Permalink
one idea for managing overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
suaviloquence committed Jun 3, 2024
1 parent 879a060 commit c041cd5
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 51 deletions.
29 changes: 15 additions & 14 deletions src/check_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use trustfall::{FieldValue, TransparentValue};
use trustfall_rustdoc::{VersionedCrate, VersionedIndexedCrate, VersionedRustdocAdapter};

use crate::{
query::{ActualSemverUpdate, LintLevel, RequiredSemverUpdate, SemverQuery},
query::{ActualSemverUpdate, LintLevel, QueryOverrideList, RequiredSemverUpdate, SemverQuery},
CrateReport, GlobalConfig, ReleaseType,
};

Expand Down Expand Up @@ -160,8 +160,9 @@ pub(super) fn run_check_release(
current_crate: VersionedCrate,
baseline_crate: VersionedCrate,
release_type: Option<ReleaseType>,
overrides: QueryOverrideList,
) -> anyhow::Result<CrateReport> {
let queries = config.all_queries()?;
let queries = SemverQuery::all_queries();

let current_version = current_crate.crate_version();
let baseline_version = baseline_crate.crate_version();
Expand Down Expand Up @@ -193,8 +194,8 @@ pub(super) fn run_check_release(
let adapter = VersionedRustdocAdapter::new(&current, Some(&previous))?;

let (queries_to_run, queries_to_skip): (Vec<_>, _) = queries.values().partition(|query| {
!version_change.supports_requirement(query.required_update)
&& query.lint_level >= LintLevel::Warn
!version_change.supports_requirement(overrides.effective_required_update(query))
&& overrides.effective_lint_level(query) >= LintLevel::Warn
});
let skipped_queries = queries_to_skip.len();

Expand Down Expand Up @@ -253,7 +254,7 @@ pub(super) fn run_check_release(
for (semver_query, time_to_decide, results) in all_results {
config
.log_verbose(|config| {
let category = match semver_query.required_update {
let category = match overrides.effective_required_update(semver_query) {
RequiredSemverUpdate::Major => "major",
RequiredSemverUpdate::Minor => "minor",
};
Expand Down Expand Up @@ -288,7 +289,7 @@ pub(super) fn run_check_release(
})
.expect("print failed");
if !results.is_empty() {
if semver_query.lint_level == LintLevel::Deny {
if overrides.effective_lint_level(semver_query) == LintLevel::Deny {
error_results.push((semver_query, results));
} else {
warning_results.push((semver_query, results));
Expand Down Expand Up @@ -317,26 +318,26 @@ pub(super) fn run_check_release(
let mut warnings = BTreeMap::new();
let mut errors = BTreeMap::new();
// print errors before warnings like clippy does
for (semver_query, results) in warning_results {
warnings
.entry(semver_query.required_update)
for (semver_query, results) in error_results {
errors
.entry(overrides.effective_required_update(semver_query))
.and_modify(|e| *e += 1)
.or_insert(1);

config.shell_warn(format!(
config.shell_error(format!(
"{}: {}",
&semver_query.id, &semver_query.human_readable_name
))?;
print_lint_failure(config, semver_query, results)?;
}

for (semver_query, results) in error_results {
errors
.entry(semver_query.required_update)
for (semver_query, results) in warning_results {
warnings
.entry(overrides.effective_required_update(semver_query))
.and_modify(|e| *e += 1)
.or_insert(1);

config.shell_error(format!(
config.shell_warn(format!(
"{}: {}",
&semver_query.id, &semver_query.human_readable_name
))?;
Expand Down
33 changes: 2 additions & 31 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use anstream::{AutoStream, ColorChoice};
use anstyle::{AnsiColor, Color, Reset, Style};
use std::{collections::BTreeMap, io::Write};
use std::io::Write;

use crate::{query::QueryOverride, templating::make_handlebars_registry, SemverQuery};
use crate::templating::make_handlebars_registry;

#[allow(dead_code)]
pub struct GlobalConfig {
Expand All @@ -14,9 +14,6 @@ pub struct GlobalConfig {
minimum_rustc_version: semver::Version,
stdout: AutoStream<Box<dyn Write + 'static>>,
stderr: AutoStream<Box<dyn Write + 'static>>,
/// A mapping of lint names to values to override that lint's defaults,
/// such as its lint level and required semver bump.
query_overrides: BTreeMap<String, QueryOverride>,
}

impl Default for GlobalConfig {
Expand All @@ -41,7 +38,6 @@ impl GlobalConfig {
minimum_rustc_version: semver::Version::new(1, 74, 0),
stdout: AutoStream::new(Box::new(std::io::stdout()), stdout_choice),
stderr: AutoStream::new(Box::new(std::io::stderr()), stderr_choice),
query_overrides: BTreeMap::new(),
}
}

Expand Down Expand Up @@ -288,31 +284,6 @@ impl GlobalConfig {
ColorChoice::Never | ColorChoice::Auto => false,
}
}

pub fn set_query_overrides(
&mut self,
query_overrides: BTreeMap<String, QueryOverride>,
) -> &mut Self {
self.query_overrides = query_overrides;
self
}

#[must_use]
pub fn query_overrides(&self) -> &BTreeMap<String, QueryOverride> {
&self.query_overrides
}

pub fn all_queries(&self) -> anyhow::Result<BTreeMap<String, SemverQuery>> {
let mut queries = SemverQuery::all_queries();
for (name, overrides) in &self.query_overrides {
if let Some(query) = queries.get_mut(name) {
query.apply_override(overrides);
} else {
anyhow::bail!("Can't configure lint with unknown name `{name}`.");
}
}
Ok(queries)
}
}

#[cfg(test)]
Expand Down
44 changes: 43 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ use trustfall_rustdoc::{load_rustdoc, VersionedCrate};
use rustdoc_cmd::RustdocCommand;
use std::collections::{BTreeMap, HashSet};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Instant;

pub use config::GlobalConfig;
pub use query::{ActualSemverUpdate, LintLevel, QueryOverride, RequiredSemverUpdate, SemverQuery};
pub use query::{
ActualSemverUpdate, LintLevel, QueryOverride, QueryOverrideList, QueryOverrides,
RequiredSemverUpdate, SemverQuery,
};

/// Test a release for semver violations.
#[non_exhaustive]
Expand All @@ -40,6 +44,13 @@ pub struct Check {
baseline_feature_config: rustdoc_gen::FeatureConfig,
/// Which `--target` to use, if unset pass no flag
build_target: Option<String>,
/// Workspace-level configuration overrides to apply to all packages if
/// running in workspace scope. Package-level overrides for a given
/// crate in `package_overrides take precedence over this member if both are set.
workspace_overrides: Option<Arc<QueryOverrides>>,
/// A mapping of package name to package-level configuration overrides for
/// that package. Takes precedence over `workspace_overrides` if both are set.
package_overrides: BTreeMap<String, Arc<QueryOverrides>>,
}

/// The kind of release we're making.
Expand Down Expand Up @@ -253,6 +264,8 @@ impl Check {
current_feature_config: rustdoc_gen::FeatureConfig::default_for_current(),
baseline_feature_config: rustdoc_gen::FeatureConfig::default_for_baseline(),
build_target: None,
workspace_overrides: None,
package_overrides: BTreeMap::new(),
}
}

Expand Down Expand Up @@ -372,6 +385,22 @@ impl Check {
})
}

/// Helper function to get the configured workspace-level overrides if set and
/// running in workspace scope, otherwise return an empty list.
#[must_use]
fn workspace_overrides(&self) -> Vec<Arc<QueryOverrides>> {
if let ScopeMode::DenyList(PackageSelection {
selection: ScopeSelection::Workspace,
..
}) = self.scope.mode
{
if let Some(wksp) = &self.workspace_overrides {
return vec![Arc::clone(wksp)];
}
}
vec![]
}

pub fn check_release(&self, config: &mut GlobalConfig) -> anyhow::Result<Report> {
let rustdoc_cmd = RustdocCommand::new().deps(false).silence(config.is_info());

Expand Down Expand Up @@ -447,12 +476,19 @@ impl Check {
},
)?;

let mut overrides = self.workspace_overrides();

if let Some(pkg) = self.package_overrides.get(&name) {
overrides.push(Arc::clone(pkg));
}

let report = run_check_release(
config,
&name,
current_crate,
baseline_crate,
self.release_type,
overrides.into(),
)?;
config.shell_status(
"Finished",
Expand Down Expand Up @@ -525,6 +561,11 @@ note: skipped the following crates since they have no library target: {skipped}"
},
)?;

let mut overrides = self.workspace_overrides();
if let Some(pkg) = self.package_overrides.get(&selected.name) {
overrides.push(Arc::clone(pkg));
}

let result = Ok((
crate_name.clone(),
Some(run_check_release(
Expand All @@ -533,6 +574,7 @@ note: skipped the following crates since they have no library target: {skipped}"
current_crate,
baseline_crate,
self.release_type,
overrides.into(),
)?),
));
config.shell_status(
Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ fn main() {
let mut config = GlobalConfig::new();
config.set_log_level(args.check_release.verbosity.log_level());

let queries = config.all_queries()?;
// TODO: do we want this to respect configuration in the current directory?
let queries = SemverQuery::all_queries();
let mut rows = vec![
["id", "type", "level", "description"],
["==", "====", "=====", "==========="],
Expand Down
Loading

0 comments on commit c041cd5

Please sign in to comment.