From b62942e03244fe9f727b1cf1d4a0635c83b11692 Mon Sep 17 00:00:00 2001 From: Nathaniel Navarro Date: Wed, 5 Jun 2024 09:09:48 -0400 Subject: [PATCH] [fud2] Unique fud2 directories and version gating `ninja --quiet` (#2092) * attempt to create a unique directory for each fud2 execution * version checking for --quiet * trigger CI again * Use a stable directory name when `--keep` * Remove an unnecessary `into` Now that we are cloning the working directory anyway. * Factor out ninja_supports_quiet --------- Co-authored-by: Adrian Sampson --- Cargo.lock | 1 + fud2/fud-core/Cargo.toml | 1 + fud2/fud-core/src/cli.rs | 17 +++++++++++------ fud2/fud-core/src/exec/driver.rs | 19 +++++++++++++++++-- fud2/fud-core/src/run.rs | 21 ++++++++++++++++++++- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ede71d979..b4ab7c4fd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1163,6 +1163,7 @@ dependencies = [ "log", "once_cell", "pathdiff", + "rand", "rhai", "serde", ] diff --git a/fud2/fud-core/Cargo.toml b/fud2/fud-core/Cargo.toml index ff0ae2cb8b..bf221dc426 100644 --- a/fud2/fud-core/Cargo.toml +++ b/fud2/fud-core/Cargo.toml @@ -22,3 +22,4 @@ env_logger.workspace = true rhai = "1.18.0" once_cell = "1.19.0" ariadne = "0.4.1" +rand = "0.8.5" diff --git a/fud2/fud-core/src/cli.rs b/fud2/fud-core/src/cli.rs index 10edd350d8..2a3de2fd64 100644 --- a/fud2/fud-core/src/cli.rs +++ b/fud2/fud-core/src/cli.rs @@ -3,7 +3,7 @@ use crate::exec::{Driver, Request, StateRef}; use crate::run::Run; use anyhow::{anyhow, bail}; use argh::FromArgs; -use camino::{Utf8Path, Utf8PathBuf}; +use camino::Utf8PathBuf; use std::fmt::Display; use std::str::FromStr; @@ -164,10 +164,15 @@ fn to_state(driver: &Driver, args: &FakeArgs) -> anyhow::Result { fn get_request(driver: &Driver, args: &FakeArgs) -> anyhow::Result { // The default working directory (if not specified) depends on the mode. - let default_workdir = driver.default_workdir(); - let workdir = args.dir.as_deref().unwrap_or_else(|| match args.mode { - Mode::Generate | Mode::Run => default_workdir.as_ref(), - _ => Utf8Path::new("."), + let workdir = args.dir.clone().unwrap_or_else(|| match args.mode { + Mode::Generate | Mode::Run => { + if args.keep.unwrap_or(false) { + driver.stable_workdir() + } else { + driver.fresh_workdir() + } + } + _ => ".".into(), }); // Find all the operations to route through. @@ -187,7 +192,7 @@ fn get_request(driver: &Driver, args: &FakeArgs) -> anyhow::Result { end_file: args.output.clone(), end_state: to_state(driver, args)?, through: through?, - workdir: workdir.into(), + workdir, }) } diff --git a/fud2/fud-core/src/exec/driver.rs b/fud2/fud-core/src/exec/driver.rs index 8d50df3aef..d4b288803e 100644 --- a/fud2/fud-core/src/exec/driver.rs +++ b/fud2/fud-core/src/exec/driver.rs @@ -2,6 +2,7 @@ use super::{OpRef, Operation, Request, Setup, SetupRef, State, StateRef}; use crate::{config, run, script, utils}; use camino::{Utf8Path, Utf8PathBuf}; use cranelift_entity::{PrimaryMap, SecondaryMap}; +use rand::distributions::{Alphanumeric, DistString}; use std::{collections::HashMap, error::Error, fmt::Display}; #[derive(PartialEq)] @@ -195,11 +196,25 @@ impl Driver { .map(|(op, _)| op) } - /// The working directory to use when running a build. - pub fn default_workdir(&self) -> Utf8PathBuf { + /// The default working directory name when we want the same directory on every run. + pub fn stable_workdir(&self) -> Utf8PathBuf { format!(".{}", &self.name).into() } + /// A new working directory that does not yet exist on the filesystem, for when we + /// want to avoid collisions. + pub fn fresh_workdir(&self) -> Utf8PathBuf { + loop { + let rand_suffix = + Alphanumeric.sample_string(&mut rand::thread_rng(), 8); + let path: Utf8PathBuf = + format!(".{}-{}", &self.name, rand_suffix).into(); + if !path.exists() { + return path; + } + } + } + /// Print a list of registered states and operations to stdout. pub fn print_info(&self) { println!("States:"); diff --git a/fud2/fud-core/src/run.rs b/fud2/fud-core/src/run.rs index 705776ec0f..d7011e7613 100644 --- a/fud2/fud-core/src/run.rs +++ b/fud2/fud-core/src/run.rs @@ -222,7 +222,9 @@ impl<'a> Run<'a> { cmd.current_dir(&dir.path); if !self.global_config.verbose { - cmd.arg("--quiet"); + if ninja_supports_quiet(&self.global_config.ninja)? { + cmd.arg("--quiet"); + } } else { cmd.arg("--verbose"); } @@ -449,6 +451,23 @@ impl Emitter { } } +/// Check whether a Ninja executable supports the `--quiet` flag. +fn ninja_supports_quiet(ninja: &str) -> std::io::Result { + let version_output = Command::new(ninja).arg("--version").output()?; + if let Ok(version) = String::from_utf8(version_output.stdout) { + let parts: Vec<&str> = version.split('.').collect(); + if parts.len() >= 2 { + let major = parts[0].parse::().unwrap_or(0); + let minor = parts[1].parse::().unwrap_or(0); + Ok(major > 1 || (major == 1 && minor >= 11)) + } else { + Ok(false) + } + } else { + Ok(false) + } +} + /// A directory that can optionally delete itself when we're done with it. pub struct TempDir { path: Utf8PathBuf,