Code change:
} } <ins> fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> { let stamp_file = build.out.join("rustfmt.stamp"); let mut cmd = Command::new(match build.initial_rustfmt() { Some(p) => p, None => return None, }); cmd.arg("--version"); let output = match cmd.output() { Ok(status) => status, Err(_) => return None, }; if !output.status.success() { return None; } Some((String::from_utf8(output.stdout).unwrap(), stamp_file)) } /// Return whether the format cache can be reused. fn verify_rustfmt_version(build: &Builder<'_>) -> bool { let Some((version, stamp_file)) = get_rustfmt_version(build) else {return false;}; !program_out_of_date(&stamp_file, &version) } /// Updates the last rustfmt version used fn update_rustfmt_version(build: &Builder<'_>) { let Some((version, stamp_file)) = get_rustfmt_version(build) else {return;}; t!(std::fs::write(stamp_file, version)) } /// Returns the files modified between the `merge-base` of HEAD and /// rust-lang/master and what is now on the disk. /// /// Returns `None` if all files should be formatted. fn get_modified_files(build: &Builder<'_>) -> Option<Vec<String>> { let Ok(remote) = get_rust_lang_rust_remote() else {return None;}; if !verify_rustfmt_version(build) { return None; } Some( output( build .config .git() .arg("diff-index") .arg("--name-only") .arg("--merge-base") .arg(&format!("{remote}/master")), ) .lines() .map(|s| s.trim().to_owned()) .collect(), ) } /// Finds the remote for rust-lang/rust. /// For example for these remotes it will return `upstream`. /// ```text /// origin  https://github.com/Nilstrieb/rust.git (fetch) /// origin  https://github.com/Nilstrieb/rust.git (push) /// upstream        https://github.com/rust-lang/rust (fetch) /// upstream        https://github.com/rust-lang/rust (push) /// ``` fn get_rust_lang_rust_remote() -> Result<String, String> { let mut git = Command::new("git"); git.args(["config", "--local", "--get-regex", "remote..*.url"]); let output = git.output().map_err(|err| format!("{err:?}"))?; if !output.status.success() { return Err("failed to execute git config command".to_owned()); } let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?; let rust_lang_remote = stdout .lines() .find(|remote| remote.contains("rust-lang")) .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?; let remote_name = rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; Ok(remote_name.into()) } </ins> #[derive(serde::Deserialize)] struct RustfmtConfig { ignore: Vec<String>,

Related discussion:
text: Since rustfmt is deterministic and idempotent, running it twice on the same file should always have the same output (if it's not both of those things, it's a bug). So we can avoid running it unless the file has changed, which should make without arguments much faster. Originally posted by in <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This will need to be careful to still rerun rustfmt when we bump its version (which happens about every 6 weeks). Maybe we can generate a file and format everything if it doesn't yet exist or has the wrong version.
Hello, I want to work on that. How would the detection of modified files work ?
you can use to see modified files. Make sure to fall back to formatting all files if that command fails for some reason, we support building from source tarballs without git installed.
This means that already-commited files that were not formatted when committed would not be formatted, right ?
Ah, good point. You can use to find where the two diverged and compare all files since then. And should still look at all files unconditionally.
Thanks, I will start working on this ! claim
That assumes that the rust-lang remote is labeled as origin. I call that upstream and my fork origin. Using the local master may also not work if one does on branch.
Yes, has a more general solution.
PR is up at