Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
7306475
Cargo.toml: Add `miette` and `thiserror` as dependencies
fischeti Jan 10, 2026
5d67d0e
error: Initial implementation of Warnings and suppression
fischeti Jan 10, 2026
026953d
errorr: Improve `emit` function
fischeti Jan 10, 2026
d8cc84d
Cargo.toml: Add `owo-colors` as dependency
fischeti Jan 10, 2026
d3c5d40
error: Nicely format warning messages
fischeti Jan 10, 2026
1f17037
sess: Add diagnostics handler
fischeti Jan 10, 2026
e6c1ce4
error: Add first warning
fischeti Jan 10, 2026
4c72646
error: Force dimming again after styled messages
fischeti Jan 10, 2026
e9a76a1
error: Add `emit_if` wrapper function
fischeti Jan 10, 2026
a57ed6e
error: Make Diagnostic a global static variable
fischeti Jan 10, 2026
113d1d1
error: Make `emit` a function of `Warning` itself
fischeti Jan 10, 2026
4bd2481
error: Drop `emitted` manually
fischeti Jan 10, 2026
c2c71ce
error: Migrate some warnings
fischeti Jan 10, 2026
4ea3b4e
error: Render multiple help messages
fischeti Jan 10, 2026
e61a777
error: Specify severity globally for `Warning`
fischeti Jan 11, 2026
e3c352d
error: Add suppression annotation below warning
fischeti Jan 11, 2026
9f5f088
error: Move W16 to `Warnings` (duplicates!)
fischeti Jan 11, 2026
7d80b3f
error: Export format macros
fischeti Jan 11, 2026
c2ae983
error: Migrate more warnings
fischeti Jan 11, 2026
4cea9ab
error: Replace deprecated `ATOMIC_BOOL_INIT`
fischeti Jan 11, 2026
b9a80d7
error: Remove `warnln` macro
fischeti Jan 11, 2026
cedb691
sess: Don't pass `suppress_warnings` anymore
fischeti Jan 11, 2026
8d528b3
error: Add unit tests
fischeti Jan 11, 2026
240b9ac
error: Add note on use of struct/tuple in enum variants
fischeti Jan 11, 2026
4facd23
error: Fix merge conflicts
fischeti Jan 12, 2026
ce302b9
cli: Fix some merge conflicts
fischeti Jan 14, 2026
05e719c
Fix clippy warnings
fischeti Jan 14, 2026
9c30dbd
Move Warnings into `diagnostics`
fischeti Jan 14, 2026
6c0a7c5
error: Rename formatting macros and move to `util`
fischeti Jan 14, 2026
02efe00
diagnostic: Differentiate W06 warnings
fischeti Jan 14, 2026
bbffaf9
diagnostics: Remove suppression hint, show code again
fischeti Jan 14, 2026
ddb5ba3
diagnostic: Consistently format `version` and `revision`
fischeti Jan 14, 2026
a02fb4d
diagnostic: Fix/duplicate W19 warning
fischeti Jan 14, 2026
b7601c1
diagnostic: Warning todo comments
fischeti Jan 14, 2026
6cf0f46
Cargo.toml: Remove `fancy` feature from `miette` again
fischeti Jan 15, 2026
de00a5e
Add some additional information, cleanup
micprog Jan 16, 2026
2295bfa
diagnostics: Address review comments
fischeti Jan 17, 2026
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
176 changes: 107 additions & 69 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ glob = "0.3"
walkdir = "2"
subst = "0.3"
tera = "1.19"
miette = "7.6.0"
thiserror = "2.0.17"
owo-colors = "4.2.3"

[target.'cfg(windows)'.dependencies]
dunce = "1.0.4"
Expand Down
48 changes: 19 additions & 29 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! Main command line tool implementation.

use std;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::process::Command as SysCommand;

Expand All @@ -22,6 +23,7 @@ use tokio::runtime::Runtime;
use crate::cmd;
use crate::cmd::fusesoc::FusesocArgs;
use crate::config::{Config, Manifest, Merge, PartialConfig, PrefixPaths, Validate};
use crate::diagnostic::{Diagnostics, Warnings};
use crate::error::*;
use crate::lockfile::*;
use crate::sess::{Session, SessionArenas, SessionIo};
Expand Down Expand Up @@ -113,8 +115,9 @@ pub fn main() -> Result<()> {
// Parse command line arguments.
let cli = Cli::parse();

let mut suppressed_warnings: IndexSet<String> =
let mut suppressed_warnings: HashSet<String> =
cli.suppress.into_iter().map(|s| s.to_owned()).collect();

// split suppress strings on commas and spaces
suppressed_warnings = suppressed_warnings
.into_iter()
Expand All @@ -125,9 +128,8 @@ pub fn main() -> Result<()> {
})
.collect();

if suppressed_warnings.contains("all") || suppressed_warnings.contains("Wall") {
suppressed_warnings.extend((1..24).map(|i| format!("W{:02}", i)));
}
// Initialize warning and error handling with the suppression arguments.
Diagnostics::init(suppressed_warnings);

#[cfg(debug_assertions)]
if cli.debug {
Expand All @@ -147,7 +149,7 @@ pub fn main() -> Result<()> {
}

let force_fetch = match cli.command {
Commands::Update(ref args) => cmd::update::setup(args, cli.local, &suppressed_warnings)?,
Commands::Update(ref args) => cmd::update::setup(args, cli.local)?,
_ => false,
};

Expand All @@ -165,15 +167,11 @@ pub fn main() -> Result<()> {

// Parse the manifest file of the package.
let manifest_path = root_dir.join("Bender.yml");
let manifest = read_manifest(&manifest_path, &suppressed_warnings)?;
let manifest = read_manifest(&manifest_path)?;
debugln!("main: {:#?}", manifest);

// Gather and parse the tool configuration.
let config = load_config(
&root_dir,
matches!(cli.command, Commands::Update(_)) && !suppressed_warnings.contains("W02"),
&suppressed_warnings,
)?;
let config = load_config(&root_dir, matches!(cli.command, Commands::Update(_)))?;
debugln!("main: {:#?}", config);

// Determine git throttle. The precedence is: CLI argument, env variable, config file, default (4).
Expand All @@ -189,7 +187,6 @@ pub fn main() -> Result<()> {
cli.local,
force_fetch,
git_throttle,
suppressed_warnings,
);

if let Commands::Clean(args) = cli.command {
Expand Down Expand Up @@ -252,13 +249,7 @@ pub fn main() -> Result<()> {
)
})?;
if !meta.file_type().is_symlink() {
if !sess.suppress_warnings.contains("W01") {
warnln!(
"[W01] Skipping link to package {} at {:?} since there is something there",
pkg_name,
path
);
}
Warnings::SkippingPackageLink(pkg_name.clone(), path.clone()).emit();
continue;
}
if path.read_link().map(|d| d != pkg_path).unwrap_or(true) {
Expand Down Expand Up @@ -398,7 +389,7 @@ fn find_package_root(from: &Path) -> Result<PathBuf> {
}

/// Read a package manifest from a file.
pub fn read_manifest(path: &Path, suppress_warnings: &IndexSet<String>) -> Result<Manifest> {
pub fn read_manifest(path: &Path) -> Result<Manifest> {
use crate::config::PartialManifest;
use std::fs::File;
debugln!("read_manifest: {:?}", path);
Expand All @@ -409,16 +400,12 @@ pub fn read_manifest(path: &Path, suppress_warnings: &IndexSet<String>) -> Resul
partial
.prefix_paths(path.parent().unwrap())
.map_err(|cause| Error::chain(format!("Error in manifest prefixing {:?}.", path), cause))?
.validate("", false, suppress_warnings)
.validate("", false)
.map_err(|cause| Error::chain(format!("Error in manifest {:?}.", path), cause))
}

/// Load a configuration by traversing a directory hierarchy upwards.
fn load_config(
from: &Path,
warn_config_loaded: bool,
suppress_warnings: &IndexSet<String>,
) -> Result<Config> {
fn load_config(from: &Path, warn_config_loaded: bool) -> Result<Config> {
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;

Expand Down Expand Up @@ -491,7 +478,7 @@ fn load_config(

// Validate the configuration.
let mut out = out
.validate("", false, suppress_warnings)
.validate("", false)
.map_err(|cause| Error::chain("Invalid configuration:", cause))?;

out.overrides = out
Expand All @@ -515,8 +502,11 @@ fn maybe_load_config(path: &Path, warn_config_loaded: bool) -> Result<Option<Par
let partial: PartialConfig = serde_yaml_ng::from_reader(file)
.map_err(|cause| Error::chain(format!("Syntax error in config {:?}.", path), cause))?;
if warn_config_loaded {
warnln!("[W02] Using config at {:?} for overrides.", path)
};
Warnings::UsingConfigForOverride {
path: path.to_path_buf(),
}
.emit();
}
Ok(Some(partial.prefix_paths(path.parent().unwrap())?))
}

Expand Down
11 changes: 4 additions & 7 deletions src/cmd/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use tokio::runtime::Runtime;

use crate::config;
use crate::config::{Locked, LockedSource};
use crate::diagnostic::Warnings;
use crate::error::*;
use crate::sess::{DependencyRef, DependencySource, Session, SessionIo};

Expand Down Expand Up @@ -138,8 +139,8 @@ pub fn run(sess: &Session, path: &Path, args: &CloneArgs) -> Result<()> {
{
Err(Error::new("git fetch failed".to_string()))?;
}
} else if !sess.suppress_warnings.contains("W14") {
warnln!("[W14] fetch not performed due to --local argument.");
} else {
Warnings::LocalNoFetch.emit();
}

eprintln!(
Expand Down Expand Up @@ -263,11 +264,7 @@ pub fn run(sess: &Session, path: &Path, args: &CloneArgs) -> Result<()> {
)
})?;
if !meta.file_type().is_symlink() {
warnln!(
"[W15] Skipping link to package {} at {:?} since there is something there",
pkg_name,
link_path
);
Warnings::SkippingPackageLink(pkg_name.clone(), link_path.to_path_buf()).emit();
continue;
}
if link_path.read_link().map(|d| d != pkg_path).unwrap_or(true) {
Expand Down
5 changes: 3 additions & 2 deletions src/cmd/fusesoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use itertools::Itertools;
use tokio::runtime::Runtime;
use walkdir::{DirEntry, WalkDir};

use crate::diagnostic::Warnings;
use crate::error::*;
use crate::sess::{Session, SessionIo};
use crate::src::{SourceFile, SourceGroup};
Expand Down Expand Up @@ -132,8 +133,8 @@ pub fn run_single(sess: &Session, args: &FusesocArgs) -> Result<()> {
Error::chain(format!("Unable to write corefile for {:?}.", &name), cause)
})?;

if fuse_depend_string.len() > 1 && !sess.suppress_warnings.contains("W16") {
warnln!("[W16] Depend strings may be wrong for the included dependencies!");
if fuse_depend_string.len() > 1 {
Warnings::DependStringMaybeWrong.emit();
}

Ok(())
Expand Down
40 changes: 29 additions & 11 deletions src/cmd/parents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use std::io::Write;

use crate::diagnostic::Warnings;
use clap::Args;
use indexmap::IndexMap;
use tabwriter::TabWriter;
Expand All @@ -14,6 +15,7 @@ use crate::config::Dependency;
use crate::error::*;
use crate::sess::{DependencyConstraint, DependencySource};
use crate::sess::{Session, SessionIo};
use crate::{fmt_path, fmt_version};

/// List packages calling this dependency
#[derive(Args, Debug)]
Expand Down Expand Up @@ -96,12 +98,25 @@ pub fn run(sess: &Session, args: &ParentsArgs) -> Result<()> {
}
);

if sess.config.overrides.contains_key(dep) && !sess.suppress_warnings.contains("W18") {
warnln!(
"[W18] An override is configured for {} to {:?}",
dep,
sess.config.overrides[dep]
)
if sess.config.overrides.contains_key(dep) {
Warnings::DepOverride {
pkg: dep.to_string(),
pkg_override: match sess.config.overrides[dep] {
Dependency::Version(ref v, _) => format!("version {}", fmt_version!(v)),
Dependency::Path(ref path, _) => format!("path {}", fmt_path!(path.display())),
Dependency::GitRevision(ref url, ref rev, _) => {
format!("git {} at revision {}", fmt_path!(url), fmt_version!(rev))
}
Dependency::GitVersion(ref url, ref version, _) => {
format!(
"git {} with version {}",
fmt_path!(url),
fmt_version!(version)
)
}
},
}
.emit();
}

Ok(())
Expand Down Expand Up @@ -150,9 +165,10 @@ pub fn get_parent_array(
let dep_manifest = rt.block_on(io.dependency_manifest(pkg, false, &[]))?;
// Filter out dependencies without a manifest
if dep_manifest.is_none() {
if !sess.suppress_warnings.contains("W17") {
warnln!("[W17] {} is shown to include dependency, but manifest does not have this information.", pkg_name.to_string());
Warnings::IncludeDepManifestMismatch {
pkg: pkg_name.to_string(),
}
.emit();
continue;
}
let dep_manifest = dep_manifest.unwrap();
Expand Down Expand Up @@ -182,9 +198,11 @@ pub fn get_parent_array(
],
);
}
} else if !sess.suppress_warnings.contains("W17") {
// Filter out dependencies with mismatching manifest
warnln!("[W17] {} is shown to include dependency, but manifest does not have this information.", pkg_name.to_string());
} else {
Warnings::IncludeDepManifestMismatch {
pkg: pkg_name.to_string(),
}
.emit();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ pub fn run(sess: &Session, args: &ScriptArgs) -> Result<()> {
let srcs = srcs
.flatten()
.into_iter()
.map(|f| f.validate("", false, &sess.suppress_warnings))
.map(|f| f.validate("", false))
.collect::<Result<Vec<_>>>()?;

let mut tera_context = Context::new();
Expand Down
13 changes: 3 additions & 10 deletions src/cmd/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use tokio::runtime::Runtime;

use crate::cmd::clone::{get_path_subdeps, symlink_dir};
use crate::config::{Dependency, Locked, LockedSource};
use crate::diagnostic::Warnings;
use crate::error::*;
use crate::sess::{DependencySource, Session, SessionIo};

Expand Down Expand Up @@ -57,11 +58,7 @@ pub fn run(sess: &Session, args: &SnapshotArgs) -> Result<()> {
.is_empty()
&& !args.no_skip
{
warnln!(
"Skipping dirty dependency {}\
\t use `--no-skip` to still snapshot.",
name
);
Warnings::SkippingDirtyDep { pkg: name.clone() }.emit();
continue;
}

Expand Down Expand Up @@ -255,11 +252,7 @@ pub fn run(sess: &Session, args: &SnapshotArgs) -> Result<()> {
)
})?;
if !meta.file_type().is_symlink() {
warnln!(
"[W15] Skipping link to package {} at {:?} since there is something there",
pkg_name,
link_path
);
Warnings::SkippingPackageLink(pkg_name.clone(), link_path.to_path_buf()).emit();
continue;
}
if link_path.read_link().map(|d| d != pkg_path).unwrap_or(true) {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub fn run(sess: &Session, args: &SourcesArgs) -> Result<()> {
srcs = srcs.filter_packages(packages).unwrap_or_default();
}

srcs = srcs.validate("", false, &sess.suppress_warnings)?;
srcs = srcs.validate("", false)?;

let result = {
let stdout = std::io::stdout();
Expand Down
9 changes: 4 additions & 5 deletions src/cmd/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use tabwriter::TabWriter;

use crate::cmd;
use crate::config::{Locked, LockedPackage};
use crate::diagnostic::Warnings;
use crate::error::*;
use crate::lockfile::*;
use crate::resolver::DependencyResolver;
Expand Down Expand Up @@ -42,11 +43,9 @@ pub struct UpdateArgs {
}

/// Execute the `update` subcommand.
pub fn setup(args: &UpdateArgs, local: bool, suppress_warnings: &IndexSet<String>) -> Result<bool> {
if local && args.fetch && !suppress_warnings.contains("W14") {
warnln!(
"[W14] As --local argument is set for bender command, no fetching will be performed."
);
pub fn setup(args: &UpdateArgs, local: bool) -> Result<bool> {
if local && args.fetch {
Warnings::LocalNoFetch.emit();
}
Ok(args.fetch)
}
Expand Down
Loading