Repository: cross-rs/cross
Pull request #968 (2022-07-23 19:38:56)

introduce verbosity levels
this will make it so rustup doesn't show verbose unless `-vv` or `-v` and `CROSS_DEBUG` is used.


Alexhuszagh: It might also be worth linking this with #797, and adding the diagnostics using `msg_info.note` or something similar. Something like:

```diff
diff --git a/src/docker/mod.rs b/src/docker/mod.rs
index cd80b20..237fc80 100644
--- a/src/docker/mod.rs
+++ b/src/docker/mod.rs
@@ -51,6 +51,7 @@ pub fn run(
             1,
         );
     }
+    msg_info.note(format_args!("running {} subcommand in container.", options.cargo_variant.to_str()))?;
     if options.is_remote() {
         remote::run(options, paths, args, msg_info).wrap_err("could not complete remote run")
     } else {
diff --git a/src/docker/remote.rs b/src/docker/remote.rs
index 23215f6..2349309 100644
--- a/src/docker/remote.rs
+++ b/src/docker/remote.rs
@@ -984,6 +984,7 @@ pub(crate) fn run(
     };
     let mount_prefix_path = mount_prefix.as_ref();
     if let VolumeId::Discard = volume {
+        msg_info.note("copying rust toolchain to temporary data volume.")?;
         copy_volume_container_xargo(engine, &container, dirs, mount_prefix_path, msg_info)
             .wrap_err("when copying xargo")?;
         copy_volume_container_cargo(engine, &container, dirs, mount_prefix_path, false, msg_info)
@@ -999,6 +1000,7 @@ pub(crate) fn run(
         .wrap_err("when copying rust")?;
     } else {
         // need to copy over the target triple if it hasn't been previously copied
+        msg_info.note(format_args!("copying rust target toolchain \"{}\" to data volume if it was not previously copied.", target.target()))?;
         copy_volume_container_rust_triple(
             engine,
             &container,
@@ -1027,6 +1029,7 @@ pub(crate) fn run(
         )
         .wrap_err("when creating mount root")?;
     }
+    msg_info.note("copying project and mounted volume files to data volume.")?;
     copy_volume_container_project(
         engine,
         &container,
diff --git a/src/rustup.rs b/src/rustup.rs
index 2b47a4d..27fdd62 100644
--- a/src/rustup.rs
+++ b/src/rustup.rs
@@ -148,8 +148,9 @@ fn version(msg_info: &mut MessageInfo) -> Result<Version> {
 }
 
 pub fn install_toolchain(toolchain: &QualifiedToolchain, msg_info: &mut MessageInfo) -> Result<()> {
-    let mut command = rustup_command(msg_info, false);
     let toolchain = toolchain.to_string();
+    msg_info.note(format_args!("installing \"{toolchain}\" toolchain via rustup."))?;
+    let mut command = rustup_command(msg_info, false);
     command.args(&["toolchain", "add", &toolchain, "--profile", "minimal"]);
     if version(msg_info)? >= semver::Version::new(1, 25, 0) {
         command.arg("--force-non-host");
@@ -166,6 +167,7 @@ pub fn install(
 ) -> Result<()> {
     let target = target.triple();
     let toolchain = toolchain.to_string();
+    msg_info.note(format_args!("adding \"{target}\" target for toolchain \"{toolchain}\" via rustup."))?;
     rustup_command(msg_info, false)
         .args(&["target", "add", target, "--toolchain", &toolchain])
         .run(msg_info, false)
@@ -178,6 +180,7 @@ pub fn install_component(
     msg_info: &mut MessageInfo,
 ) -> Result<()> {
     let toolchain = toolchain.to_string();
+    msg_info.note(format_args!("installing \"{component}\" component for toolchain \"{toolchain}\" via rustup."))?;
     rustup_command(msg_info, false)
         .args(&["component", "add", component, "--toolchain", &toolchain])
         .run(msg_info, false)

```
Alexhuszagh: Removed some of my comments since the rationale for the PR was made clearer elsewhere: the goal is so every external call to a `rustup`, `cargo`, etc. command is only printed if the verbosity level is >= 2 (similar to cargo, which only displays `rustc` commands only if `-vv` or higher is provided).

Patch:
diff --git a/.changes/968.json b/.changes/968.json
new file mode 100644
index 0000000..1c1ebd1
--- /dev/null
+++ b/.changes/968.json
@@ -0,0 +1,4 @@
+{
+    "description": "only print rustup --verbose if `-vv` or `CROSS_VERBOSE=1` is used",
+    "type": "fixed"
+}
diff --git a/src/bin/cross.rs b/src/bin/cross.rs
index 64536d2..b98579a 100644
--- a/src/bin/cross.rs
+++ b/src/bin/cross.rs
@@ -18,7 +18,11 @@ pub fn main() -> cross::Result<()> {
     let target_list = rustc::target_list(&mut Verbosity::Quiet.into())?;
     let args = cli::parse(&target_list)?;
     let subcommand = args.subcommand;
-    let mut msg_info = shell::MessageInfo::create(args.verbose, args.quiet, args.color.as_deref())?;
+    let mut msg_info = shell::MessageInfo::create(
+        args.verbose + cross::config::bool_from_envvar("CROSS_DEBUG") as u8,
+        args.quiet,
+        args.color.as_deref(),
+    )?;
     let status = match cross::run(args, target_list, &mut msg_info)? {
         Some(status) => status,
         None => {
diff --git a/src/cli.rs b/src/cli.rs
index f5cf598..29d0da8 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -18,7 +18,7 @@ pub struct Args {
     pub target_dir: Option<PathBuf>,
     pub manifest_path: Option<PathBuf>,
     pub version: bool,
-    pub verbose: bool,
+    pub verbose: u8,
     pub quiet: bool,
     pub color: Option<String>,
 }
@@ -61,16 +61,22 @@ pub fn fmt_subcommands(stdout: &str, msg_info: &mut MessageInfo) -> Result<()> {
     Ok(())
 }
 
-fn is_verbose(arg: &str) -> bool {
+fn is_verbose(arg: &str) -> u8 {
     match arg {
-        "--verbose" => true,
+        "--verbose" => 1,
         // cargo can handle any number of "v"s
         a => {
-            a.starts_with('-')
+            if a.starts_with('-')
                 && a.len() >= 2
                 && a.get(1..)
                     .map(|a| a.chars().all(|x| x == 'v'))
                     .unwrap_or_default()
+            {
+                // string must be of form `-v[v]*` here
+                a.len() as u8 - 1
+            } else {
+                0
+            }
         }
     }
 }
@@ -160,7 +166,7 @@ pub fn parse(target_list: &TargetList) -> Result<Args> {
     let mut all: Vec<String> = Vec::new();
     let mut version = false;
     let mut quiet = false;
-    let mut verbose = false;
+    let mut verbose = 0;
     let mut color = None;
 
     {
@@ -169,8 +175,8 @@ pub fn parse(target_list: &TargetList) -> Result<Args> {
             if arg.is_empty() {
                 continue;
             }
-            if is_verbose(arg.as_str()) {
-                verbose = true;
+            if let v @ 1.. = is_verbose(arg.as_str()) {
+                verbose += v;
                 all.push(arg);
             } else if matches!(arg.as_str(), "--version" | "-V") {
                 version = true;
@@ -275,13 +281,13 @@ mod tests {
 
     #[test]
     fn is_verbose_test() {
-        assert!(!is_verbose("b"));
-        assert!(!is_verbose("x"));
-        assert!(!is_verbose("-"));
-        assert!(!is_verbose("-V"));
-        assert!(is_verbose("-v"));
-        assert!(is_verbose("--verbose"));
-        assert!(is_verbose("-vvvv"));
-        assert!(!is_verbose("-version"));
+        assert!(is_verbose("b") == 0);
+        assert!(is_verbose("x") == 0);
+        assert!(is_verbose("-") == 0);
+        assert!(is_verbose("-V") == 0);
+        assert!(is_verbose("-v") == 1);
+        assert!(is_verbose("--verbose") == 1);
+        assert!(is_verbose("-vvvv") == 4);
+        assert!(is_verbose("-version") == 0);
     }
 }
diff --git a/src/rustc.rs b/src/rustc.rs
index e36c947..f758fea 100644
--- a/src/rustc.rs
+++ b/src/rustc.rs
@@ -367,7 +367,7 @@ mod tests {
             "bisector-nightly-2022-04-26-x86_64-unknown-linux-gnu",
             "/tmp/cross/sysroot".as_ref(),
             &crate::config::Config::new(None),
-            &mut MessageInfo::create(true, false, None).unwrap(),
+            &mut MessageInfo::create(2, false, None).unwrap(),
         )
         .unwrap();
     }
diff --git a/src/rustup.rs b/src/rustup.rs
index 5e952d9..2b47a4d 100644
--- a/src/rustup.rs
+++ b/src/rustup.rs
@@ -39,7 +39,7 @@ fn rustup_command(msg_info: &mut MessageInfo, no_flags: bool) -> Command {
         Verbosity::Quiet => {
             cmd.arg("--quiet");
         }
-        Verbosity::Verbose => {
+        Verbosity::Verbose(2..) => {
             cmd.arg("--verbose");
         }
         _ => (),
diff --git a/src/shell.rs b/src/shell.rs
index 90171fe..b32eaca 100644
--- a/src/shell.rs
+++ b/src/shell.rs
@@ -69,25 +69,33 @@ macro_rules! status {
 pub enum Verbosity {
     Quiet,
     Normal,
-    Verbose,
+    Verbose(u8),
 }
 
 impl Verbosity {
     pub fn verbose(self) -> bool {
         match self {
-            Self::Verbose => true,
+            Self::Verbose(..) => true,
             Self::Normal | Self::Quiet => false,
         }
     }
 
-    fn create(color_choice: ColorChoice, verbose: bool, quiet: bool) -> Option<Self> {
-        match (verbose, quiet) {
-            (true, true) => {
+    #[must_use]
+    pub fn level(&self) -> u8 {
+        match &self {
+            Verbosity::Verbose(v) => *v,
+            _ => 0,
+        }
+    }
+
+    fn create(color_choice: ColorChoice, verbose: impl Into<u8>, quiet: bool) -> Option<Self> {
+        match (verbose.into(), quiet) {
+            (1.., true) => {
                 MessageInfo::from(color_choice).fatal("cannot set both --verbose and --quiet", 101)
             }
-            (true, false) => Some(Verbosity::Verbose),
-            (false, true) => Some(Verbosity::Quiet),
-            (false, false) => None,
+            (v @ 1.., false) => Some(Verbosity::Verbose(v)),
+            (0, true) => Some(Verbosity::Quiet),
+            (0, false) => None,
         }
     }
 }
@@ -143,7 +151,7 @@ impl MessageInfo {
         }
     }
 
-    pub fn create(verbose: bool, quiet: bool, color: Option<&str>) -> Result<MessageInfo> {
+    pub fn create(verbose: impl Into<u8>, quiet: bool, color: Option<&str>) -> Result<MessageInfo> {
         let color_choice = get_color_choice(color)?;
         let verbosity = get_verbosity(color_choice, verbose, quiet)?;
 
@@ -178,7 +186,7 @@ impl MessageInfo {
     }
 
     pub fn as_verbose<T, C: Fn(&mut MessageInfo) -> T>(&mut self, call: C) -> T {
-        self.as_verbosity(call, Verbosity::Verbose)
+        self.as_verbosity(call, Verbosity::Verbose(2))
     }
 
     fn erase_line<S: Stream + Write>(&mut self, stream: &mut S) -> Result<()> {
@@ -397,7 +405,11 @@ fn get_color_choice(color: Option<&str>) -> Result<ColorChoice> {
     })
 }
 
-fn get_verbosity(color_choice: ColorChoice, verbose: bool, quiet: bool) -> Result<Verbosity> {
+fn get_verbosity(
+    color_choice: ColorChoice,
+    verbose: impl Into<u8>,
+    quiet: bool,
+) -> Result<Verbosity> {
     // cargo always checks the value of these variables.
     let env_verbose = cargo_envvar_bool("CARGO_TERM_VERBOSE")?;
     let env_quiet = cargo_envvar_bool("CARGO_TERM_QUIET")?;
diff --git a/xtask/src/build_docker_image.rs b/xtask/src/build_docker_image.rs
index 70f120f..fcd2266 100644
--- a/xtask/src/build_docker_image.rs
+++ b/xtask/src/build_docker_image.rs
@@ -118,7 +118,7 @@ pub fn build_docker_image(
     msg_info: &mut MessageInfo,
 ) -> cross::Result<()> {
     let verbose = match verbose {
-        0 => msg_info.is_verbose() as u8,
+        0 => msg_info.verbosity.level(),
         v => v,
     };
     let metadata = cargo_metadata(msg_info)?;
diff --git a/xtask/src/ci.rs b/xtask/src/ci.rs
index 7a9d675..1d850f4 100644
--- a/xtask/src/ci.rs
+++ b/xtask/src/ci.rs
@@ -90,7 +90,7 @@ pub fn ci(args: CiJob, metadata: CargoMetadata) -> cross::Result<()> {
                 let search = cargo_command()
                     .args(&["search", "--limit", "1"])
                     .arg("cross")
-                    .run_and_get_stdout(&mut Verbosity::Verbose.into())?;
+                    .run_and_get_stdout(&mut Verbosity::Verbose(2).into())?;
                 let (cross, rest) = search
                     .split_once(" = ")
                     .ok_or_else(|| eyre::eyre!("cargo search failed"))?;
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 106d437..35a3067 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -115,7 +115,7 @@ pub fn main() -> cross::Result<()> {
             hooks::test(cli.toolchain.as_deref(), &mut msg_info)?;
         }
         Commands::CiJob(args) => {
-            let metadata = cargo_metadata(&mut Verbosity::Verbose.into())?;
+            let metadata = cargo_metadata(&mut Verbosity::Verbose(2).into())?;
             ci::ci(args, metadata)?;
         }
         Commands::ConfigureCrosstool(args) => {
diff --git a/xtask/src/util.rs b/xtask/src/util.rs
index c761163..f5cc7fe 100644
--- a/xtask/src/util.rs
+++ b/xtask/src/util.rs
@@ -20,7 +20,7 @@ pub fn get_cargo_workspace() -> &'static Path {
         cross::cargo_metadata_with_args(
             Some(manifest_dir.as_ref()),
             None,
-            &mut MessageInfo::create(true, false, None).expect("should not fail"),
+            &mut MessageInfo::create(2, false, None).expect("should not fail"),
         )
         .unwrap()
         .unwrap()
@@ -274,7 +274,7 @@ mod tests {
     fn check_ubuntu_base() -> cross::Result<()> {
         // count all the entries of FROM for our images
         let mut counts = BTreeMap::new();
-        let mut msg_info = Verbosity::Verbose.into();
+        let mut msg_info = Verbosity::Verbose(2).into();
         let dockerfiles = read_dockerfiles(&mut msg_info)?;
         for (path, dockerfile) in dockerfiles {
             let lines: Vec<&str> = dockerfile.lines().collect();


Test patch:
diff --git a/src/tests.rs b/src/tests.rs
index 2429a7b..02afac1 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -15,7 +15,7 @@ static WORKSPACE: OnceCell<PathBuf> = OnceCell::new();
 /// Returns the cargo workspace for the manifest
 pub fn get_cargo_workspace() -> &'static Path {
     let manifest_dir = env!("CARGO_MANIFEST_DIR");
-    let mut msg_info = crate::shell::Verbosity::Verbose.into();
+    let mut msg_info = crate::shell::Verbosity::Verbose(2).into();
     #[allow(clippy::unwrap_used)]
     WORKSPACE.get_or_init(|| {
         crate::cargo_metadata_with_args(Some(manifest_dir.as_ref()), None, &mut msg_info)