mirror of
https://github.com/numtide/treefmt.git
synced 2024-09-11 17:07:44 +03:00
only run formatters if there are files to format
Add more debugging. Take the baseline from ~500millis to ~60millis.
This commit is contained in:
parent
fd7d6e2396
commit
c9bc5c63c9
@ -6,6 +6,11 @@ edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
console = "0.13"
|
||||
|
@ -40,7 +40,8 @@ fn cwd() -> PathBuf {
|
||||
}
|
||||
|
||||
/// Returns an absolute path to the treefmt.toml file. From the current folder, and up.
|
||||
#[must_use] pub fn lookup(dir: &PathBuf) -> Option<PathBuf> {
|
||||
#[must_use]
|
||||
pub fn lookup(dir: &PathBuf) -> Option<PathBuf> {
|
||||
let mut cwd = dir.clone();
|
||||
loop {
|
||||
let config_file = cwd.join(FILENAME);
|
||||
|
@ -48,7 +48,8 @@ pub struct CustomLogOutput {
|
||||
|
||||
impl CustomLogOutput {
|
||||
/// Returns a new CustomLogOutput
|
||||
#[must_use] pub const fn new() -> Self {
|
||||
#[must_use]
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
quiet: AtomicBool::new(false),
|
||||
log_level: AtomicU8::new(LogLevel::Info as u8),
|
||||
|
111
src/engine.rs
111
src/engine.rs
@ -49,6 +49,11 @@ pub fn run_treefmt(
|
||||
// Load the treefmt.toml file
|
||||
let project_config = config::from_path(&treefmt_toml)?;
|
||||
|
||||
CLOG.debug(&format!(
|
||||
"load config: {}",
|
||||
start_time.elapsed().as_millis()
|
||||
));
|
||||
|
||||
// Load all the formatter instances from the config. Ignore the ones that failed.
|
||||
let formatters =
|
||||
project_config
|
||||
@ -67,9 +72,14 @@ pub fn run_treefmt(
|
||||
sum
|
||||
});
|
||||
|
||||
CLOG.debug(&format!(
|
||||
"load formatters: {}",
|
||||
start_time.elapsed().as_millis()
|
||||
));
|
||||
|
||||
// Load the eval cache
|
||||
let cache = CacheManifest::load(&cache_dir, &treefmt_toml);
|
||||
|
||||
CLOG.debug(&format!("load cache: {}", start_time.elapsed().as_millis()));
|
||||
// Insert the new formatter configs
|
||||
let cache = cache.update_formatters(formatters.clone());
|
||||
|
||||
@ -126,10 +136,16 @@ pub fn run_treefmt(
|
||||
}
|
||||
}
|
||||
}
|
||||
CLOG.debug(&format!("tree walk: {}", start_time.elapsed().as_millis()));
|
||||
|
||||
// Filter out all of the paths that were already in the cache
|
||||
let matches = cache.clone().filter_matches(matches);
|
||||
|
||||
CLOG.debug(&format!(
|
||||
"filter_matches: {}",
|
||||
start_time.elapsed().as_millis()
|
||||
));
|
||||
|
||||
// Start another collection of formatter names to path to mtime.
|
||||
//
|
||||
// This time to collect the new paths that have been formatted.
|
||||
@ -141,62 +157,77 @@ pub fn run_treefmt(
|
||||
let paths: Vec<PathBuf> = path_mtime.keys().cloned().collect();
|
||||
let formatter = formatters.get(&formatter_name).unwrap();
|
||||
|
||||
// Keep track of the paths that are actually going to be formatted
|
||||
filtered_files += paths.len();
|
||||
if !paths.is_empty() {
|
||||
// Keep track of the paths that are actually going to be formatted
|
||||
filtered_files += paths.len();
|
||||
|
||||
match formatter.clone().fmt(&paths.clone()) {
|
||||
// FIXME: do we care about the output?
|
||||
Ok(_) => {
|
||||
// Get the new mtimes and compare them to the original ones
|
||||
let new_paths = paths.into_iter().fold(BTreeMap::new(), |mut sum, path| {
|
||||
let mtime = get_path_mtime(&path).unwrap();
|
||||
sum.insert(path, mtime);
|
||||
sum
|
||||
});
|
||||
new_matches.insert(formatter_name.clone(), new_paths);
|
||||
}
|
||||
Err(err) => {
|
||||
// FIXME: What is the right behaviour if a formatter has failed running?
|
||||
CLOG.error(&format!("{} failed: {}", &formatter, err));
|
||||
let start_time = Instant::now();
|
||||
|
||||
match formatter.clone().fmt(&paths.clone()) {
|
||||
// FIXME: do we care about the output?
|
||||
Ok(_) => {
|
||||
CLOG.info(&format!(
|
||||
"{}: {} files formatted in {} millis",
|
||||
formatter.name,
|
||||
paths.len(),
|
||||
start_time.elapsed().as_millis()
|
||||
));
|
||||
|
||||
// Get the new mtimes and compare them to the original ones
|
||||
let new_paths = paths.into_iter().fold(BTreeMap::new(), |mut sum, path| {
|
||||
let mtime = get_path_mtime(&path).unwrap();
|
||||
sum.insert(path, mtime);
|
||||
sum
|
||||
});
|
||||
new_matches.insert(formatter_name.clone(), new_paths);
|
||||
}
|
||||
Err(err) => {
|
||||
// FIXME: What is the right behaviour if a formatter has failed running?
|
||||
CLOG.error(&format!("{} failed: {}", &formatter, err));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CLOG.debug(&format!("format: {}", start_time.elapsed().as_millis()));
|
||||
|
||||
// Record the new matches in the cache
|
||||
let cache = cache.add_results(new_matches.clone());
|
||||
// And write to disk
|
||||
cache.write(cache_dir, treefmt_toml);
|
||||
CLOG.debug(&format!(
|
||||
"write cache: {}",
|
||||
start_time.elapsed().as_millis()
|
||||
));
|
||||
|
||||
// Diff the old matches with the new matches
|
||||
let changed_matches: BTreeMap<FormatterName, Vec<PathBuf>> = new_matches
|
||||
|
||||
.into_iter()
|
||||
.fold(BTreeMap::new(), |mut sum, (name, new_paths)| {
|
||||
let old_paths = matches.get(&name).unwrap().clone();
|
||||
let filtered = new_paths
|
||||
|
||||
.iter()
|
||||
.filter_map(|(k, v)| {
|
||||
if old_paths.get(k).unwrap() == v {
|
||||
None
|
||||
} else {
|
||||
Some(k.clone())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let changed_matches: BTreeMap<FormatterName, Vec<PathBuf>> =
|
||||
new_matches
|
||||
.into_iter()
|
||||
.fold(BTreeMap::new(), |mut sum, (name, new_paths)| {
|
||||
let old_paths = matches.get(&name).unwrap().clone();
|
||||
let filtered = new_paths
|
||||
.iter()
|
||||
.filter_map(|(k, v)| {
|
||||
if old_paths.get(k).unwrap() == v {
|
||||
None
|
||||
} else {
|
||||
Some(k.clone())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
sum.insert(name, filtered);
|
||||
sum
|
||||
});
|
||||
sum.insert(name, filtered);
|
||||
sum
|
||||
});
|
||||
|
||||
// Finally display all the paths that have been formatted
|
||||
for (_name, paths) in changed_matches {
|
||||
// Keep track of how many files were reformatted
|
||||
reformatted_files += paths.len();
|
||||
println!("{}:", name);
|
||||
for path in paths {
|
||||
println!("- {}", path.display());
|
||||
}
|
||||
// println!("{}:", name);
|
||||
// for path in paths {
|
||||
// println!("- {}", path.display());
|
||||
// }
|
||||
}
|
||||
|
||||
println!(
|
||||
|
@ -68,7 +68,8 @@ impl CacheManifest {
|
||||
}
|
||||
|
||||
/// Always loads the manifest. If an error occured, log and return an empty manifest.
|
||||
#[must_use] pub fn load(cache_dir: &PathBuf, treefmt_toml: &PathBuf) -> Self {
|
||||
#[must_use]
|
||||
pub fn load(cache_dir: &PathBuf, treefmt_toml: &PathBuf) -> Self {
|
||||
match Self::try_load(cache_dir, treefmt_toml) {
|
||||
Ok(manifest) => manifest,
|
||||
Err(err) => {
|
||||
@ -107,7 +108,8 @@ impl CacheManifest {
|
||||
|
||||
/// Checks and inserts the formatter info into the cache.
|
||||
/// If the formatter info has changed, invalidate all the old paths.
|
||||
#[must_use] pub fn update_formatters(self, formatters: BTreeMap<FormatterName, Formatter>) -> Self {
|
||||
#[must_use]
|
||||
pub fn update_formatters(self, formatters: BTreeMap<FormatterName, Formatter>) -> Self {
|
||||
let mut new_formatters = BTreeMap::new();
|
||||
let mut new_paths = self.matches.clone();
|
||||
for (name, fmt) in formatters {
|
||||
@ -145,12 +147,12 @@ impl CacheManifest {
|
||||
}
|
||||
|
||||
/// Returns a new map with all the paths that haven't changed
|
||||
#[must_use] pub fn filter_matches(
|
||||
#[must_use]
|
||||
pub fn filter_matches(
|
||||
self,
|
||||
matches: BTreeMap<FormatterName, BTreeMap<PathBuf, Mtime>>,
|
||||
) -> BTreeMap<FormatterName, BTreeMap<PathBuf, Mtime>> {
|
||||
matches
|
||||
|
||||
.into_iter()
|
||||
.fold(BTreeMap::new(), |mut sum, (key, path_infos)| {
|
||||
let new_path_infos = match self.matches.get(&key) {
|
||||
@ -175,10 +177,8 @@ impl CacheManifest {
|
||||
}
|
||||
|
||||
/// Merge recursively the new matches with the existing entries in the cache
|
||||
#[must_use] pub fn add_results(
|
||||
self,
|
||||
matches: BTreeMap<FormatterName, BTreeMap<PathBuf, Mtime>>,
|
||||
) -> Self {
|
||||
#[must_use]
|
||||
pub fn add_results(self, matches: BTreeMap<FormatterName, BTreeMap<PathBuf, Mtime>>) -> Self {
|
||||
// Get a copy of the old matches
|
||||
let mut new_matches = self.matches.to_owned();
|
||||
// This is really ugly. Get a second copy to work around lifetime issues.
|
||||
@ -187,7 +187,9 @@ impl CacheManifest {
|
||||
// Merge all the new matches into it
|
||||
for (name, path_infos) in matches {
|
||||
let mut def = BTreeMap::new();
|
||||
let merged_path_infos = new_matches_cmp.get_mut(&name).unwrap_or_else(|| def.borrow_mut());
|
||||
let merged_path_infos = new_matches_cmp
|
||||
.get_mut(&name)
|
||||
.unwrap_or_else(|| def.borrow_mut());
|
||||
for (path, mtime) in path_infos {
|
||||
merged_path_infos.insert(path.clone(), mtime);
|
||||
}
|
||||
|
@ -37,13 +37,15 @@ pub fn get_path_mtime(path: &PathBuf) -> Result<Mtime> {
|
||||
}
|
||||
|
||||
/// Small utility that stat() and retrieve the mtime of a file metadata
|
||||
#[must_use] pub fn get_meta_mtime(metadata: &Metadata) -> Mtime {
|
||||
#[must_use]
|
||||
pub fn get_meta_mtime(metadata: &Metadata) -> Mtime {
|
||||
Mtime(FileTime::from_last_modification_time(metadata).unix_seconds())
|
||||
}
|
||||
|
||||
/// Returns an absolute path. If the path is absolute already, leave it alone. Otherwise join it to the reference path.
|
||||
/// Then clean all superfluous ../
|
||||
#[must_use] pub fn expand_path(path: &PathBuf, reference: &PathBuf) -> PathBuf {
|
||||
#[must_use]
|
||||
pub fn expand_path(path: &PathBuf, reference: &PathBuf) -> PathBuf {
|
||||
let new_path = if path.is_absolute() {
|
||||
path.clone()
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user