diff --git a/CHANGELOG.md b/CHANGELOG.md index d3482b131..0425e1ec9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## Unreleased +### Fixed +- Ensure informative print is not in stdout (e.g. fix for scripts) +- Use write to stdout instead of print to enable piping bender output into another command +- Remove compile warnings for release ## 0.29.0 - 2025-11-07 ### Fixed diff --git a/src/cmd/clean.rs b/src/cmd/clean.rs index ee37b11e7..cfcf64aad 100644 --- a/src/cmd/clean.rs +++ b/src/cmd/clean.rs @@ -23,7 +23,7 @@ pub fn new() -> Command { /// Execute the `clean` subcommand. pub fn run(sess: &Session, matches: &ArgMatches, path: &Path) -> Result<()> { - println!("Cleaning all dependencies"); + eprintln!("Cleaning all dependencies"); // Clean the checkout directory if let Some(checkout_dir) = &sess.manifest.workspace.checkout_dir { @@ -33,9 +33,9 @@ pub fn run(sess: &Session, matches: &ArgMatches, path: &Path) -> Result<()> { eprintln!("Failed to clean checkout directory: {:?}", e); e })?; - println!("Successfully cleaned {}", checkout_dir.display()); + eprintln!("Successfully cleaned {}", checkout_dir.display()); } else { - println!("No checkout directory found."); + eprintln!("No checkout directory found."); } } @@ -46,7 +46,7 @@ pub fn run(sess: &Session, matches: &ArgMatches, path: &Path) -> Result<()> { eprintln!("Failed to clean .bender directory: {:?}", e); e })?; - println!("Successfully cleaned .bender directory."); + eprintln!("Successfully cleaned .bender directory."); } // Clean the Bender.lock file @@ -56,7 +56,7 @@ pub fn run(sess: &Session, matches: &ArgMatches, path: &Path) -> Result<()> { eprintln!("Failed to remove Bender.lock file: {:?}", e); e })?; - println!("Successfully removed Bender.lock file."); + eprintln!("Successfully removed Bender.lock file."); } Ok(()) diff --git a/src/cmd/clone.rs b/src/cmd/clone.rs index 9f092a419..50b9ec14b 100644 --- a/src/cmd/clone.rs +++ b/src/cmd/clone.rs @@ -52,7 +52,7 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { )))?; } _ => { - println!("A non-path override is already present, proceeding anyways"); + eprintln!("A non-path override is already present, proceeding anyways"); } } } @@ -71,8 +71,8 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { // Copy dependency to dir for proper workflow if path.join(path_mod).join(dep).exists() { - println!("{} already has a directory in {}.", dep, path_mod); - println!("Please manually ensure the correct checkout."); + eprintln!("{} already has a directory in {}.", dep, path_mod); + eprintln!("Please manually ensure the correct checkout."); } else { let rt = Runtime::new()?; let io = SessionIo::new(sess); @@ -105,7 +105,6 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { if !command.unwrap().success() { Err(Error::new(format!("Copying {} failed", dep,)))?; } - // println!("{:?}", command); } } @@ -155,7 +154,7 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { warnln!("[W14] fetch not performed due to --local argument."); } - println!( + eprintln!( "{} checkout added in {:?}", dep, path.join(path_mod).join(dep) @@ -212,7 +211,7 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { )))? }; - println!("{} dependency added to Bender.local", dep); + eprintln!("{} dependency added to Bender.local", dep); // Update Bender.lock to enforce usage use std::fs::File; @@ -238,7 +237,7 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { serde_yaml_ng::to_writer(&file, &locked) .map_err(|cause| Error::chain(format!("Cannot write lockfile {:?}.", path), cause))?; - println!("Lockfile updated"); + eprintln!("Lockfile updated"); // Update any possible workspace symlinks for (link_path, pkg_name) in &sess.manifest.workspace.package_links { @@ -309,7 +308,7 @@ pub fn run(sess: &Session, path: &Path, matches: &ArgMatches) -> Result<()> { std::env::set_current_dir(d).unwrap(); } } - println!("{} symlink updated", dep); + eprintln!("{} symlink updated", dep); } } diff --git a/src/cmd/config.rs b/src/cmd/config.rs index 0a20cfb75..fab9ef822 100644 --- a/src/cmd/config.rs +++ b/src/cmd/config.rs @@ -4,6 +4,7 @@ //! The `config` subcommand. use std; +use std::io::Write; use clap::{ArgMatches, Command}; use serde_json; @@ -23,6 +24,6 @@ pub fn run(sess: &Session, _matches: &ArgMatches) -> Result<()> { let handle = stdout.lock(); serde_json::to_writer_pretty(handle, sess.config) }; - println!(); + let _ = writeln!(std::io::stdout(),); result.map_err(|cause| Error::chain("Failed to serialize configuration.", cause)) } diff --git a/src/cmd/fusesoc.rs b/src/cmd/fusesoc.rs index 0787bb52a..de6f3efa1 100644 --- a/src/cmd/fusesoc.rs +++ b/src/cmd/fusesoc.rs @@ -281,7 +281,7 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { ) .unwrap(); } - println!("{}", msg); + let _ = writeln!(std::io::stdout(), "{}", msg); // Let user resolve conflict if both stderr and stdin go to a TTY. if std::io::stderr().is_terminal() && std::io::stdin().is_terminal() { index = { @@ -368,7 +368,6 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { lic_vec.clone(), )?; - // println!("{}", fuse_str); fs::write(&generate_files[pkg], fuse_str).map_err(|cause| { Error::chain(format!("Unable to write corefile for {:?}.", &pkg), cause) })?; diff --git a/src/cmd/packages.rs b/src/cmd/packages.rs index 48e450ac6..848f92e9f 100644 --- a/src/cmd/packages.rs +++ b/src/cmd/packages.rs @@ -108,7 +108,11 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { let mut tw = TabWriter::new(vec![]); write!(&mut tw, "{}", target_str).unwrap(); tw.flush().unwrap(); - print!("{}", String::from_utf8(tw.into_inner().unwrap()).unwrap()); + let _ = write!( + std::io::stdout(), + "{}", + String::from_utf8(tw.into_inner().unwrap()).unwrap() + ); } else if graph { let mut graph_str = String::from(""); for (&pkg, deps) in sess.graph().iter() { @@ -135,7 +139,11 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { let mut tw = TabWriter::new(vec![]); write!(&mut tw, "{}", graph_str).unwrap(); tw.flush().unwrap(); - print!("{}", String::from_utf8(tw.into_inner().unwrap()).unwrap()); + let _ = write!( + std::io::stdout(), + "{}", + String::from_utf8(tw.into_inner().unwrap()).unwrap() + ); } else { let mut version_str = String::from(""); for pkgs in sess.packages().iter() { @@ -162,25 +170,29 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { } else if flat { // Print one line per package. for pkg_name in pkg_names { - println!("{}", pkg_name); + let _ = writeln!(std::io::stdout(), "{}", pkg_name); } } else { // Print all packages per rank on one line. for (i, pkg_name) in pkg_names.enumerate() { if i > 0 { - print!(" {}", pkg_name); + let _ = write!(std::io::stdout(), " {}", pkg_name); } else { - print!("{}", pkg_name); + let _ = write!(std::io::stdout(), "{}", pkg_name); } } - println!(); + let _ = writeln!(std::io::stdout(),); } } if version { let mut tw = TabWriter::new(vec![]); write!(&mut tw, "{}", version_str).unwrap(); tw.flush().unwrap(); - print!("{}", String::from_utf8(tw.into_inner().unwrap()).unwrap()); + let _ = write!( + std::io::stdout(), + "{}", + String::from_utf8(tw.into_inner().unwrap()).unwrap() + ); } } Ok(()) diff --git a/src/cmd/parents.rs b/src/cmd/parents.rs index 4479261b5..e0730d352 100644 --- a/src/cmd/parents.rs +++ b/src/cmd/parents.rs @@ -90,9 +90,9 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { }; if parent_array.is_empty() { - println!("No parents found for {}.", dep); + let _ = writeln!(std::io::stdout(), "No parents found for {}.", dep); } else { - println!("Parents found:"); + let _ = writeln!(std::io::stdout(), "Parents found:"); let source = &parent_array.values().next().unwrap()[1]; let mut constant_source = true; for (_, v) in parent_array.iter() { @@ -114,10 +114,15 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { let mut tw = TabWriter::new(vec![]); write!(&mut tw, "{}", res).unwrap(); tw.flush().unwrap(); - print!("{}", String::from_utf8(tw.into_inner().unwrap()).unwrap()); + let _ = write!( + std::io::stdout(), + "{}", + String::from_utf8(tw.into_inner().unwrap()).unwrap() + ); } - println!( + let _ = writeln!( + std::io::stdout(), "{} used version: {} at {}{}", sess.dependency(mydep).name, match sess.dependency(mydep).version.clone() { diff --git a/src/cmd/path.rs b/src/cmd/path.rs index df01e3884..c36cef0eb 100644 --- a/src/cmd/path.rs +++ b/src/cmd/path.rs @@ -3,6 +3,8 @@ //! The `path` subcommand. +use std::io::Write; + use clap::{Arg, ArgAction, ArgMatches, Command}; use futures::future::join_all; use tokio::runtime::Runtime; @@ -63,7 +65,7 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { // Print paths for c in paths { if let Some(s) = c.to_str() { - println!("{}", s); + let _ = writeln!(std::io::stdout(), "{}", s); } } diff --git a/src/cmd/script.rs b/src/cmd/script.rs index 19b0154ed..fece9670b 100644 --- a/src/cmd/script.rs +++ b/src/cmd/script.rs @@ -4,6 +4,7 @@ //! The `script` subcommand. use std::fs; +use std::io::Write; use std::path::Path; use std::path::PathBuf; @@ -680,11 +681,12 @@ fn emit_template( tera_context.insert("vivado_filesets", &vivado_filesets); if template == "json" { - println!("{:#}", tera_context.into_json()); + let _ = writeln!(std::io::stdout(), "{:#}", tera_context.into_json()); return Ok(()); } - print!( + let _ = write!( + std::io::stdout(), "{}", tera_obj .render_str(template, &tera_context) diff --git a/src/cmd/sources.rs b/src/cmd/sources.rs index aab6ddf0d..45413aed9 100644 --- a/src/cmd/sources.rs +++ b/src/cmd/sources.rs @@ -4,6 +4,7 @@ //! The `sources` subcommand. use std; +use std::io::Write; use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use indexmap::{IndexMap, IndexSet}; @@ -172,6 +173,6 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { serde_json::to_writer_pretty(handle, &srcs) } }; - println!(); + let _ = writeln!(std::io::stdout(),); result.map_err(|cause| Error::chain("Failed to serialize source file manifest.", cause)) } diff --git a/src/cmd/update.rs b/src/cmd/update.rs index 9b010e1f6..9f8bba82e 100644 --- a/src/cmd/update.rs +++ b/src/cmd/update.rs @@ -207,7 +207,7 @@ pub fn run_plain<'ctx>( let mut tw = TabWriter::new(vec![]); write!(&mut tw, "{}", update_str).unwrap(); tw.flush().unwrap(); - println!("{}", String::from_utf8(tw.into_inner().unwrap()).unwrap()); + eprintln!("{}", String::from_utf8(tw.into_inner().unwrap()).unwrap()); write_lockfile(&locked_new, &sess.root.join("Bender.lock"), sess.root)?; Ok((locked_new, update_map.keys().cloned().collect())) } diff --git a/src/cmd/vendor.rs b/src/cmd/vendor.rs index fccfeb3b2..f7254e752 100644 --- a/src/cmd/vendor.rs +++ b/src/cmd/vendor.rs @@ -4,21 +4,23 @@ //! The `vendor` subcommand. -use crate::config::PrefixPaths; -use crate::futures::TryFutureExt; +use std::collections::HashSet; +use std::io::Write; +use std::path::Path; +use std::path::PathBuf; + use clap::{Arg, ArgAction, ArgMatches, Command}; use futures::future::{self}; +use glob::Pattern; +use tempfile::TempDir; use tokio::runtime::Runtime; use crate::config; +use crate::config::PrefixPaths; use crate::error::*; +use crate::futures::TryFutureExt; use crate::git::Git; use crate::sess::{DependencySource, Session}; -use glob::Pattern; -use std::collections::HashSet; -use std::path::Path; -use std::path::PathBuf; -use tempfile::TempDir; /// A patch linkage #[derive(Clone)] @@ -199,7 +201,7 @@ pub fn run(sess: &Session, matches: &ArgMatches) -> Result<()> { let get_diff = diff(&rt, git.clone(), vendor_package, patch_link, dep_path.clone()) .map_err(|cause| Error::chain("Failed to get diff.", cause))?; if !get_diff.is_empty() { - print!("{}", get_diff); + let _ = write!(std::io::stdout(), "{}", get_diff); // If desired, return an error (e.g. for CI) if matches.contains_id("err_on_diff") { let err_msg : Option<&String> = matches.get_one("err_on_diff"); diff --git a/src/error.rs b/src/error.rs index 71c626dcb..778d56cac 100644 --- a/src/error.rs +++ b/src/error.rs @@ -45,10 +45,9 @@ macro_rules! debugln { #[macro_export] #[cfg(not(debug_assertions))] macro_rules! debugln { - ($($arg:tt)*) => { format!($($arg)*); } - // format! is used and discarded here such that the compiler does not - // complain about the arguments to debugln! not being used in release - // builds. + ($fmt:expr $(, $arg:expr)* $(,)?) => { $(let _ = $arg;)* } + // create an unused binding here so the compiler does not complain + // about the arguments to debugln! not being used in release builds. } /// Emit a diagnostic message. diff --git a/src/git.rs b/src/git.rs index 428db9b17..b11e5af0b 100644 --- a/src/git.rs +++ b/src/git.rs @@ -70,10 +70,10 @@ impl<'ctx> Git<'ctx> { .to_lowercase() .contains("too many open files") { - println!( + eprintln!( "Please consider increasing your `ulimit -n`, e.g. by running `ulimit -n 4096`" ); - println!("This is a known issue (#52)."); + eprintln!("This is a known issue (#52)."); Error::chain("Failed to spawn child process.", cause) } else { Error::chain("Failed to spawn child process.", cause)