From 32643dc8536212ef01c8b9c63674cee050c10b8e Mon Sep 17 00:00:00 2001 From: Ross Smyth Date: Mon, 26 Feb 2024 17:19:30 -0500 Subject: [PATCH] Fix .\miri fmt on Windows --- src/tools/miri/miri-script/src/commands.rs | 46 +++++++++------------ src/tools/miri/miri-script/src/util.rs | 47 +++++++++++++++++++++- 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 88ee62fc18a1..dc6ef58c5208 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -526,37 +526,27 @@ impl Command { } fn fmt(flags: Vec) -> Result<()> { + use itertools::Itertools; + let e = MiriEnv::new()?; - let toolchain = &e.toolchain; let config_path = path!(e.miri_dir / "rustfmt.toml"); - let mut cmd = cmd!( - e.sh, - "rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}" - ); - eprintln!("$ {cmd} ..."); + // Collect each rust file in the miri repo. + let files = WalkDir::new(&e.miri_dir) + .into_iter() + .filter_entry(|entry| { + let name = entry.file_name().to_string_lossy(); + let ty = entry.file_type(); + if ty.is_file() { + name.ends_with(".rs") + } else { + // dir or symlink. skip `target` and `.git`. + &name != "target" && &name != ".git" + } + }) + .filter_ok(|item| item.file_type().is_file()) + .map_ok(|item| item.into_path()); - // Add all the filenames to the command. - // FIXME: `rustfmt` will follow the `mod` statements in these files, so we get a bunch of - // duplicate diffs. - for item in WalkDir::new(&e.miri_dir).into_iter().filter_entry(|entry| { - let name = entry.file_name().to_string_lossy(); - let ty = entry.file_type(); - if ty.is_file() { - name.ends_with(".rs") - } else { - // dir or symlink. skip `target` and `.git`. - &name != "target" && &name != ".git" - } - }) { - let item = item?; - if item.file_type().is_file() { - cmd = cmd.arg(item.into_path()); - } - } - - // We want our own error message, repeating the command is too much. - cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?; - Ok(()) + e.format_files(files, &e.toolchain[..], &config_path, &flags[..]) } } diff --git a/src/tools/miri/miri-script/src/util.rs b/src/tools/miri/miri-script/src/util.rs index 420ecdab63c9..5c0202432406 100644 --- a/src/tools/miri/miri-script/src/util.rs +++ b/src/tools/miri/miri-script/src/util.rs @@ -1,7 +1,7 @@ use std::ffi::{OsStr, OsString}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use dunce::canonicalize; use path_macro::path; use xshell::{cmd, Shell}; @@ -145,4 +145,47 @@ impl MiriEnv { .run()?; Ok(()) } + + /// Receives an iterator of files. + /// Will format each file with the miri rustfmt config. + /// Does not follow module relationships. + pub fn format_files( + &self, + files: impl Iterator>, + toolchain: &str, + config_path: &Path, + flags: &[OsString], + ) -> anyhow::Result<()> { + use itertools::Itertools; + + let mut first = true; + + // Format in batches as not all out files fit into Windows' command argument limit. + for batch in &files.chunks(256) { + // Build base command. + let mut cmd = cmd!( + self.sh, + "rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}" + ); + if first { + eprintln!("$ {cmd} ..."); + first = false; + } + // Add files. + for file in batch { + // Make it a relative path so that on platforms with extremely tight argument + // limits (like Windows), we become immune to someone cloning the repo + // 50 directories deep. + let file = file?; + let file = file.strip_prefix(&self.miri_dir)?; + cmd = cmd.arg(file); + } + + // Run commands. + // We want our own error message, repeating the command is too much. + cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?; + } + + Ok(()) + } }