From e6e98b600c9e954b371b8db17d87afcdc8665945 Mon Sep 17 00:00:00 2001 From: Basile Henry Date: Thu, 28 Jan 2021 10:33:45 +0100 Subject: [PATCH 1/5] Remove redudant extern crate --- src/main.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 64e729e8..096a4b27 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,5 @@ #![allow(clippy::redundant_closure, clippy::redundant_pattern_matching)] -extern crate anyhow; -extern crate env_logger; -extern crate log; -extern crate prjfmt; -extern crate structopt; - use prjfmt::{run_cli, Cli, CLOG}; use structopt::StructOpt; From 58074d9c30772c9741c9af1740748451345f1b92 Mon Sep 17 00:00:00 2001 From: Basile Henry Date: Thu, 28 Jan 2021 10:34:13 +0100 Subject: [PATCH 2/5] Use ignore for better control over globbing resolves #13: Includes and excludes resolves #24: Follows .gitgnore directives --- Cargo.lock | 101 ++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + examples/monorepo/prjfmt.toml | 5 +- src/formatters/tool.rs | 82 +++++++++++++++++---------- 4 files changed, 157 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e1cbe5a..949da429 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -47,6 +56,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bstr" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" +dependencies = [ + "memchr", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -184,6 +202,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.4" @@ -200,6 +224,19 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "globset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "heck" version = "0.3.2" @@ -224,6 +261,24 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +[[package]] +name = "ignore" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "itoa" version = "0.4.7" @@ -251,6 +306,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + [[package]] name = "memoffset" version = "0.6.1" @@ -270,6 +331,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -282,10 +349,12 @@ version = "0.1.0" dependencies = [ "anyhow", "console", + "either", "env_logger", "filetime", "glob", "hex", + "ignore", "log", "rayon", "serde", @@ -378,7 +447,10 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", + "thread_local", ] [[package]] @@ -393,6 +465,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -503,6 +584,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thread_local" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915" +dependencies = [ + "once_cell", +] + [[package]] name = "toml" version = "0.5.8" @@ -548,6 +638,17 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index f34043ab..112d95b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,10 +9,12 @@ edition = "2018" [dependencies] anyhow = "1.0" console = "0.13" +either = "1.6.1" env_logger = { version = "0.8", default-features = false } filetime = "0.2" glob = "0.3" hex = "0.4" +ignore = "0.4.17" log = "0.4" rayon = "1.5.0" serde = { version = "1.0", features = ["derive"] } diff --git a/examples/monorepo/prjfmt.toml b/examples/monorepo/prjfmt.toml index 07ee21be..b202db90 100644 --- a/examples/monorepo/prjfmt.toml +++ b/examples/monorepo/prjfmt.toml @@ -1,8 +1,7 @@ # fmt is the universal code formatter - https://github.com/numtide/fmt [formatters.ormolu] files = "*.hs" # / "*.hs" / "Makefile" mandatory -#includes = [ "haskell/" ] # "haskell-frontend/*.hs" treat it like whitelist, and haskell-frontend will be ignored. only if `includes` exists. -#excludes = [] # blacklisted folder/files. +excludes = [ "haskell/" ] # blacklisted folder/files. command = "ormolu" args = [ "--ghc-opt", "-XBangPatterns", @@ -17,4 +16,4 @@ files = [ "*.rs" ] includes = [ "rust/" ] excludes = [] command = "cargo" -args = [ "fmt", "--" ] \ No newline at end of file +args = [ "fmt", "--" ] diff --git a/src/formatters/tool.rs b/src/formatters/tool.rs index e1ba0550..a4dcc192 100644 --- a/src/formatters/tool.rs +++ b/src/formatters/tool.rs @@ -4,13 +4,12 @@ use crate::formatters::manifest::{read_prjfmt_manifest, RootManifest}; use crate::{emoji, CLOG}; use anyhow::{anyhow, Error, Result}; use filetime::FileTime; -use glob; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use std::fs::{metadata, read_to_string}; -use std::iter::Iterator; +use std::iter::{IntoIterator, Iterator}; use std::path::PathBuf; use xshell::cmd; @@ -113,38 +112,48 @@ pub fn run_prjfmt(cwd: PathBuf, cache_dir: PathBuf) -> anyhow::Result<()> { pub fn glob_to_path( cwd: &PathBuf, extensions: &FileExtensions, - _includes: &Option>, - _excludes: &Option>, + includes: &Option>, + excludes: &Option>, ) -> anyhow::Result> { - let dir = cwd.to_str().unwrap_or(""); - - let glob_ext = |extension| -> anyhow::Result<_> { - let pat = format!("{}/**/{}", dir, extension); - let globs = glob::glob(&pat).map_err(|err| { - anyhow::anyhow!( - "{} Error at position: {} due to {}", - emoji::ERROR, - err.pos, - err.msg - ) - })?; - - Ok(globs.map(|glob_res| Ok(glob_res?))) - }; + use ignore::{overrides::OverrideBuilder, WalkBuilder}; - match extensions { - FileExtensions::SingleFile(sfile) => glob_ext(sfile)?.collect(), - FileExtensions::MultipleFile(strs) => { - strs.iter() - .map(glob_ext) - .try_fold(Vec::new(), |mut v, globs| { - for glob in globs? { - v.push(glob?) - } - Ok(v) - }) + let mut overrides_builder = OverrideBuilder::new(cwd); + + if let Some(includes) = includes { + for include in includes { + // Remove trailing `/` as we add one explicitly in the override + let include = include.trim_end_matches('/'); + for extension in extensions.clone().into_iter() { + overrides_builder.add(&format!("{}/**/{}", include, extension))?; + } + } + } else { + for extension in extensions.clone().into_iter() { + overrides_builder.add(&extension)?; } } + + if let Some(excludes) = excludes { + for exclude in excludes { + overrides_builder.add(&format!("!/{}", exclude))?; + } + } + + let overrides = overrides_builder.build()?; + + Ok(WalkBuilder::new(cwd) + .overrides(overrides) + .build() + .filter_map(|e| { + e.ok().and_then(|e| { + match e.file_type() { + // Skip directory entries + Some(t) if t.is_dir() => None, + _ => Some(e.into_path()), + } + }) + }) + .collect()) } /// Convert each PathBuf into FileMeta @@ -246,6 +255,19 @@ pub enum FileExtensions { MultipleFile(Vec), } +impl IntoIterator for FileExtensions { + type Item = String; + type IntoIter = either::Either, std::vec::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + match self { + FileExtensions::SingleFile(glob) => + either::Either::Left(std::iter::once(glob)), + FileExtensions::MultipleFile(globs) => either::Either::Right(globs.into_iter()), + } + } +} + #[derive(Debug, Deserialize, Serialize, Clone)] /// Each context of the formatter config pub struct CmdContext { From 5f1d42515340e77d01894b4716d29fd0b23faa72 Mon Sep 17 00:00:00 2001 From: Basile Henry Date: Thu, 28 Jan 2021 11:22:01 +0100 Subject: [PATCH 3/5] Exclude not from root --- src/formatters/tool.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/formatters/tool.rs b/src/formatters/tool.rs index a4dcc192..8b42b46a 100644 --- a/src/formatters/tool.rs +++ b/src/formatters/tool.rs @@ -135,7 +135,7 @@ pub fn glob_to_path( if let Some(excludes) = excludes { for exclude in excludes { - overrides_builder.add(&format!("!/{}", exclude))?; + overrides_builder.add(&format!("!{}", exclude))?; } } @@ -261,8 +261,7 @@ impl IntoIterator for FileExtensions { fn into_iter(self) -> Self::IntoIter { match self { - FileExtensions::SingleFile(glob) => - either::Either::Left(std::iter::once(glob)), + FileExtensions::SingleFile(glob) => either::Either::Left(std::iter::once(glob)), FileExtensions::MultipleFile(globs) => either::Either::Right(globs.into_iter()), } } From e81f8dcf0095ac2e323ffbce96935e40054dc479 Mon Sep 17 00:00:00 2001 From: Basile Henry Date: Thu, 28 Jan 2021 11:22:11 +0100 Subject: [PATCH 4/5] Update cargoSha256 --- overlay.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overlay.nix b/overlay.nix index f547c197..09bdb3c1 100644 --- a/overlay.nix +++ b/overlay.nix @@ -5,7 +5,7 @@ final: prev: pname = "prjfmt"; version = "0.0.1"; src = ./.; - cargoSha256 = "sha256-98M9OPWil9bKknam8ys4dNP6/iZObW0RrAC7PxiHxYI="; + cargoSha256 = "sha256:0bsxwl5bhjg8d4mdyk2mx7g5744b790nhdlyg393vwjmnbnyy1k2"; doCheck = false; nativeBuildInputs = [ ]; buildInputs = [ ]; From c4ba6ca9536f0e8de609491fa4fac3480c22607d Mon Sep 17 00:00:00 2001 From: Basile Henry Date: Thu, 28 Jan 2021 11:29:11 +0100 Subject: [PATCH 5/5] Remove unnecessary clones --- src/formatters/tool.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/formatters/tool.rs b/src/formatters/tool.rs index 8b42b46a..7119a3e5 100644 --- a/src/formatters/tool.rs +++ b/src/formatters/tool.rs @@ -123,12 +123,12 @@ pub fn glob_to_path( for include in includes { // Remove trailing `/` as we add one explicitly in the override let include = include.trim_end_matches('/'); - for extension in extensions.clone().into_iter() { + for extension in extensions.into_iter() { overrides_builder.add(&format!("{}/**/{}", include, extension))?; } } } else { - for extension in extensions.clone().into_iter() { + for extension in extensions.into_iter() { overrides_builder.add(&extension)?; } } @@ -255,14 +255,14 @@ pub enum FileExtensions { MultipleFile(Vec), } -impl IntoIterator for FileExtensions { - type Item = String; - type IntoIter = either::Either, std::vec::IntoIter>; +impl<'a> IntoIterator for &'a FileExtensions { + type Item = &'a String; + type IntoIter = either::Either, std::slice::Iter<'a, String>>; fn into_iter(self) -> Self::IntoIter { match self { FileExtensions::SingleFile(glob) => either::Either::Left(std::iter::once(glob)), - FileExtensions::MultipleFile(globs) => either::Either::Right(globs.into_iter()), + FileExtensions::MultipleFile(globs) => either::Either::Right(globs.iter()), } } }