Fix .\miri fmt on Windows

This commit is contained in:
Ross Smyth 2024-02-26 17:19:30 -05:00
parent c414c08da3
commit 32643dc853
2 changed files with 63 additions and 30 deletions

View file

@ -526,37 +526,27 @@ impl Command {
}
fn fmt(flags: Vec<OsString>) -> 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[..])
}
}

View file

@ -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<Item = Result<PathBuf, walkdir::Error>>,
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(())
}
}