From e58564e6a746cd4580fdc4dc3cf8aa2034424400 Mon Sep 17 00:00:00 2001 From: nokazn <41154684+nokazn@users.noreply.github.com> Date: Sat, 10 Feb 2024 01:54:08 +0900 Subject: [PATCH] fix: glob patterns and add tests --- Cargo.lock | 365 ++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 + src/utils/glob.rs | 228 ++++++++++++++++++++++------ src/utils/mod.rs | 1 + src/utils/tests.rs | 16 ++ src/workspaces.rs | 2 +- 6 files changed, 558 insertions(+), 58 deletions(-) create mode 100644 src/utils/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 64e2015..3bd4735 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,12 +59,30 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "base64ct" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + [[package]] name = "block-buffer" version = "0.10.4" @@ -105,6 +123,19 @@ dependencies = [ "typenum", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "digest" version = "0.10.7" @@ -115,6 +146,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "env_filter" version = "0.1.0" @@ -144,6 +181,99 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -188,18 +318,49 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.20" @@ -212,12 +373,59 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "path-clean" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro2" version = "1.0.78" @@ -236,6 +444,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.10.3" @@ -265,6 +482,19 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -277,6 +507,12 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.195" @@ -321,6 +557,31 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serial_test" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ad9342b3aaca7cb43c45c097dd008d4907070394bd0751a0aa8817e5a018d" +dependencies = [ + "dashmap", + "futures", + "lazy_static", + "log", + "parking_lot", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha2" version = "0.10.8" @@ -332,6 +593,21 @@ dependencies = [ "digest", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + [[package]] name = "strum" version = "0.25.0" @@ -369,17 +645,33 @@ dependencies = [ "base64ct", "env_logger", "glob", + "itertools", "log", + "paste", "path-clean", "serde", "serde_json", "serde_yaml", + "serial_test", "sha2", "strum", "strum_macros", + "tempfile", "thiserror", ] +[[package]] +name = "tempfile" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] + [[package]] name = "thiserror" version = "1.0.56" @@ -436,7 +728,22 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -445,51 +752,93 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index e5669cc..e3357da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,16 @@ edition = "2021" base64ct = { version = "1.6.0", features = ["alloc"] } env_logger = "0.11.1" glob = "0.3.1" +itertools = "0.12.1" log = "0.4.20" +paste = "1.0.14" path-clean = "1.0.1" serde = { version = "1.0.195", features = ["derive"] } serde_json = "1.0.111" serde_yaml = "0.9.31" +serial_test = "3.0.0" sha2 = "0.10.8" strum = "0.25.0" strum_macros = "0.25.3" +tempfile = "3.10.0" thiserror = "1.0.56" diff --git a/src/utils/glob.rs b/src/utils/glob.rs index ee416da..ea0b0a7 100644 --- a/src/utils/glob.rs +++ b/src/utils/glob.rs @@ -1,6 +1,10 @@ use glob::glob; +use itertools::Itertools; +use std::env::set_current_dir; use std::path::PathBuf; +use crate::utils::path::to_absolute_path; + const NEGATE: char = '!'; pub fn collect( @@ -8,22 +12,32 @@ pub fn collect( patterns: Option>, enable_negate: bool, ) -> Vec { - let mut include = Vec::::new(); - let mut exclude = Vec::::new(); + let mut entries = Vec::::new(); for pattern in patterns.unwrap_or_default() { if let (Some(matched), negate) = resolve_glob(&base_dir, pattern, enable_negate) { if negate { - exclude.extend(matched); + entries = entries + .iter() + .filter_map(|entry| { + if matched.iter().any(|p| entry.starts_with(p)) { + None + } else { + Some(entry) + } + }) + .cloned() + .collect::>(); } else { - include.extend(matched); + entries.extend(matched); } } } - include + let result = entries .iter() - .filter(|path| !exclude.contains(path)) - .cloned() - .collect::>() + .unique() + .map(to_absolute_path) + .collect::>(); + result } fn resolve_glob( @@ -31,9 +45,12 @@ fn resolve_glob( pattern: String, enable_negate: bool, ) -> (Option>, bool) { + if let Err(error) = set_current_dir(&base_dir) { + log::warn!("Cannot access to a directory {:?}: {:?}", base_dir, error); + return (None, false); + } let (pattern, negate) = parse_negate(pattern, enable_negate); - let pattern = base_dir.join(pattern); - match glob(&pattern.to_string_lossy().as_ref()) { + match glob(&pattern) { Ok(entries) => { let entries = entries .filter_map(|entry| { @@ -71,46 +88,159 @@ fn parse_negate(pattern: String, enable_negate: bool) -> (String, bool) { #[cfg(test)] mod tests { - #[test] - fn test_parse_negate() { - use super::*; - struct TestCase { - input: (String, bool), - expected: (String, bool), - } + use crate::test_each; - [ - TestCase { - input: (String::from("foo"), true), - expected: (String::from("foo"), false), - }, - TestCase { - input: (String::from("!foo"), true), - expected: (String::from("foo"), true), - }, - TestCase { - input: (String::from("!!foo"), true), - expected: (String::from("foo"), false), - }, - TestCase { - input: (String::from("!!!foo"), true), - expected: (String::from("foo"), true), - }, - TestCase { - input: (String::from("foo!bar"), true), - expected: (String::from("foo!bar"), false), - }, - TestCase { - input: (String::from("foo!!!!!!!!!!bar"), true), - expected: (String::from("foo!!!!!!!!!!bar"), false), - }, - ] - .iter() - .for_each(|case| { - assert_eq!( - parse_negate(case.input.0.clone(), case.input.1), - case.expected - ); + use super::*; + use std::fs::File; + use std::path::PathBuf; + use std::{fs, vec}; + use tempfile::TempDir; + + struct CollectTestCase { + input: (Vec, bool), + file_system: Vec, + expected: Vec, + } + + fn test_collect_each(case: &CollectTestCase) { + let tmp_dir = TempDir::new().unwrap(); + case.file_system.iter().for_each(|path| { + fs::create_dir_all(&tmp_dir.path().join(path.parent().unwrap())).unwrap(); + File::create(&tmp_dir.path().join(path)).unwrap(); }); + + assert_eq!( + collect( + &tmp_dir.as_ref().to_path_buf(), + Some(case.input.clone().0), + case.input.1 + ), + case + .expected + .iter() + .map(|path| tmp_dir.path().join(path).canonicalize().unwrap()) + .collect::>() + ); + tmp_dir.close().unwrap(); } + + test_each! { + test_collect, + 0 => &CollectTestCase { + input: (vec!["foo".to_string()], true), + file_system: vec![PathBuf::from("./foo")], + expected: vec![PathBuf::from("./foo")], + }, + 1 => &CollectTestCase { + input: (vec!["bar".to_string()], true), + file_system: vec![PathBuf::from("./foo")], + expected: vec![], + }, + 2 => &CollectTestCase { + input: (vec!["f*".to_string()], true), + file_system: vec![PathBuf::from("./foo")], + expected: vec![PathBuf::from("./foo")], + }, + 3 => &CollectTestCase { + input: (vec!["*fo*".to_string()], true), + file_system: vec![PathBuf::from("./foo")], + expected: vec![PathBuf::from("./foo")], + }, + 4 => &CollectTestCase { + input: (vec!["**/foo".to_string()], true), + file_system: vec![PathBuf::from("./foo")], + expected: vec![PathBuf::from("./foo")], + }, + 5 => &CollectTestCase { + input: (vec!["**/baz".to_string()], true), + file_system: vec![PathBuf::from("./foo/bar/baz/qux")], + expected: vec![PathBuf::from("./foo/bar/baz/")], + }, + 6 => &CollectTestCase { + input: (vec!["**/bar".to_string()], true), + file_system: vec![PathBuf::from("./foo/bar")], + expected: vec![PathBuf::from("./foo/bar")], + }, + 7 => &CollectTestCase { + input: (vec!["foo".to_string(), "!foo".to_string()], true), + file_system: vec![PathBuf::from("./foo/bar")], + expected: vec![], + }, + 8 => &CollectTestCase { + input: (vec!["!foo".to_string(), "foo".to_string()], true), + file_system: vec![PathBuf::from("./foo/bar")], + expected: vec![PathBuf::from("./foo/")], + }, + 9 => &CollectTestCase { + input: ( + vec!["foo".to_string(), "!foo".to_string(), "bar".to_string()], + true, + ), + file_system: vec![PathBuf::from("./foo"), PathBuf::from("./bar")], + expected: vec![PathBuf::from("./bar")], + }, + 10 => &CollectTestCase { + input: ( + vec!["!foo".to_string(), "foo".to_string(), "bar".to_string()], + true, + ), + file_system: vec![PathBuf::from("./foo"), PathBuf::from("./bar")], + expected: vec![PathBuf::from("./foo"), PathBuf::from("./bar")], + }, + 11 => &CollectTestCase { + input: ( + vec![ + "foo".to_string(), + "!foo".to_string(), + "bar".to_string(), + "!bar".to_string(), + ], + true, + ), + file_system: vec![PathBuf::from("./foo"),PathBuf::from("./bar")], + expected: vec![], + }, + } + + struct ParseNegateTestCase { + input: (String, bool), + expected: (String, bool), + } + + fn test_parse_negate_each(case: &ParseNegateTestCase) { + use super::*; + + assert_eq!( + parse_negate(case.input.0.clone(), case.input.1), + case.expected + ); + } + + test_each!( + test_parse_negate, + 0 => &ParseNegateTestCase { + input: (String::from("foo"), true), + expected: (String::from("foo"), false), + }, + 1 => &ParseNegateTestCase { + input: (String::from("!foo"), true), + expected: (String::from("foo"), true), + }, + 2 => &ParseNegateTestCase { + input: (String::from("!!foo"), true), + expected: (String::from("foo"), false), + }, + 3 => &ParseNegateTestCase { + input: (String::from("!!!foo"), true), + expected: (String::from("foo"), true), + }, + 4 => &ParseNegateTestCase { + input: (String::from("foo!bar"), true), + expected: (String::from("foo!bar"), false), + }, + 5 => &ParseNegateTestCase { + input: (String::from("foo!!!!!!!!!!bar"), true), + expected: (String::from("foo!!!!!!!!!!bar"), false), + }, + ); } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b187645..7e83cd2 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ pub mod glob; pub mod hash; pub mod path; +pub mod tests; diff --git a/src/utils/tests.rs b/src/utils/tests.rs new file mode 100644 index 0000000..b590406 --- /dev/null +++ b/src/utils/tests.rs @@ -0,0 +1,16 @@ +mod tests { + #[macro_export] + macro_rules! test_each { + ($name:ident, $($suffix:expr => $case:expr,)*) => { + paste::item! { + $( + #[test] + #[serial_test::serial] + fn [< $name _ $suffix >]() { + [< $name _each >]($case); + } + )* + } + }; + } +} diff --git a/src/workspaces.rs b/src/workspaces.rs index e65f892..996084f 100644 --- a/src/workspaces.rs +++ b/src/workspaces.rs @@ -45,7 +45,7 @@ impl Workspaces { fn resolve_pnpm_workspaces(base_dir: PathBuf) -> Vec { match PnpmWorkspace::new(&base_dir) { - Ok(p) => utils::glob::collect(&base_dir, p.packages, false), + Ok(p) => utils::glob::collect(&base_dir, p.packages, true), Err(_) => vec![], } }