From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/ignore/.cargo-checksum.json | 2 +- vendor/ignore/Cargo.lock | 161 ++++++++++----- vendor/ignore/Cargo.toml | 46 +++-- vendor/ignore/examples/walk.rs | 28 +-- vendor/ignore/src/default_types.rs | 413 ++++++++++++++++++++----------------- vendor/ignore/src/dir.rs | 128 +++++++----- vendor/ignore/src/gitignore.rs | 107 ++++++---- vendor/ignore/src/lib.rs | 64 +++--- vendor/ignore/src/overrides.rs | 6 +- vendor/ignore/src/pathutil.rs | 24 +-- vendor/ignore/src/types.rs | 55 ++--- vendor/ignore/src/walk.rs | 263 ++++++++++++++--------- 12 files changed, 750 insertions(+), 547 deletions(-) (limited to 'vendor/ignore') diff --git a/vendor/ignore/.cargo-checksum.json b/vendor/ignore/.cargo-checksum.json index a7938c57b..529cb29fb 100644 --- a/vendor/ignore/.cargo-checksum.json +++ b/vendor/ignore/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.lock":"ac7f13d7cdfcd775f3485ee8c33899e64a8e09ed57c2746a0ad53334a4ad905a","Cargo.toml":"8b4f826e98ee5771bdc9a2dc64a9e89d8089ecec11c54498a7af5180722a2e61","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"fad351a4d6dad422368750be404b7a419bc9f6ab5acc86934edb3502fba2029d","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","examples/walk.rs":"efad5c51147fb5020cf2b5d3c23cb8b10dd9f272be37d4c3149f6354fc2ee1f0","src/default_types.rs":"82a964c32a9ad1afe4188cf986bc5e943ab325ad18c2e410c160f3dd13243691","src/dir.rs":"b1216258129e859a0ac9f20018840901bdcec95d82c339052d99167978d42456","src/gitignore.rs":"7e3bc151fbc92e05d4a5913a436c75afd173718974718a49707773e21de8b262","src/lib.rs":"1daba870ede6e78d508d44c8635b894b89dd8f38cb2624eefac18a6e3848100d","src/overrides.rs":"06625e2fb723bb90bdbb867abeaca2fd4293702d29439d9cdb647ed1e22f7dab","src/pathutil.rs":"146b00e5dcb80dd9d9f43b9f42fe5600c3e72a31b47cba8f7ce3f6d2dc877fc1","src/types.rs":"635ed3fad2b8360c8fc12f0b455a154c28642e3acf61457d40dd689b62359643","src/walk.rs":"e0129a6559446d0d4949948b2b19d643de8bdf4a836f07618bc9da9c72cb9c12","tests/gitignore_matched_path_or_any_parents_tests.gitignore":"3895c935f76a57928cc12284dfff406693b7666c0ffce9b8676c6c1976debe2d","tests/gitignore_matched_path_or_any_parents_tests.rs":"715fa13a13c1bec0731c14dbb0b81f12d74b2c021e110474e4cbc76fd13af7f2"},"package":"dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"} \ No newline at end of file +{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.lock":"16a4513da0165c40dc75e159d3a87c0c7bc6d42916d2be98dcbd89cb20c00cc9","Cargo.toml":"b627db2b0588425d7d0ec477f7ebcfa1d369f1afdf2c48b0f7cf5d30d2783418","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"fad351a4d6dad422368750be404b7a419bc9f6ab5acc86934edb3502fba2029d","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","examples/walk.rs":"9facef1184ed0cbdf503bc7131195b3c8fc75d4323d2d81537163239077f20d6","src/default_types.rs":"a4e4a74a3e274e34d1d6e0108957b5c4c11688aaa4d1de4d699695f3412c1a7b","src/dir.rs":"7d1f6d68df762cbf8c3307493f2dc6234196c26bd2e4eedb5c92555738138225","src/gitignore.rs":"193533dee85bc968d823abca30b684e916f274b18f0f510a52f9b9e0a21095d3","src/lib.rs":"0b5b9252d82a6d6af8aec39dcddab13c44660a46e2f517ab0d29549a284a8764","src/overrides.rs":"93ed90a3e0d47a7c195af684692372a76a37e11bb66eca018488d752d3df463b","src/pathutil.rs":"d0fb48f0ff1d2e0ff0462bf7b8ee80f7133f2fffaac299bef966b821ee42f442","src/types.rs":"298b659d48466893d754a4d4fd66ea0183569313629f52af9431d583e0cdbabc","src/walk.rs":"a7af07d3f3f774d1cfb6f3adc0d7e52b28c292404119824d870e93d5e04da3e1","tests/gitignore_matched_path_or_any_parents_tests.gitignore":"3895c935f76a57928cc12284dfff406693b7666c0ffce9b8676c6c1976debe2d","tests/gitignore_matched_path_or_any_parents_tests.rs":"715fa13a13c1bec0731c14dbb0b81f12d74b2c021e110474e4cbc76fd13af7f2"},"package":"747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060"} \ No newline at end of file diff --git a/vendor/ignore/Cargo.lock b/vendor/ignore/Cargo.lock index c64e5168e..801b87b42 100644 --- a/vendor/ignore/Cargo.lock +++ b/vendor/ignore/Cargo.lock @@ -4,18 +4,24 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] -name = "bstr" +name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bstr" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -29,90 +35,120 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", ] [[package]] -name = "crossbeam-utils" -version = "0.8.14" +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ + "autocfg", "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "crossbeam-utils" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] [[package]] name = "globset" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata", + "regex-syntax", ] [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.21" dependencies = [ + "bstr", "crossbeam-channel", + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata", "same-file", - "thread_local", "walkdir", "winapi-util", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "log" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] -name = "log" -version = "0.4.17" +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memoffset" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ - "cfg-if", + "autocfg", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "proc-macro2" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] [[package]] -name = "once_cell" -version = "1.17.0" +name = "quote" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] [[package]] -name = "regex" -version = "1.7.0" +name = "regex-automata" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -121,9 +157,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "same-file" @@ -134,29 +170,56 @@ dependencies = [ "winapi-util", ] +[[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.152" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "thread_local" -version = "1.1.4" +name = "syn" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ - "once_cell", + "proc-macro2", + "quote", + "unicode-ident", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "walkdir" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", - "winapi", "winapi-util", ] @@ -178,9 +241,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] diff --git a/vendor/ignore/Cargo.toml b/vendor/ignore/Cargo.toml index b397dcf8d..60ab32a56 100644 --- a/vendor/ignore/Cargo.toml +++ b/vendor/ignore/Cargo.toml @@ -10,9 +10,9 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" name = "ignore" -version = "0.4.20" +version = "0.4.21" authors = ["Andrew Gallant "] description = """ A fast library for efficiently matching ignore files such as `.gitignore` @@ -35,35 +35,47 @@ repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore" name = "ignore" bench = false -[dependencies.globset] -version = "0.4.10" +[dependencies.crossbeam-deque] +version = "0.8.3" -[dependencies.lazy_static] -version = "1.1" +[dependencies.globset] +version = "0.4.14" [dependencies.log] -version = "0.4.5" +version = "0.4.20" [dependencies.memchr] -version = "2.1" +version = "2.6.3" -[dependencies.regex] -version = "1.1" +[dependencies.regex-automata] +version = "0.4.0" +features = [ + "std", + "perf", + "syntax", + "meta", + "nfa", + "hybrid", + "dfa-onepass", +] +default-features = false [dependencies.same-file] -version = "1.0.4" - -[dependencies.thread_local] -version = "1" +version = "1.0.6" [dependencies.walkdir] -version = "2.2.7" +version = "2.4.0" + +[dev-dependencies.bstr] +version = "1.6.2" +features = ["std"] +default-features = false [dev-dependencies.crossbeam-channel] -version = "0.5.0" +version = "0.5.8" [features] -simd-accel = ["globset/simd-accel"] +simd-accel = [] [target."cfg(windows)".dependencies.winapi-util] version = "0.1.2" diff --git a/vendor/ignore/examples/walk.rs b/vendor/ignore/examples/walk.rs index e064478c5..5bbd10f2b 100644 --- a/vendor/ignore/examples/walk.rs +++ b/vendor/ignore/examples/walk.rs @@ -1,10 +1,6 @@ -use std::env; -use std::io::{self, Write}; -use std::path::Path; -use std::thread; +use std::{env, io::Write, path::Path}; -use ignore::WalkBuilder; -use walkdir::WalkDir; +use {bstr::ByteVec, ignore::WalkBuilder, walkdir::WalkDir}; fn main() { let mut path = env::args().nth(1).unwrap(); @@ -19,10 +15,11 @@ fn main() { simple = true; } - let stdout_thread = thread::spawn(move || { - let mut stdout = io::BufWriter::new(io::stdout()); + let stdout_thread = std::thread::spawn(move || { + let mut stdout = std::io::BufWriter::new(std::io::stdout()); for dent in rx { - write_path(&mut stdout, dent.path()); + stdout.write(&*Vec::from_path_lossy(dent.path())).unwrap(); + stdout.write(b"\n").unwrap(); } }); @@ -65,16 +62,3 @@ impl DirEntry { } } } - -#[cfg(unix)] -fn write_path(mut wtr: W, path: &Path) { - use std::os::unix::ffi::OsStrExt; - wtr.write(path.as_os_str().as_bytes()).unwrap(); - wtr.write(b"\n").unwrap(); -} - -#[cfg(not(unix))] -fn write_path(mut wtr: W, path: &Path) { - wtr.write(path.to_string_lossy().as_bytes()).unwrap(); - wtr.write(b"\n").unwrap(); -} diff --git a/vendor/ignore/src/default_types.rs b/vendor/ignore/src/default_types.rs index e6a3a8f37..af71fe8e9 100644 --- a/vendor/ignore/src/default_types.rs +++ b/vendor/ignore/src/default_types.rs @@ -9,104 +9,117 @@ /// Please try to keep this list sorted lexicographically and wrapped to 79 /// columns (inclusive). #[rustfmt::skip] -pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ - ("agda", &["*.agda", "*.lagda"]), - ("aidl", &["*.aidl"]), - ("amake", &["*.mk", "*.bp"]), - ("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]), - ("asm", &["*.asm", "*.s", "*.S"]), - ("asp", &[ +pub(crate) const DEFAULT_TYPES: &[(&[&str], &[&str])] = &[ + (&["ada"], &["*.adb", "*.ads"]), + (&["agda"], &["*.agda", "*.lagda"]), + (&["aidl"], &["*.aidl"]), + (&["alire"], &["alire.toml"]), + (&["amake"], &["*.mk", "*.bp"]), + (&["asciidoc"], &["*.adoc", "*.asc", "*.asciidoc"]), + (&["asm"], &["*.asm", "*.s", "*.S"]), + (&["asp"], &[ "*.aspx", "*.aspx.cs", "*.aspx.vb", "*.ascx", "*.ascx.cs", "*.ascx.vb", "*.asp" ]), - ("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]), - ("avro", &["*.avdl", "*.avpr", "*.avsc"]), - ("awk", &["*.awk"]), - ("bazel", &[ + (&["ats"], &["*.ats", "*.dats", "*.sats", "*.hats"]), + (&["avro"], &["*.avdl", "*.avpr", "*.avsc"]), + (&["awk"], &["*.awk"]), + (&["bat", "batch"], &["*.bat"]), + (&["bazel"], &[ "*.bazel", "*.bzl", "*.BUILD", "*.bazelrc", "BUILD", "MODULE.bazel", "WORKSPACE", "WORKSPACE.bazel", ]), - ("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]), - ("brotli", &["*.br"]), - ("buildstream", &["*.bst"]), - ("bzip2", &["*.bz2", "*.tbz2"]), - ("c", &["*.[chH]", "*.[chH].in", "*.cats"]), - ("cabal", &["*.cabal"]), - ("candid", &["*.did"]), - ("carp", &["*.carp"]), - ("cbor", &["*.cbor"]), - ("ceylon", &["*.ceylon"]), - ("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]), - ("cmake", &["*.cmake", "CMakeLists.txt"]), - ("coffeescript", &["*.coffee"]), - ("config", &["*.cfg", "*.conf", "*.config", "*.ini"]), - ("coq", &["*.v"]), - ("cpp", &[ + (&["bitbake"], &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]), + (&["brotli"], &["*.br"]), + (&["buildstream"], &["*.bst"]), + (&["bzip2"], &["*.bz2", "*.tbz2"]), + (&["c"], &["*.[chH]", "*.[chH].in", "*.cats"]), + (&["cabal"], &["*.cabal"]), + (&["candid"], &["*.did"]), + (&["carp"], &["*.carp"]), + (&["cbor"], &["*.cbor"]), + (&["ceylon"], &["*.ceylon"]), + (&["clojure"], &["*.clj", "*.cljc", "*.cljs", "*.cljx"]), + (&["cmake"], &["*.cmake", "CMakeLists.txt"]), + (&["cmd"], &["*.bat", "*.cmd"]), + (&["cml"], &["*.cml"]), + (&["coffeescript"], &["*.coffee"]), + (&["config"], &["*.cfg", "*.conf", "*.config", "*.ini"]), + (&["coq"], &["*.v"]), + (&["cpp"], &[ "*.[ChH]", "*.cc", "*.[ch]pp", "*.[ch]xx", "*.hh", "*.inl", "*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in", ]), - ("creole", &["*.creole"]), - ("crystal", &["Projectfile", "*.cr", "*.ecr", "shard.yml"]), - ("cs", &["*.cs"]), - ("csharp", &["*.cs"]), - ("cshtml", &["*.cshtml"]), - ("css", &["*.css", "*.scss"]), - ("csv", &["*.csv"]), - ("cuda", &["*.cu", "*.cuh"]), - ("cython", &["*.pyx", "*.pxi", "*.pxd"]), - ("d", &["*.d"]), - ("dart", &["*.dart"]), - ("devicetree", &["*.dts", "*.dtsi"]), - ("dhall", &["*.dhall"]), - ("diff", &["*.patch", "*.diff"]), - ("docker", &["*Dockerfile*"]), - ("dts", &["*.dts", "*.dtsi"]), - ("dvc", &["Dvcfile", "*.dvc"]), - ("ebuild", &["*.ebuild"]), - ("edn", &["*.edn"]), - ("elisp", &["*.el"]), - ("elixir", &["*.ex", "*.eex", "*.exs"]), - ("elm", &["*.elm"]), - ("erb", &["*.erb"]), - ("erlang", &["*.erl", "*.hrl"]), - ("fennel", &["*.fnl"]), - ("fidl", &["*.fidl"]), - ("fish", &["*.fish"]), - ("flatbuffers", &["*.fbs"]), - ("fortran", &[ + (&["creole"], &["*.creole"]), + (&["crystal"], &["Projectfile", "*.cr", "*.ecr", "shard.yml"]), + (&["cs"], &["*.cs"]), + (&["csharp"], &["*.cs"]), + (&["cshtml"], &["*.cshtml"]), + (&["csproj"], &["*.csproj"]), + (&["css"], &["*.css", "*.scss"]), + (&["csv"], &["*.csv"]), + (&["cuda"], &["*.cu", "*.cuh"]), + (&["cython"], &["*.pyx", "*.pxi", "*.pxd"]), + (&["d"], &["*.d"]), + (&["dart"], &["*.dart"]), + (&["devicetree"], &["*.dts", "*.dtsi"]), + (&["dhall"], &["*.dhall"]), + (&["diff"], &["*.patch", "*.diff"]), + (&["dita"], &["*.dita", "*.ditamap", "*.ditaval"]), + (&["docker"], &["*Dockerfile*"]), + (&["dockercompose"], &["docker-compose.yml", "docker-compose.*.yml"]), + (&["dts"], &["*.dts", "*.dtsi"]), + (&["dvc"], &["Dvcfile", "*.dvc"]), + (&["ebuild"], &["*.ebuild", "*.eclass"]), + (&["edn"], &["*.edn"]), + (&["elisp"], &["*.el"]), + (&["elixir"], &["*.ex", "*.eex", "*.exs", "*.heex", "*.leex", "*.livemd"]), + (&["elm"], &["*.elm"]), + (&["erb"], &["*.erb"]), + (&["erlang"], &["*.erl", "*.hrl"]), + (&["fennel"], &["*.fnl"]), + (&["fidl"], &["*.fidl"]), + (&["fish"], &["*.fish"]), + (&["flatbuffers"], &["*.fbs"]), + (&["fortran"], &[ "*.f", "*.F", "*.f77", "*.F77", "*.pfo", "*.f90", "*.F90", "*.f95", "*.F95", ]), - ("fsharp", &["*.fs", "*.fsx", "*.fsi"]), - ("fut", &["*.fut"]), - ("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]), - ("gn", &["*.gn", "*.gni"]), - ("go", &["*.go"]), - ("gradle", &["*.gradle"]), - ("groovy", &["*.groovy", "*.gradle"]), - ("gzip", &["*.gz", "*.tgz"]), - ("h", &["*.h", "*.hh", "*.hpp"]), - ("haml", &["*.haml"]), - ("hare", &["*.ha"]), - ("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]), - ("hbs", &["*.hbs"]), - ("hs", &["*.hs", "*.lhs"]), - ("html", &["*.htm", "*.html", "*.ejs"]), - ("hy", &["*.hy"]), - ("idris", &["*.idr", "*.lidr"]), - ("janet", &["*.janet"]), - ("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]), - ("jinja", &["*.j2", "*.jinja", "*.jinja2"]), - ("jl", &["*.jl"]), - ("js", &["*.js", "*.jsx", "*.vue", "*.cjs", "*.mjs"]), - ("json", &["*.json", "composer.lock"]), - ("jsonl", &["*.jsonl"]), - ("julia", &["*.jl"]), - ("jupyter", &["*.ipynb", "*.jpynb"]), - ("k", &["*.k"]), - ("kotlin", &["*.kt", "*.kts"]), - ("less", &["*.less"]), - ("license", &[ + (&["fsharp"], &["*.fs", "*.fsx", "*.fsi"]), + (&["fut"], &["*.fut"]), + (&["gap"], &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]), + (&["gn"], &["*.gn", "*.gni"]), + (&["go"], &["*.go"]), + (&["gprbuild"], &["*.gpr"]), + (&["gradle"], &[ + "*.gradle", "*.gradle.kts", "gradle.properties", "gradle-wrapper.*", + "gradlew", "gradlew.bat", + ]), + (&["graphql"], &["*.graphql", "*.graphqls"]), + (&["groovy"], &["*.groovy", "*.gradle"]), + (&["gzip"], &["*.gz", "*.tgz"]), + (&["h"], &["*.h", "*.hh", "*.hpp"]), + (&["haml"], &["*.haml"]), + (&["hare"], &["*.ha"]), + (&["haskell"], &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]), + (&["hbs"], &["*.hbs"]), + (&["hs"], &["*.hs", "*.lhs"]), + (&["html"], &["*.htm", "*.html", "*.ejs"]), + (&["hy"], &["*.hy"]), + (&["idris"], &["*.idr", "*.lidr"]), + (&["janet"], &["*.janet"]), + (&["java"], &["*.java", "*.jsp", "*.jspx", "*.properties"]), + (&["jinja"], &["*.j2", "*.jinja", "*.jinja2"]), + (&["jl"], &["*.jl"]), + (&["js"], &["*.js", "*.jsx", "*.vue", "*.cjs", "*.mjs"]), + (&["json"], &["*.json", "composer.lock", "*.sarif"]), + (&["jsonl"], &["*.jsonl"]), + (&["julia"], &["*.jl"]), + (&["jupyter"], &["*.ipynb", "*.jpynb"]), + (&["k"], &["*.k"]), + (&["kotlin"], &["*.kt", "*.kts"]), + (&["less"], &["*.less"]), + (&["license"], &[ // General "COPYING", "COPYING[.-]*", "COPYRIGHT", "COPYRIGHT[.-]*", @@ -133,79 +146,92 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ "MPL-*[0-9]*", "OFL-*[0-9]*", ]), - ("lilypond", &["*.ly", "*.ily"]), - ("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]), - ("lock", &["*.lock", "package-lock.json"]), - ("log", &["*.log"]), - ("lua", &["*.lua"]), - ("lz4", &["*.lz4"]), - ("lzma", &["*.lzma"]), - ("m4", &["*.ac", "*.m4"]), - ("make", &[ + (&["lilypond"], &["*.ly", "*.ily"]), + (&["lisp"], &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]), + (&["lock"], &["*.lock", "package-lock.json"]), + (&["log"], &["*.log"]), + (&["lua"], &["*.lua"]), + (&["lz4"], &["*.lz4"]), + (&["lzma"], &["*.lzma"]), + (&["m4"], &["*.ac", "*.m4"]), + (&["make"], &[ "[Gg][Nn][Uu]makefile", "[Mm]akefile", "[Gg][Nn][Uu]makefile.am", "[Mm]akefile.am", "[Gg][Nn][Uu]makefile.in", "[Mm]akefile.in", "*.mk", "*.mak" ]), - ("mako", &["*.mako", "*.mao"]), - ("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]), - ("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]), - ("matlab", &["*.m"]), - ("md", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]), - ("meson", &["meson.build", "meson_options.txt"]), - ("minified", &["*.min.html", "*.min.css", "*.min.js"]), - ("mint", &["*.mint"]), - ("mk", &["mkfile"]), - ("ml", &["*.ml"]), - ("motoko", &["*.mo"]), - ("msbuild", &[ + (&["mako"], &["*.mako", "*.mao"]), + (&["man"], &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]), + (&["markdown", "md"], &[ + "*.markdown", + "*.md", + "*.mdown", + "*.mdwn", + "*.mkd", + "*.mkdn", + "*.mdx", + ]), + (&["matlab"], &["*.m"]), + (&["meson"], &["meson.build", "meson_options.txt"]), + (&["minified"], &["*.min.html", "*.min.css", "*.min.js"]), + (&["mint"], &["*.mint"]), + (&["mk"], &["mkfile"]), + (&["ml"], &["*.ml"]), + (&["motoko"], &["*.mo"]), + (&["msbuild"], &[ "*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets", + "*.sln", ]), - ("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]), - ("nix", &["*.nix"]), - ("objc", &["*.h", "*.m"]), - ("objcpp", &["*.h", "*.mm"]), - ("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]), - ("org", &["*.org", "*.org_archive"]), - ("pants", &["BUILD"]), - ("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]), - ("pdf", &["*.pdf"]), - ("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]), - ("php", &[ + (&["nim"], &["*.nim", "*.nimf", "*.nimble", "*.nims"]), + (&["nix"], &["*.nix"]), + (&["objc"], &["*.h", "*.m"]), + (&["objcpp"], &["*.h", "*.mm"]), + (&["ocaml"], &["*.ml", "*.mli", "*.mll", "*.mly"]), + (&["org"], &["*.org", "*.org_archive"]), + (&["pants"], &["BUILD"]), + (&["pascal"], &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]), + (&["pdf"], &["*.pdf"]), + (&["perl"], &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]), + (&["php"], &[ // note that PHP 6 doesn't exist // See: https://wiki.php.net/rfc/php6 "*.php", "*.php3", "*.php4", "*.php5", "*.php7", "*.php8", "*.pht", "*.phtml" ]), - ("po", &["*.po"]), - ("pod", &["*.pod"]), - ("postscript", &["*.eps", "*.ps"]), - ("protobuf", &["*.proto"]), - ("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]), - ("puppet", &["*.epp", "*.erb", "*.pp", "*.rb"]), - ("purs", &["*.purs"]), - ("py", &["*.py"]), - ("qmake", &["*.pro", "*.pri", "*.prf"]), - ("qml", &["*.qml"]), - ("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]), - ("racket", &["*.rkt"]), - ("rdoc", &["*.rdoc"]), - ("readme", &["README*", "*README"]), - ("reasonml", &["*.re", "*.rei"]), - ("red", &["*.r", "*.red", "*.reds"]), - ("rescript", &["*.res", "*.resi"]), - ("robot", &["*.robot"]), - ("rst", &["*.rst"]), - ("ruby", &[ + (&["po"], &["*.po"]), + (&["pod"], &["*.pod"]), + (&["postscript"], &["*.eps", "*.ps"]), + (&["prolog"], &["*.pl", "*.pro", "*.prolog", "*.P"]), + (&["protobuf"], &["*.proto"]), + (&["ps"], &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]), + (&["puppet"], &["*.epp", "*.erb", "*.pp", "*.rb"]), + (&["purs"], &["*.purs"]), + (&["py", "python"], &["*.py", "*.pyi"]), + (&["qmake"], &["*.pro", "*.pri", "*.prf"]), + (&["qml"], &["*.qml"]), + (&["r"], &["*.R", "*.r", "*.Rmd", "*.Rnw"]), + (&["racket"], &["*.rkt"]), + (&["raku"], &[ + "*.raku", "*.rakumod", "*.rakudoc", "*.rakutest", + "*.p6", "*.pl6", "*.pm6" + ]), + (&["rdoc"], &["*.rdoc"]), + (&["readme"], &["README*", "*README"]), + (&["reasonml"], &["*.re", "*.rei"]), + (&["red"], &["*.r", "*.red", "*.reds"]), + (&["rescript"], &["*.res", "*.resi"]), + (&["robot"], &["*.robot"]), + (&["rst"], &["*.rst"]), + (&["ruby"], &[ // Idiomatic files "config.ru", "Gemfile", ".irbrc", "Rakefile", // Extensions "*.gemspec", "*.rb", "*.rbw" ]), - ("rust", &["*.rs"]), - ("sass", &["*.sass", "*.scss"]), - ("scala", &["*.scala", "*.sbt"]), - ("sh", &[ + (&["rust"], &["*.rs"]), + (&["sass"], &["*.sass", "*.scss"]), + (&["scala"], &["*.scala", "*.sbt"]), + (&["sh"], &[ // Portable/misc. init files ".login", ".logout", ".profile", "profile", // bash-specific init files @@ -228,60 +254,66 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ // Extensions "*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh", "*.zsh", ]), - ("slim", &["*.skim", "*.slim", "*.slime"]), - ("smarty", &["*.tpl"]), - ("sml", &["*.sml", "*.sig"]), - ("solidity", &["*.sol"]), - ("soy", &["*.soy"]), - ("spark", &["*.spark"]), - ("spec", &["*.spec"]), - ("sql", &["*.sql", "*.psql"]), - ("stylus", &["*.styl"]), - ("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]), - ("svg", &["*.svg"]), - ("swift", &["*.swift"]), - ("swig", &["*.def", "*.i"]), - ("systemd", &[ + (&["slim"], &["*.skim", "*.slim", "*.slime"]), + (&["smarty"], &["*.tpl"]), + (&["sml"], &["*.sml", "*.sig"]), + (&["solidity"], &["*.sol"]), + (&["soy"], &["*.soy"]), + (&["spark"], &["*.spark"]), + (&["spec"], &["*.spec"]), + (&["sql"], &["*.sql", "*.psql"]), + (&["stylus"], &["*.styl"]), + (&["sv"], &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]), + (&["svg"], &["*.svg"]), + (&["swift"], &["*.swift"]), + (&["swig"], &["*.def", "*.i"]), + (&["systemd"], &[ "*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path", "*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target", "*.timer", ]), - ("taskpaper", &["*.taskpaper"]), - ("tcl", &["*.tcl"]), - ("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]), - ("texinfo", &["*.texi"]), - ("textile", &["*.textile"]), - ("tf", &["*.tf"]), - ("thrift", &["*.thrift"]), - ("toml", &["*.toml", "Cargo.lock"]), - ("ts", &["*.ts", "*.tsx", "*.cts", "*.mts"]), - ("twig", &["*.twig"]), - ("txt", &["*.txt"]), - ("typoscript", &["*.typoscript", "*.ts"]), - ("vala", &["*.vala"]), - ("vb", &["*.vb"]), - ("vcl", &["*.vcl"]), - ("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]), - ("vhdl", &["*.vhd", "*.vhdl"]), - ("vim", &[ + (&["taskpaper"], &["*.taskpaper"]), + (&["tcl"], &["*.tcl"]), + (&["tex"], &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]), + (&["texinfo"], &["*.texi"]), + (&["textile"], &["*.textile"]), + (&["tf"], &[ + "*.tf", "*.auto.tfvars", "terraform.tfvars", "*.tf.json", + "*.auto.tfvars.json", "terraform.tfvars.json", "*.terraformrc", + "terraform.rc", "*.tfrc", "*.terraform.lock.hcl", + ]), + (&["thrift"], &["*.thrift"]), + (&["toml"], &["*.toml", "Cargo.lock"]), + (&["ts", "typescript"], &["*.ts", "*.tsx", "*.cts", "*.mts"]), + (&["twig"], &["*.twig"]), + (&["txt"], &["*.txt"]), + (&["typoscript"], &["*.typoscript", "*.ts"]), + (&["usd"], &["*.usd", "*.usda", "*.usdc"]), + (&["v"], &["*.v", "*.vsh"]), + (&["vala"], &["*.vala"]), + (&["vb"], &["*.vb"]), + (&["vcl"], &["*.vcl"]), + (&["verilog"], &["*.v", "*.vh", "*.sv", "*.svh"]), + (&["vhdl"], &["*.vhd", "*.vhdl"]), + (&["vim"], &[ "*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc", ]), - ("vimscript", &[ + (&["vimscript"], &[ "*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc", ]), - ("webidl", &["*.idl", "*.webidl", "*.widl"]), - ("wiki", &["*.mediawiki", "*.wiki"]), - ("xml", &[ + (&["webidl"], &["*.idl", "*.webidl", "*.widl"]), + (&["wiki"], &["*.mediawiki", "*.wiki"]), + (&["xml"], &[ "*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb", "*.rng", "*.sch", "*.xhtml", ]), - ("xz", &["*.xz", "*.txz"]), - ("yacc", &["*.y"]), - ("yaml", &["*.yaml", "*.yml"]), - ("yang", &["*.yang"]), - ("z", &["*.Z"]), - ("zig", &["*.zig"]), - ("zsh", &[ + (&["xz"], &["*.xz", "*.txz"]), + (&["yacc"], &["*.y"]), + (&["yaml"], &["*.yaml", "*.yml"]), + (&["yang"], &["*.yang"]), + (&["z"], &["*.Z"]), + (&["zig"], &["*.zig"]), + (&["zsh"], &[ ".zshenv", "zshenv", ".zlogin", "zlogin", ".zlogout", "zlogout", @@ -289,7 +321,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ".zshrc", "zshrc", "*.zsh", ]), - ("zstd", &["*.zst", "*.zstd"]), + (&["zstd"], &["*.zst", "*.zstd"]), ]; #[cfg(test)] @@ -298,10 +330,10 @@ mod tests { #[test] fn default_types_are_sorted() { - let mut names = DEFAULT_TYPES.iter().map(|(name, _exts)| name); - - let Some(mut previous_name) = names.next() else { return; }; - + let mut names = DEFAULT_TYPES.iter().map(|(aliases, _)| aliases[0]); + let Some(mut previous_name) = names.next() else { + return; + }; for name in names { assert!( name > previous_name, @@ -309,7 +341,6 @@ mod tests { name, previous_name ); - previous_name = name; } } diff --git a/vendor/ignore/src/dir.rs b/vendor/ignore/src/dir.rs index 2577665d5..51fc813e1 100644 --- a/vendor/ignore/src/dir.rs +++ b/vendor/ignore/src/dir.rs @@ -13,24 +13,28 @@ // with non-obvious failure modes. Alas, such things haven't been documented // well. -use std::collections::HashMap; -use std::ffi::{OsStr, OsString}; -use std::fs::{File, FileType}; -use std::io::{self, BufRead}; -use std::path::{Path, PathBuf}; -use std::sync::{Arc, RwLock}; - -use crate::gitignore::{self, Gitignore, GitignoreBuilder}; -use crate::overrides::{self, Override}; -use crate::pathutil::{is_hidden, strip_prefix}; -use crate::types::{self, Types}; -use crate::walk::DirEntry; -use crate::{Error, Match, PartialErrorBuilder}; +use std::{ + collections::HashMap, + ffi::{OsStr, OsString}, + fs::{File, FileType}, + io::{self, BufRead}, + path::{Path, PathBuf}, + sync::{Arc, RwLock}, +}; + +use crate::{ + gitignore::{self, Gitignore, GitignoreBuilder}, + overrides::{self, Override}, + pathutil::{is_hidden, strip_prefix}, + types::{self, Types}, + walk::DirEntry, + {Error, Match, PartialErrorBuilder}, +}; /// IgnoreMatch represents information about where a match came from when using /// the `Ignore` matcher. #[derive(Clone, Debug)] -pub struct IgnoreMatch<'a>(IgnoreMatchInner<'a>); +pub(crate) struct IgnoreMatch<'a>(IgnoreMatchInner<'a>); /// IgnoreMatchInner describes precisely where the match information came from. /// This is private to allow expansion to more matchers in the future. @@ -85,7 +89,7 @@ struct IgnoreOptions { /// Ignore is a matcher useful for recursively walking one or more directories. #[derive(Clone, Debug)] -pub struct Ignore(Arc); +pub(crate) struct Ignore(Arc); #[derive(Clone, Debug)] struct IgnoreInner { @@ -134,22 +138,22 @@ struct IgnoreInner { impl Ignore { /// Return the directory path of this matcher. - pub fn path(&self) -> &Path { + pub(crate) fn path(&self) -> &Path { &self.0.dir } /// Return true if this matcher has no parent. - pub fn is_root(&self) -> bool { + pub(crate) fn is_root(&self) -> bool { self.0.parent.is_none() } /// Returns true if this matcher was added via the `add_parents` method. - pub fn is_absolute_parent(&self) -> bool { + pub(crate) fn is_absolute_parent(&self) -> bool { self.0.is_absolute_parent } /// Return this matcher's parent, if one exists. - pub fn parent(&self) -> Option { + pub(crate) fn parent(&self) -> Option { self.0.parent.clone() } @@ -157,7 +161,7 @@ impl Ignore { /// /// Note that this can only be called on an `Ignore` matcher with no /// parents (i.e., `is_root` returns `true`). This will panic otherwise. - pub fn add_parents>( + pub(crate) fn add_parents>( &self, path: P, ) -> (Ignore, Option) { @@ -222,7 +226,7 @@ impl Ignore { /// returned if it exists. /// /// Note that all I/O errors are completely ignored. - pub fn add_child>( + pub(crate) fn add_child>( &self, dir: P, ) -> (Ignore, Option) { @@ -335,7 +339,7 @@ impl Ignore { } /// Like `matched`, but works with a directory entry instead. - pub fn matched_dir_entry<'a>( + pub(crate) fn matched_dir_entry<'a>( &'a self, dent: &DirEntry, ) -> Match> { @@ -442,7 +446,29 @@ impl Ignore { } if self.0.opts.parents { if let Some(abs_parent_path) = self.absolute_base() { - let path = abs_parent_path.join(path); + // What we want to do here is take the absolute base path of + // this directory and join it with the path we're searching. + // The main issue we want to avoid is accidentally duplicating + // directory components, so we try to strip any common prefix + // off of `path`. Overall, this seems a little ham-fisted, but + // it does fix a nasty bug. It should do fine until we overhaul + // this crate. + let dirpath = self.0.dir.as_path(); + let path_prefix = match strip_prefix("./", dirpath) { + None => dirpath, + Some(stripped_dot_slash) => stripped_dot_slash, + }; + let path = match strip_prefix(path_prefix, path) { + None => abs_parent_path.join(path), + Some(p) => { + let p = match strip_prefix("/", p) { + None => p, + Some(p) => p, + }; + abs_parent_path.join(p) + } + }; + for ig in self.parents().skip_while(|ig| !ig.0.is_absolute_parent) { @@ -498,7 +524,7 @@ impl Ignore { } /// Returns an iterator over parent ignore matchers, including this one. - pub fn parents(&self) -> Parents<'_> { + pub(crate) fn parents(&self) -> Parents<'_> { Parents(Some(self)) } @@ -512,7 +538,7 @@ impl Ignore { /// An iterator over all parents of an ignore matcher, including itself. /// /// The lifetime `'a` refers to the lifetime of the initial `Ignore` matcher. -pub struct Parents<'a>(Option<&'a Ignore>); +pub(crate) struct Parents<'a>(Option<&'a Ignore>); impl<'a> Iterator for Parents<'a> { type Item = &'a Ignore; @@ -530,7 +556,7 @@ impl<'a> Iterator for Parents<'a> { /// A builder for creating an Ignore matcher. #[derive(Clone, Debug)] -pub struct IgnoreBuilder { +pub(crate) struct IgnoreBuilder { /// The root directory path for this ignore matcher. dir: PathBuf, /// An override matcher (default is empty). @@ -550,7 +576,7 @@ impl IgnoreBuilder { /// /// All relative file paths are resolved with respect to the current /// working directory. - pub fn new() -> IgnoreBuilder { + pub(crate) fn new() -> IgnoreBuilder { IgnoreBuilder { dir: Path::new("").to_path_buf(), overrides: Arc::new(Override::empty()), @@ -574,7 +600,7 @@ impl IgnoreBuilder { /// /// The matcher returned won't match anything until ignore rules from /// directories are added to it. - pub fn build(&self) -> Ignore { + pub(crate) fn build(&self) -> Ignore { let git_global_matcher = if !self.opts.git_global { Gitignore::empty() } else { @@ -616,7 +642,10 @@ impl IgnoreBuilder { /// By default, no override matcher is used. /// /// This overrides any previous setting. - pub fn overrides(&mut self, overrides: Override) -> &mut IgnoreBuilder { + pub(crate) fn overrides( + &mut self, + overrides: Override, + ) -> &mut IgnoreBuilder { self.overrides = Arc::new(overrides); self } @@ -626,13 +655,13 @@ impl IgnoreBuilder { /// By default, no file type matcher is used. /// /// This overrides any previous setting. - pub fn types(&mut self, types: Types) -> &mut IgnoreBuilder { + pub(crate) fn types(&mut self, types: Types) -> &mut IgnoreBuilder { self.types = Arc::new(types); self } /// Adds a new global ignore matcher from the ignore file path given. - pub fn add_ignore(&mut self, ig: Gitignore) -> &mut IgnoreBuilder { + pub(crate) fn add_ignore(&mut self, ig: Gitignore) -> &mut IgnoreBuilder { self.explicit_ignores.push(ig); self } @@ -643,7 +672,7 @@ impl IgnoreBuilder { /// /// When specifying multiple names, earlier names have lower precedence than /// later names. - pub fn add_custom_ignore_filename>( + pub(crate) fn add_custom_ignore_filename>( &mut self, file_name: S, ) -> &mut IgnoreBuilder { @@ -654,7 +683,7 @@ impl IgnoreBuilder { /// Enables ignoring hidden files. /// /// This is enabled by default. - pub fn hidden(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn hidden(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.hidden = yes; self } @@ -665,7 +694,7 @@ impl IgnoreBuilder { /// supported by search tools such as ripgrep and The Silver Searcher. /// /// This is enabled by default. - pub fn ignore(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn ignore(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.ignore = yes; self } @@ -676,7 +705,7 @@ impl IgnoreBuilder { /// file path given are respected. Otherwise, they are ignored. /// /// This is enabled by default. - pub fn parents(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn parents(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.parents = yes; self } @@ -689,7 +718,7 @@ impl IgnoreBuilder { /// This overwrites any previous global gitignore setting. /// /// This is enabled by default. - pub fn git_global(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn git_global(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.git_global = yes; self } @@ -700,7 +729,7 @@ impl IgnoreBuilder { /// man page. /// /// This is enabled by default. - pub fn git_ignore(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn git_ignore(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.git_ignore = yes; self } @@ -711,7 +740,7 @@ impl IgnoreBuilder { /// `gitignore` man page. /// /// This is enabled by default. - pub fn git_exclude(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn git_exclude(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.git_exclude = yes; self } @@ -721,7 +750,7 @@ impl IgnoreBuilder { /// /// When disabled, git-related ignore rules are applied even when searching /// outside a git repository. - pub fn require_git(&mut self, yes: bool) -> &mut IgnoreBuilder { + pub(crate) fn require_git(&mut self, yes: bool) -> &mut IgnoreBuilder { self.opts.require_git = yes; self } @@ -729,7 +758,7 @@ impl IgnoreBuilder { /// Process ignore files case insensitively /// /// This is disabled by default. - pub fn ignore_case_insensitive( + pub(crate) fn ignore_case_insensitive( &mut self, yes: bool, ) -> &mut IgnoreBuilder { @@ -746,7 +775,7 @@ impl IgnoreBuilder { /// precedence than later names). /// /// I/O errors are ignored. -pub fn create_gitignore>( +pub(crate) fn create_gitignore>( dir: &Path, dir_for_ignorefile: &Path, names: &[T], @@ -839,22 +868,19 @@ fn resolve_git_commondir( #[cfg(test)] mod tests { - use std::fs::{self, File}; - use std::io::Write; - use std::path::Path; + use std::{io::Write, path::Path}; - use crate::dir::IgnoreBuilder; - use crate::gitignore::Gitignore; - use crate::tests::TempDir; - use crate::Error; + use crate::{ + dir::IgnoreBuilder, gitignore::Gitignore, tests::TempDir, Error, + }; fn wfile>(path: P, contents: &str) { - let mut file = File::create(path).unwrap(); + let mut file = std::fs::File::create(path).unwrap(); file.write_all(contents.as_bytes()).unwrap(); } fn mkdirp>(path: P) { - fs::create_dir_all(path).unwrap(); + std::fs::create_dir_all(path).unwrap(); } fn partial(err: Error) -> Vec { @@ -1171,7 +1197,7 @@ mod tests { assert!(ignore.matched("ignore_me", false).is_ignore()); // missing commondir file - assert!(fs::remove_file(commondir_path()).is_ok()); + assert!(std::fs::remove_file(commondir_path()).is_ok()); let (_, err) = ib.add_child(td.path().join("linked-worktree")); // We squash the error in this case, because it occurs in repositories // that are not linked worktrees but have submodules. diff --git a/vendor/ignore/src/gitignore.rs b/vendor/ignore/src/gitignore.rs index 3c7ba5e6b..0b667f264 100644 --- a/vendor/ignore/src/gitignore.rs +++ b/vendor/ignore/src/gitignore.rs @@ -7,20 +7,22 @@ Note that this module implements the specification as described in the the `git` command line tool. */ -use std::cell::RefCell; -use std::env; -use std::fs::File; -use std::io::{self, BufRead, Read}; -use std::path::{Path, PathBuf}; -use std::str; -use std::sync::Arc; - -use globset::{Candidate, GlobBuilder, GlobSet, GlobSetBuilder}; -use regex::bytes::Regex; -use thread_local::ThreadLocal; - -use crate::pathutil::{is_file_name, strip_prefix}; -use crate::{Error, Match, PartialErrorBuilder}; +use std::{ + fs::File, + io::{BufRead, BufReader, Read}, + path::{Path, PathBuf}, + sync::Arc, +}; + +use { + globset::{Candidate, GlobBuilder, GlobSet, GlobSetBuilder}, + regex_automata::util::pool::Pool, +}; + +use crate::{ + pathutil::{is_file_name, strip_prefix}, + Error, Match, PartialErrorBuilder, +}; /// Glob represents a single glob in a gitignore file. /// @@ -82,7 +84,7 @@ pub struct Gitignore { globs: Vec, num_ignores: u64, num_whitelists: u64, - matches: Option>>>>, + matches: Option>>>, } impl Gitignore { @@ -249,8 +251,7 @@ impl Gitignore { return Match::None; } let path = path.as_ref(); - let _matches = self.matches.as_ref().unwrap().get_or_default(); - let mut matches = _matches.borrow_mut(); + let mut matches = self.matches.as_ref().unwrap().get(); let candidate = Candidate::new(path); self.set.matches_candidate_into(&candidate, &mut *matches); for &i in matches.iter().rev() { @@ -337,12 +338,12 @@ impl GitignoreBuilder { .build() .map_err(|err| Error::Glob { glob: None, err: err.to_string() })?; Ok(Gitignore { - set: set, + set, root: self.root.clone(), globs: self.globs.clone(), num_ignores: nignore as u64, num_whitelists: nwhite as u64, - matches: Some(Arc::new(ThreadLocal::default())), + matches: Some(Arc::new(Pool::new(|| vec![]))), }) } @@ -389,7 +390,7 @@ impl GitignoreBuilder { Err(err) => return Some(Error::Io(err).with_path(path)), Ok(file) => file, }; - let rdr = io::BufReader::new(file); + let rdr = BufReader::new(file); let mut errs = PartialErrorBuilder::default(); for (i, line) in rdr.lines().enumerate() { let lineno = (i + 1) as u64; @@ -448,7 +449,7 @@ impl GitignoreBuilder { return Ok(self); } let mut glob = Glob { - from: from, + from, original: line.to_string(), actual: String::new(), is_whitelist: false, @@ -533,7 +534,7 @@ impl GitignoreBuilder { /// Return the file path of the current environment's global gitignore file. /// /// Note that the file path returned may not exist. -fn gitconfig_excludes_path() -> Option { +pub fn gitconfig_excludes_path() -> Option { // git supports $HOME/.gitconfig and $XDG_CONFIG_HOME/git/config. Notably, // both can be active at the same time, where $HOME/.gitconfig takes // precedent. So if $HOME/.gitconfig defines a `core.excludesFile`, then @@ -558,7 +559,7 @@ fn gitconfig_home_contents() -> Option> { }; let mut file = match File::open(home.join(".gitconfig")) { Err(_) => return None, - Ok(file) => io::BufReader::new(file), + Ok(file) => BufReader::new(file), }; let mut contents = vec![]; file.read_to_end(&mut contents).ok().map(|_| contents) @@ -567,13 +568,13 @@ fn gitconfig_home_contents() -> Option> { /// Returns the file contents of git's global config file, if one exists, in /// the user's XDG_CONFIG_HOME directory. fn gitconfig_xdg_contents() -> Option> { - let path = env::var_os("XDG_CONFIG_HOME") + let path = std::env::var_os("XDG_CONFIG_HOME") .and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) }) .or_else(|| home_dir().map(|p| p.join(".config"))) .map(|x| x.join("git/config")); let mut file = match path.and_then(|p| File::open(p).ok()) { None => return None, - Some(file) => io::BufReader::new(file), + Some(file) => BufReader::new(file), }; let mut contents = vec![]; file.read_to_end(&mut contents).ok().map(|_| contents) @@ -583,7 +584,7 @@ fn gitconfig_xdg_contents() -> Option> { /// /// Specifically, this respects XDG_CONFIG_HOME. fn excludes_file_default() -> Option { - env::var_os("XDG_CONFIG_HOME") + std::env::var_os("XDG_CONFIG_HOME") .and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) }) .or_else(|| home_dir().map(|p| p.join(".config"))) .map(|x| x.join("git/ignore")) @@ -592,18 +593,28 @@ fn excludes_file_default() -> Option { /// Extract git's `core.excludesfile` config setting from the raw file contents /// given. fn parse_excludes_file(data: &[u8]) -> Option { + use std::sync::OnceLock; + + use regex_automata::{meta::Regex, util::syntax}; + // N.B. This is the lazy approach, and isn't technically correct, but // probably works in more circumstances. I guess we would ideally have // a full INI parser. Yuck. - lazy_static::lazy_static! { - static ref RE: Regex = - Regex::new(r"(?im)^\s*excludesfile\s*=\s*(.+)\s*$").unwrap(); - }; - let caps = match RE.captures(data) { - None => return None, - Some(caps) => caps, - }; - str::from_utf8(&caps[1]).ok().map(|s| PathBuf::from(expand_tilde(s))) + static RE: OnceLock = OnceLock::new(); + let re = RE.get_or_init(|| { + Regex::builder() + .configure(Regex::config().utf8_empty(false)) + .syntax(syntax::Config::new().utf8(false)) + .build(r#"(?im-u)^\s*excludesfile\s*=\s*"?\s*(\S+?)\s*"?\s*$"#) + .unwrap() + }); + // We don't care about amortizing allocs here I think. This should only + // be called ~once per traversal or so? (Although it's not guaranteed...) + let mut caps = re.create_captures(); + re.captures(data, &mut caps); + let span = caps.get_group(1)?; + let candidate = &data[span]; + std::str::from_utf8(candidate).ok().map(|s| PathBuf::from(expand_tilde(s))) } /// Expands ~ in file paths to the value of $HOME. @@ -617,18 +628,18 @@ fn expand_tilde(path: &str) -> String { /// Returns the location of the user's home directory. fn home_dir() -> Option { - // We're fine with using env::home_dir for now. Its bugs are, IMO, pretty - // minor corner cases. We should still probably eventually migrate to - // the `dirs` crate to get a proper implementation. + // We're fine with using std::env::home_dir for now. Its bugs are, IMO, + // pretty minor corner cases. #![allow(deprecated)] - env::home_dir() + std::env::home_dir() } #[cfg(test)] mod tests { - use super::{Gitignore, GitignoreBuilder}; use std::path::Path; + use super::{Gitignore, GitignoreBuilder}; + fn gi_from_str>(root: P, s: &str) -> Gitignore { let mut builder = GitignoreBuilder::new(root); builder.add_str(None, s).unwrap(); @@ -761,6 +772,22 @@ mod tests { assert!(super::parse_excludes_file(&data).is_none()); } + #[test] + fn parse_excludes_file4() { + let data = bytes("[core]\nexcludesFile = \"~/foo/bar\""); + let got = super::parse_excludes_file(&data); + assert_eq!( + path_string(got.unwrap()), + super::expand_tilde("~/foo/bar") + ); + } + + #[test] + fn parse_excludes_file5() { + let data = bytes("[core]\nexcludesFile = \" \"~/foo/bar \" \""); + assert!(super::parse_excludes_file(&data).is_none()); + } + // See: https://github.com/BurntSushi/ripgrep/issues/106 #[test] fn regression_106() { diff --git a/vendor/ignore/src/lib.rs b/vendor/ignore/src/lib.rs index 824f7c4dc..a5d5ca30b 100644 --- a/vendor/ignore/src/lib.rs +++ b/vendor/ignore/src/lib.rs @@ -46,9 +46,6 @@ See the documentation for `WalkBuilder` for many other options. #![deny(missing_docs)] -use std::error; -use std::fmt; -use std::io; use std::path::{Path, PathBuf}; pub use crate::walk::{ @@ -101,7 +98,7 @@ pub enum Error { child: PathBuf, }, /// An error that occurs when doing I/O, such as reading an ignore file. - Io(io::Error), + Io(std::io::Error), /// An error that occurs when trying to parse a glob. Glob { /// The original glob that caused this error. This glob, when @@ -125,21 +122,23 @@ impl Clone for Error { match *self { Error::Partial(ref errs) => Error::Partial(errs.clone()), Error::WithLineNumber { line, ref err } => { - Error::WithLineNumber { line: line, err: err.clone() } + Error::WithLineNumber { line, err: err.clone() } } Error::WithPath { ref path, ref err } => { Error::WithPath { path: path.clone(), err: err.clone() } } Error::WithDepth { depth, ref err } => { - Error::WithDepth { depth: depth, err: err.clone() } + Error::WithDepth { depth, err: err.clone() } } Error::Loop { ref ancestor, ref child } => Error::Loop { ancestor: ancestor.clone(), child: child.clone(), }, Error::Io(ref err) => match err.raw_os_error() { - Some(e) => Error::Io(io::Error::from_raw_os_error(e)), - None => Error::Io(io::Error::new(err.kind(), err.to_string())), + Some(e) => Error::Io(std::io::Error::from_raw_os_error(e)), + None => { + Error::Io(std::io::Error::new(err.kind(), err.to_string())) + } }, Error::Glob { ref glob, ref err } => { Error::Glob { glob: glob.clone(), err: err.clone() } @@ -183,22 +182,22 @@ impl Error { } } - /// Inspect the original [`io::Error`] if there is one. + /// Inspect the original [`std::io::Error`] if there is one. /// /// [`None`] is returned if the [`Error`] doesn't correspond to an - /// [`io::Error`]. This might happen, for example, when the error was + /// [`std::io::Error`]. This might happen, for example, when the error was /// produced because a cycle was found in the directory tree while /// following symbolic links. /// /// This method returns a borrowed value that is bound to the lifetime of the [`Error`]. To /// obtain an owned value, the [`into_io_error`] can be used instead. /// - /// > This is the original [`io::Error`] and is _not_ the same as - /// > [`impl From for std::io::Error`][impl] which contains additional context about the - /// error. + /// > This is the original [`std::io::Error`] and is _not_ the same as + /// > [`impl From for std::io::Error`][impl] which contains + /// > additional context about the error. /// /// [`None`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#variant.None - /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html + /// [`std::io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html /// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html /// [`Error`]: struct.Error.html /// [`into_io_error`]: struct.Error.html#method.into_io_error @@ -224,10 +223,10 @@ impl Error { } /// Similar to [`io_error`] except consumes self to convert to the original - /// [`io::Error`] if one exists. + /// [`std::io::Error`] if one exists. /// /// [`io_error`]: struct.Error.html#method.io_error - /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html + /// [`std::io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html pub fn into_io_error(self) -> Option { match self { Error::Partial(mut errs) => { @@ -268,7 +267,7 @@ impl Error { /// Turn an error into a tagged error with the given depth. fn with_depth(self, depth: usize) -> Error { - Error::WithDepth { depth: depth, err: Box::new(self) } + Error::WithDepth { depth, err: Box::new(self) } } /// Turn an error into a tagged error with the given file path and line @@ -287,7 +286,7 @@ impl Error { let depth = err.depth(); if let (Some(anc), Some(child)) = (err.loop_ancestor(), err.path()) { return Error::WithDepth { - depth: depth, + depth, err: Box::new(Error::Loop { ancestor: anc.to_path_buf(), child: child.to_path_buf(), @@ -295,15 +294,15 @@ impl Error { }; } let path = err.path().map(|p| p.to_path_buf()); - let mut ig_err = Error::Io(io::Error::from(err)); + let mut ig_err = Error::Io(std::io::Error::from(err)); if let Some(path) = path { - ig_err = Error::WithPath { path: path, err: Box::new(ig_err) }; + ig_err = Error::WithPath { path, err: Box::new(ig_err) }; } ig_err } } -impl error::Error for Error { +impl std::error::Error for Error { #[allow(deprecated)] fn description(&self) -> &str { match *self { @@ -320,8 +319,8 @@ impl error::Error for Error { } } -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { Error::Partial(ref errs) => { let msgs: Vec = @@ -359,8 +358,8 @@ impl fmt::Display for Error { } } -impl From for Error { - fn from(err: io::Error) -> Error { +impl From for Error { + fn from(err: std::io::Error) -> Error { Error::Io(err) } } @@ -488,19 +487,18 @@ impl Match { #[cfg(test)] mod tests { - use std::env; - use std::error; - use std::fs; - use std::path::{Path, PathBuf}; - use std::result; + use std::{ + env, fs, + path::{Path, PathBuf}, + }; /// A convenient result type alias. - pub type Result = - result::Result>; + pub(crate) type Result = + std::result::Result>; macro_rules! err { ($($tt:tt)*) => { - Box::::from(format!($($tt)*)) + Box::::from(format!($($tt)*)) } } diff --git a/vendor/ignore/src/overrides.rs b/vendor/ignore/src/overrides.rs index e96b8e0b6..fd8af95d7 100644 --- a/vendor/ignore/src/overrides.rs +++ b/vendor/ignore/src/overrides.rs @@ -6,8 +6,10 @@ line tools. use std::path::Path; -use crate::gitignore::{self, Gitignore, GitignoreBuilder}; -use crate::{Error, Match}; +use crate::{ + gitignore::{self, Gitignore, GitignoreBuilder}, + Error, Match, +}; /// Glob represents a single glob in an override matcher. /// diff --git a/vendor/ignore/src/pathutil.rs b/vendor/ignore/src/pathutil.rs index f21b4f5ab..1e2e812c4 100644 --- a/vendor/ignore/src/pathutil.rs +++ b/vendor/ignore/src/pathutil.rs @@ -1,5 +1,4 @@ -use std::ffi::OsStr; -use std::path::Path; +use std::{ffi::OsStr, path::Path}; use crate::walk::DirEntry; @@ -9,7 +8,7 @@ use crate::walk::DirEntry; /// /// On Unix, this implements a more optimized check. #[cfg(unix)] -pub fn is_hidden(dent: &DirEntry) -> bool { +pub(crate) fn is_hidden(dent: &DirEntry) -> bool { use std::os::unix::ffi::OsStrExt; if let Some(name) = file_name(dent.path()) { @@ -26,7 +25,7 @@ pub fn is_hidden(dent: &DirEntry) -> bool { /// * The base name of the path starts with a `.`. /// * The file attributes have the `HIDDEN` property set. #[cfg(windows)] -pub fn is_hidden(dent: &DirEntry) -> bool { +pub(crate) fn is_hidden(dent: &DirEntry) -> bool { use std::os::windows::fs::MetadataExt; use winapi_util::file; @@ -49,7 +48,7 @@ pub fn is_hidden(dent: &DirEntry) -> bool { /// /// This only returns true if the base name of the path starts with a `.`. #[cfg(not(any(unix, windows)))] -pub fn is_hidden(dent: &DirEntry) -> bool { +pub(crate) fn is_hidden(dent: &DirEntry) -> bool { if let Some(name) = file_name(dent.path()) { name.to_str().map(|s| s.starts_with(".")).unwrap_or(false) } else { @@ -61,7 +60,7 @@ pub fn is_hidden(dent: &DirEntry) -> bool { /// /// If `path` doesn't have a prefix `prefix`, then return `None`. #[cfg(unix)] -pub fn strip_prefix<'a, P: AsRef + ?Sized>( +pub(crate) fn strip_prefix<'a, P: AsRef + ?Sized>( prefix: &'a P, path: &'a Path, ) -> Option<&'a Path> { @@ -80,7 +79,7 @@ pub fn strip_prefix<'a, P: AsRef + ?Sized>( /// /// If `path` doesn't have a prefix `prefix`, then return `None`. #[cfg(not(unix))] -pub fn strip_prefix<'a, P: AsRef + ?Sized>( +pub(crate) fn strip_prefix<'a, P: AsRef + ?Sized>( prefix: &'a P, path: &'a Path, ) -> Option<&'a Path> { @@ -90,10 +89,11 @@ pub fn strip_prefix<'a, P: AsRef + ?Sized>( /// Returns true if this file path is just a file name. i.e., Its parent is /// the empty string. #[cfg(unix)] -pub fn is_file_name>(path: P) -> bool { - use memchr::memchr; +pub(crate) fn is_file_name>(path: P) -> bool { use std::os::unix::ffi::OsStrExt; + use memchr::memchr; + let path = path.as_ref().as_os_str().as_bytes(); memchr(b'/', path).is_none() } @@ -101,7 +101,7 @@ pub fn is_file_name>(path: P) -> bool { /// Returns true if this file path is just a file name. i.e., Its parent is /// the empty string. #[cfg(not(unix))] -pub fn is_file_name>(path: P) -> bool { +pub(crate) fn is_file_name>(path: P) -> bool { path.as_ref().parent().map(|p| p.as_os_str().is_empty()).unwrap_or(false) } @@ -110,7 +110,7 @@ pub fn is_file_name>(path: P) -> bool { /// If the path terminates in ., .., or consists solely of a root of prefix, /// file_name will return None. #[cfg(unix)] -pub fn file_name<'a, P: AsRef + ?Sized>( +pub(crate) fn file_name<'a, P: AsRef + ?Sized>( path: &'a P, ) -> Option<&'a OsStr> { use memchr::memrchr; @@ -135,7 +135,7 @@ pub fn file_name<'a, P: AsRef + ?Sized>( /// If the path terminates in ., .., or consists solely of a root of prefix, /// file_name will return None. #[cfg(not(unix))] -pub fn file_name<'a, P: AsRef + ?Sized>( +pub(crate) fn file_name<'a, P: AsRef + ?Sized>( path: &'a P, ) -> Option<&'a OsStr> { path.as_ref().file_name() diff --git a/vendor/ignore/src/types.rs b/vendor/ignore/src/types.rs index 616a8d217..308b784d4 100644 --- a/vendor/ignore/src/types.rs +++ b/vendor/ignore/src/types.rs @@ -84,18 +84,14 @@ assert!(matcher.matched("y.cpp", false).is_whitelist()); ``` */ -use std::cell::RefCell; -use std::collections::HashMap; -use std::path::Path; -use std::sync::Arc; +use std::{collections::HashMap, path::Path, sync::Arc}; -use globset::{GlobBuilder, GlobSet, GlobSetBuilder}; -use regex::Regex; -use thread_local::ThreadLocal; +use { + globset::{GlobBuilder, GlobSet, GlobSetBuilder}, + regex_automata::util::pool::Pool, +}; -use crate::default_types::DEFAULT_TYPES; -use crate::pathutil::file_name; -use crate::{Error, Match}; +use crate::{default_types::DEFAULT_TYPES, pathutil::file_name, Error, Match}; /// Glob represents a single glob in a set of file type definitions. /// @@ -181,7 +177,7 @@ pub struct Types { /// The set of all glob selections, used for actual matching. set: GlobSet, /// Temporary storage for globs that match. - matches: Arc>>>, + matches: Arc>>, } /// Indicates the type of a selection for a particular file type. @@ -235,7 +231,7 @@ impl Types { has_selected: false, glob_to_selection: vec![], set: GlobSetBuilder::new().build().unwrap(), - matches: Arc::new(ThreadLocal::default()), + matches: Arc::new(Pool::new(|| vec![])), } } @@ -283,7 +279,7 @@ impl Types { return Match::None; } }; - let mut matches = self.matches.get_or_default().borrow_mut(); + let mut matches = self.matches.get(); self.set.matches_into(name, &mut *matches); // The highest precedent match is the last one. if let Some(&i) = matches.last() { @@ -356,12 +352,12 @@ impl TypesBuilder { .build() .map_err(|err| Error::Glob { glob: None, err: err.to_string() })?; Ok(Types { - defs: defs, - selections: selections, - has_selected: has_selected, - glob_to_selection: glob_to_selection, - set: set, - matches: Arc::new(ThreadLocal::default()), + defs, + selections, + has_selected, + glob_to_selection, + set, + matches: Arc::new(Pool::new(|| vec![])), }) } @@ -419,10 +415,7 @@ impl TypesBuilder { /// If `name` is `all` or otherwise contains any character that is not a /// Unicode letter or number, then an error is returned. pub fn add(&mut self, name: &str, glob: &str) -> Result<(), Error> { - lazy_static::lazy_static! { - static ref RE: Regex = Regex::new(r"^[\pL\pN]+$").unwrap(); - }; - if name == "all" || !RE.is_match(name) { + if name == "all" || !name.chars().all(|c| c.is_alphanumeric()) { return Err(Error::InvalidDefinition); } let (key, glob) = (name.to_string(), glob.to_string()); @@ -488,9 +481,11 @@ impl TypesBuilder { /// Add a set of default file type definitions. pub fn add_defaults(&mut self) -> &mut TypesBuilder { static MSG: &'static str = "adding a default type should never fail"; - for &(name, exts) in DEFAULT_TYPES { - for ext in exts { - self.add(name, ext).expect(MSG); + for &(names, exts) in DEFAULT_TYPES { + for name in names { + for ext in exts { + self.add(name, ext).expect(MSG); + } } } self @@ -537,6 +532,8 @@ mod tests { "html:*.htm", "rust:*.rs", "js:*.js", + "py:*.py", + "python:*.py", "foo:*.{rs,foo}", "combo:include:html,rust", ] @@ -551,6 +548,8 @@ mod tests { matched!(match7, types(), vec!["foo"], vec!["rust"], "main.foo"); matched!(match8, types(), vec!["combo"], vec![], "index.html"); matched!(match9, types(), vec!["combo"], vec![], "lib.rs"); + matched!(match10, types(), vec!["py"], vec![], "main.py"); + matched!(match11, types(), vec!["python"], vec![], "main.py"); matched!(not, matchnot1, types(), vec!["rust"], vec![], "index.html"); matched!(not, matchnot2, types(), vec![], vec!["rust"], "main.rs"); @@ -558,6 +557,8 @@ mod tests { matched!(not, matchnot4, types(), vec!["rust"], vec!["foo"], "main.rs"); matched!(not, matchnot5, types(), vec!["rust"], vec!["foo"], "main.foo"); matched!(not, matchnot6, types(), vec!["combo"], vec![], "leftpad.js"); + matched!(not, matchnot7, types(), vec!["py"], vec![], "index.html"); + matched!(not, matchnot8, types(), vec!["python"], vec![], "doc.md"); #[test] fn test_invalid_defs() { @@ -569,7 +570,7 @@ mod tests { let original_defs = btypes.definitions(); let bad_defs = vec![ // Reference to type that does not exist - "combo:include:html,python", + "combo:include:html,qwerty", // Bad format "combo:foobar:html,rust", "", diff --git a/vendor/ignore/src/walk.rs b/vendor/ignore/src/walk.rs index 602faaec3..2288fe0bd 100644 --- a/vendor/ignore/src/walk.rs +++ b/vendor/ignore/src/walk.rs @@ -1,23 +1,26 @@ -use std::cmp; -use std::ffi::OsStr; -use std::fmt; -use std::fs::{self, FileType, Metadata}; -use std::io; -use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; -use std::vec; - -use same_file::Handle; -use walkdir::{self, WalkDir}; - -use crate::dir::{Ignore, IgnoreBuilder}; -use crate::gitignore::GitignoreBuilder; -use crate::overrides::Override; -use crate::types::Types; -use crate::{Error, PartialErrorBuilder}; +use std::{ + cmp::Ordering, + ffi::OsStr, + fs::{self, FileType, Metadata}, + io, + path::{Path, PathBuf}, + sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering}, + sync::Arc, +}; + +use { + crossbeam_deque::{Stealer, Worker as Deque}, + same_file::Handle, + walkdir::{self, WalkDir}, +}; + +use crate::{ + dir::{Ignore, IgnoreBuilder}, + gitignore::GitignoreBuilder, + overrides::Override, + types::Types, + Error, PartialErrorBuilder, +}; /// A directory entry with a possible error attached. /// @@ -36,9 +39,7 @@ impl DirEntry { } /// The full path that this entry represents. - /// Analogous to [`path`], but moves ownership of the path. - /// - /// [`path`]: struct.DirEntry.html#method.path + /// Analogous to [`DirEntry::path`], but moves ownership of the path. pub fn into_path(self) -> PathBuf { self.dent.into_path() } @@ -107,11 +108,11 @@ impl DirEntry { } fn new_walkdir(dent: walkdir::DirEntry, err: Option) -> DirEntry { - DirEntry { dent: DirEntryInner::Walkdir(dent), err: err } + DirEntry { dent: DirEntryInner::Walkdir(dent), err } } fn new_raw(dent: DirEntryRaw, err: Option) -> DirEntry { - DirEntry { dent: DirEntryInner::Raw(dent), err: err } + DirEntry { dent: DirEntryInner::Raw(dent), err } } } @@ -251,8 +252,8 @@ struct DirEntryRaw { metadata: fs::Metadata, } -impl fmt::Debug for DirEntryRaw { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl std::fmt::Debug for DirEntryRaw { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Leaving out FileType because it doesn't have a debug impl // in Rust 1.9. We could add it if we really wanted to by manually // querying each possibly file type. Meh. ---AG @@ -324,7 +325,7 @@ impl DirEntryRaw { ) -> Result { let ty = ent.file_type().map_err(|err| { let err = Error::Io(io::Error::from(err)).with_path(ent.path()); - Error::WithDepth { depth: depth, err: Box::new(err) } + Error::WithDepth { depth, err: Box::new(err) } })?; DirEntryRaw::from_entry_os(depth, ent, ty) } @@ -337,13 +338,13 @@ impl DirEntryRaw { ) -> Result { let md = ent.metadata().map_err(|err| { let err = Error::Io(io::Error::from(err)).with_path(ent.path()); - Error::WithDepth { depth: depth, err: Box::new(err) } + Error::WithDepth { depth, err: Box::new(err) } })?; Ok(DirEntryRaw { path: ent.path(), - ty: ty, + ty, follow_link: false, - depth: depth, + depth, metadata: md, }) } @@ -358,9 +359,9 @@ impl DirEntryRaw { Ok(DirEntryRaw { path: ent.path(), - ty: ty, + ty, follow_link: false, - depth: depth, + depth, ino: ent.ino(), }) } @@ -391,7 +392,7 @@ impl DirEntryRaw { path: pb, ty: md.file_type(), follow_link: link, - depth: depth, + depth, metadata: md, }) } @@ -410,7 +411,7 @@ impl DirEntryRaw { path: pb, ty: md.file_type(), follow_link: link, - depth: depth, + depth, ino: md.ino(), }) } @@ -494,17 +495,15 @@ pub struct WalkBuilder { #[derive(Clone)] enum Sorter { - ByName( - Arc cmp::Ordering + Send + Sync + 'static>, - ), - ByPath(Arc cmp::Ordering + Send + Sync + 'static>), + ByName(Arc Ordering + Send + Sync + 'static>), + ByPath(Arc Ordering + Send + Sync + 'static>), } #[derive(Clone)] struct Filter(Arc bool + Send + Sync + 'static>); -impl fmt::Debug for WalkBuilder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl std::fmt::Debug for WalkBuilder { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("WalkBuilder") .field("paths", &self.paths) .field("ig_builder", &self.ig_builder) @@ -578,7 +577,7 @@ impl WalkBuilder { .into_iter(); let ig_root = self.ig_builder.build(); Walk { - its: its, + its, it: None, ig_root: ig_root.clone(), ig: ig_root.clone(), @@ -828,7 +827,7 @@ impl WalkBuilder { /// Note that this is not used in the parallel iterator. pub fn sort_by_file_path(&mut self, cmp: F) -> &mut WalkBuilder where - F: Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static, + F: Fn(&Path, &Path) -> Ordering + Send + Sync + 'static, { self.sorter = Some(Sorter::ByPath(Arc::new(cmp))); self @@ -847,7 +846,7 @@ impl WalkBuilder { /// Note that this is not used in the parallel iterator. pub fn sort_by_file_name(&mut self, cmp: F) -> &mut WalkBuilder where - F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static, + F: Fn(&OsStr, &OsStr) -> Ordering + Send + Sync + 'static, { self.sorter = Some(Sorter::ByName(Arc::new(cmp))); self @@ -911,7 +910,7 @@ impl WalkBuilder { /// ignore files like `.gitignore` are respected. The precise matching rules /// and precedence is explained in the documentation for `WalkBuilder`. pub struct Walk { - its: vec::IntoIter<(PathBuf, Option)>, + its: std::vec::IntoIter<(PathBuf, Option)>, it: Option, ig_root: Ignore, ig: Ignore, @@ -1040,6 +1039,8 @@ impl Iterator for Walk { } } +impl std::iter::FusedIterator for Walk {} + /// WalkEventIter transforms a WalkDir iterator into an iterator that more /// accurately describes the directory tree. Namely, it emits events that are /// one of three types: directory, file or "exit." An "exit" event means that @@ -1123,10 +1124,10 @@ impl WalkState { } } -/// A builder for constructing a visitor when using -/// [`WalkParallel::visit`](struct.WalkParallel.html#method.visit). The builder -/// will be called for each thread started by `WalkParallel`. The visitor -/// returned from each builder is then called for every directory entry. +/// A builder for constructing a visitor when using [`WalkParallel::visit`]. +/// The builder will be called for each thread started by `WalkParallel`. The +/// visitor returned from each builder is then called for every directory +/// entry. pub trait ParallelVisitorBuilder<'s> { /// Create per-thread `ParallelVisitor`s for `WalkParallel`. fn build(&mut self) -> Box; @@ -1143,9 +1144,8 @@ impl<'a, 's, P: ParallelVisitorBuilder<'s>> ParallelVisitorBuilder<'s> /// Receives files and directories for the current thread. /// /// Setup for the traversal can be implemented as part of -/// [`ParallelVisitorBuilder::build`](trait.ParallelVisitorBuilder.html#tymethod.build). -/// Teardown when traversal finishes can be implemented by implementing the -/// `Drop` trait on your traversal type. +/// [`ParallelVisitorBuilder::build`]. Teardown when traversal finishes can be +/// implemented by implementing the `Drop` trait on your traversal type. pub trait ParallelVisitor: Send { /// Receives files and directories for the current thread. This is called /// once for every directory entry visited by traversal. @@ -1187,7 +1187,7 @@ impl<'s> ParallelVisitor for FnVisitorImp<'s> { /// /// Unlike `Walk`, this uses multiple threads for traversing a directory. pub struct WalkParallel { - paths: vec::IntoIter, + paths: std::vec::IntoIter, ig_root: Ignore, max_filesize: Option, max_depth: Option, @@ -1228,9 +1228,8 @@ impl WalkParallel { /// can be merged together into a single data structure. pub fn visit(mut self, builder: &mut dyn ParallelVisitorBuilder<'_>) { let threads = self.threads(); - let stack = Arc::new(Mutex::new(vec![])); + let mut stack = vec![]; { - let mut stack = stack.lock().unwrap(); let mut visitor = builder.build(); let mut paths = Vec::new().into_iter(); std::mem::swap(&mut paths, &mut self.paths); @@ -1268,9 +1267,9 @@ impl WalkParallel { } }; stack.push(Message::Work(Work { - dent: dent, + dent, ignore: self.ig_root.clone(), - root_device: root_device, + root_device, })); } // ... but there's no need to start workers if we don't need them. @@ -1280,24 +1279,24 @@ impl WalkParallel { } // Create the workers and then wait for them to finish. let quit_now = Arc::new(AtomicBool::new(false)); - let num_pending = - Arc::new(AtomicUsize::new(stack.lock().unwrap().len())); + let active_workers = Arc::new(AtomicUsize::new(threads)); + let stacks = Stack::new_for_each_thread(threads, stack); std::thread::scope(|s| { - let mut handles = vec![]; - for _ in 0..threads { - let worker = Worker { + let handles: Vec<_> = stacks + .into_iter() + .map(|stack| Worker { visitor: builder.build(), - stack: stack.clone(), + stack, quit_now: quit_now.clone(), - num_pending: num_pending.clone(), + active_workers: active_workers.clone(), max_depth: self.max_depth, max_filesize: self.max_filesize, follow_links: self.follow_links, skip: self.skip.clone(), filter: self.filter.clone(), - }; - handles.push(s.spawn(|| worker.run())); - } + }) + .map(|worker| s.spawn(|| worker.run())) + .collect(); for handle in handles { handle.join().unwrap(); } @@ -1387,6 +1386,73 @@ impl Work { } } +/// A work-stealing stack. +#[derive(Debug)] +struct Stack { + /// This thread's index. + index: usize, + /// The thread-local stack. + deque: Deque, + /// The work stealers. + stealers: Arc<[Stealer]>, +} + +impl Stack { + /// Create a work-stealing stack for each thread. The given messages + /// correspond to the initial paths to start the search at. They will + /// be distributed automatically to each stack in a round-robin fashion. + fn new_for_each_thread(threads: usize, init: Vec) -> Vec { + // Using new_lifo() ensures each worker operates depth-first, not + // breadth-first. We do depth-first because a breadth first traversal + // on wide directories with a lot of gitignores is disastrous (for + // example, searching a directory tree containing all of crates.io). + let deques: Vec> = + std::iter::repeat_with(Deque::new_lifo).take(threads).collect(); + let stealers = Arc::<[Stealer]>::from( + deques.iter().map(Deque::stealer).collect::>(), + ); + let stacks: Vec = deques + .into_iter() + .enumerate() + .map(|(index, deque)| Stack { + index, + deque, + stealers: stealers.clone(), + }) + .collect(); + // Distribute the initial messages. + init.into_iter() + .zip(stacks.iter().cycle()) + .for_each(|(m, s)| s.push(m)); + stacks + } + + /// Push a message. + fn push(&self, msg: Message) { + self.deque.push(msg); + } + + /// Pop a message. + fn pop(&self) -> Option { + self.deque.pop().or_else(|| self.steal()) + } + + /// Steal a message from another queue. + fn steal(&self) -> Option { + // For fairness, try to steal from index + 1, index + 2, ... len - 1, + // then wrap around to 0, 1, ... index - 1. + let (left, right) = self.stealers.split_at(self.index); + // Don't steal from ourselves + let right = &right[1..]; + + right + .iter() + .chain(left.iter()) + .map(|s| s.steal_batch_and_pop(&self.deque)) + .find_map(|s| s.success()) + } +} + /// A worker is responsible for descending into directories, updating the /// ignore matchers, producing new work and invoking the caller's callback. /// @@ -1394,19 +1460,19 @@ impl Work { struct Worker<'s> { /// The caller's callback. visitor: Box, - /// A stack of work to do. + /// A work-stealing stack of work to do. /// /// We use a stack instead of a channel because a stack lets us visit /// directories in depth first order. This can substantially reduce peak - /// memory usage by keeping both the number of files path and gitignore + /// memory usage by keeping both the number of file paths and gitignore /// matchers in memory lower. - stack: Arc>>, + stack: Stack, /// Whether all workers should terminate at the next opportunity. Note /// that we need this because we don't want other `Work` to be done after /// we quit. We wouldn't need this if have a priority channel. quit_now: Arc, - /// The number of outstanding work items. - num_pending: Arc, + /// The number of currently active workers. + active_workers: Arc, /// The maximum depth of directories to descend. A value of `0` means no /// descension at all. max_depth: Option, @@ -1434,7 +1500,6 @@ impl<'s> Worker<'s> { if let WalkState::Quit = self.run_one(work) { self.quit_now(); } - self.work_done(); } } @@ -1616,23 +1681,20 @@ impl<'s> Worker<'s> { return None; } None => { - // Once num_pending reaches 0, it is impossible for it to - // ever increase again. Namely, it only reaches 0 once - // all jobs have run such that no jobs have produced more - // work. We have this guarantee because num_pending is - // always incremented before each job is submitted and only - // decremented once each job is completely finished. - // Therefore, if this reaches zero, then there can be no - // other job running. - if self.num_pending() == 0 { - // Every other thread is blocked at the next recv(). - // Send the initial quit message and quit. + if self.deactivate_worker() == 0 { + // If deactivate_worker() returns 0, every worker thread + // is currently within the critical section between the + // acquire in deactivate_worker() and the release in + // activate_worker() below. For this to happen, every + // worker's local deque must be simultaneously empty, + // meaning there is no more work left at all. self.send_quit(); return None; } // Wait for next `Work` or `Quit` message. loop { if let Some(v) = self.recv() { + self.activate_worker(); value = Some(v); break; } @@ -1640,7 +1702,8 @@ impl<'s> Worker<'s> { // CPU waiting, we let the thread sleep for a bit. In // general, this tends to only occur once the search is // approaching termination. - thread::sleep(Duration::from_millis(1)); + let dur = std::time::Duration::from_millis(1); + std::thread::sleep(dur); } } } @@ -1649,41 +1712,37 @@ impl<'s> Worker<'s> { /// Indicates that all workers should quit immediately. fn quit_now(&self) { - self.quit_now.store(true, Ordering::SeqCst); + self.quit_now.store(true, AtomicOrdering::SeqCst); } /// Returns true if this worker should quit immediately. fn is_quit_now(&self) -> bool { - self.quit_now.load(Ordering::SeqCst) - } - - /// Returns the number of pending jobs. - fn num_pending(&self) -> usize { - self.num_pending.load(Ordering::SeqCst) + self.quit_now.load(AtomicOrdering::SeqCst) } /// Send work. fn send(&self, work: Work) { - self.num_pending.fetch_add(1, Ordering::SeqCst); - let mut stack = self.stack.lock().unwrap(); - stack.push(Message::Work(work)); + self.stack.push(Message::Work(work)); } /// Send a quit message. fn send_quit(&self) { - let mut stack = self.stack.lock().unwrap(); - stack.push(Message::Quit); + self.stack.push(Message::Quit); } /// Receive work. fn recv(&self) -> Option { - let mut stack = self.stack.lock().unwrap(); - stack.pop() + self.stack.pop() + } + + /// Deactivates a worker and returns the number of currently active workers. + fn deactivate_worker(&self) -> usize { + self.active_workers.fetch_sub(1, AtomicOrdering::Acquire) - 1 } - /// Signal that work has been received. - fn work_done(&self) { - self.num_pending.fetch_sub(1, Ordering::SeqCst); + /// Reactivates a worker. + fn activate_worker(&self) { + self.active_workers.fetch_add(1, AtomicOrdering::Release); } } -- cgit v1.2.3