summaryrefslogtreecommitdiffstats
path: root/vendor/ignore
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ignore')
-rw-r--r--vendor/ignore/.cargo-checksum.json2
-rw-r--r--vendor/ignore/Cargo.lock161
-rw-r--r--vendor/ignore/Cargo.toml46
-rw-r--r--vendor/ignore/examples/walk.rs28
-rw-r--r--vendor/ignore/src/default_types.rs413
-rw-r--r--vendor/ignore/src/dir.rs128
-rw-r--r--vendor/ignore/src/gitignore.rs107
-rw-r--r--vendor/ignore/src/lib.rs64
-rw-r--r--vendor/ignore/src/overrides.rs6
-rw-r--r--vendor/ignore/src/pathutil.rs24
-rw-r--r--vendor/ignore/src/types.rs55
-rw-r--r--vendor/ignore/src/walk.rs263
12 files changed, 750 insertions, 547 deletions
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"
@@ -135,28 +171,55 @@ dependencies = [
]
[[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 <jamslam@gmail.com>"]
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<W: Write>(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<W: Write>(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<IgnoreInner>);
+pub(crate) struct Ignore(Arc<IgnoreInner>);
#[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<Ignore> {
+ pub(crate) fn parent(&self) -> Option<Ignore> {
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<P: AsRef<Path>>(
+ pub(crate) fn add_parents<P: AsRef<Path>>(
&self,
path: P,
) -> (Ignore, Option<Error>) {
@@ -222,7 +226,7 @@ impl Ignore {
/// returned if it exists.
///
/// Note that all I/O errors are completely ignored.
- pub fn add_child<P: AsRef<Path>>(
+ pub(crate) fn add_child<P: AsRef<Path>>(
&self,
dir: P,
) -> (Ignore, Option<Error>) {
@@ -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<IgnoreMatch<'a>> {
@@ -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<S: AsRef<OsStr>>(
+ pub(crate) fn add_custom_ignore_filename<S: AsRef<OsStr>>(
&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<T: AsRef<OsStr>>(
+pub(crate) fn create_gitignore<T: AsRef<OsStr>>(
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<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) {
- fs::create_dir_all(path).unwrap();
+ std::fs::create_dir_all(path).unwrap();
}
fn partial(err: Error) -> Vec<Error> {
@@ -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<Glob>,
num_ignores: u64,
num_whitelists: u64,
- matches: Option<Arc<ThreadLocal<RefCell<Vec<usize>>>>>,
+ matches: Option<Arc<Pool<Vec<usize>>>>,
}
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<PathBuf> {
+pub fn gitconfig_excludes_path() -> Option<PathBuf> {
// 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<Vec<u8>> {
};
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<Vec<u8>> {
/// 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<Vec<u8>> {
- 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<Vec<u8>> {
///
/// Specifically, this respects XDG_CONFIG_HOME.
fn excludes_file_default() -> Option<PathBuf> {
- 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<PathBuf> {
/// Extract git's `core.excludesfile` config setting from the raw file contents
/// given.
fn parse_excludes_file(data: &[u8]) -> Option<PathBuf> {
+ 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<Regex> = 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<PathBuf> {
- // 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<P: AsRef<Path>>(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<Error> 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<Error> 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<std::io::Error> {
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<String> =
@@ -359,8 +358,8 @@ impl fmt::Display for Error {
}
}
-impl From<io::Error> for Error {
- fn from(err: io::Error) -> Error {
+impl From<std::io::Error> for Error {
+ fn from(err: std::io::Error) -> Error {
Error::Io(err)
}
}
@@ -488,19 +487,18 @@ impl<T> Match<T> {
#[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<T> =
- result::Result<T, Box<dyn error::Error + Send + Sync>>;
+ pub(crate) type Result<T> =
+ std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
macro_rules! err {
($($tt:tt)*) => {
- Box::<dyn error::Error + Send + Sync>::from(format!($($tt)*))
+ Box::<dyn std::error::Error + Send + Sync>::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<Path> + ?Sized>(
+pub(crate) fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
prefix: &'a P,
path: &'a Path,
) -> Option<&'a Path> {
@@ -80,7 +79,7 @@ pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
///
/// If `path` doesn't have a prefix `prefix`, then return `None`.
#[cfg(not(unix))]
-pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
+pub(crate) fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
prefix: &'a P,
path: &'a Path,
) -> Option<&'a Path> {
@@ -90,10 +89,11 @@ pub fn strip_prefix<'a, P: AsRef<Path> + ?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<P: AsRef<Path>>(path: P) -> bool {
- use memchr::memchr;
+pub(crate) fn is_file_name<P: AsRef<Path>>(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<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) -> bool {
+pub(crate) fn is_file_name<P: AsRef<Path>>(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<P: AsRef<Path>>(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<Path> + ?Sized>(
+pub(crate) fn file_name<'a, P: AsRef<Path> + ?Sized>(
path: &'a P,
) -> Option<&'a OsStr> {
use memchr::memrchr;
@@ -135,7 +135,7 @@ pub fn file_name<'a, P: AsRef<Path> + ?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<Path> + ?Sized>(
+pub(crate) fn file_name<'a, P: AsRef<Path> + ?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<ThreadLocal<RefCell<Vec<usize>>>>,
+ matches: Arc<Pool<Vec<usize>>>,
}
/// 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<Error>) -> DirEntry {
- DirEntry { dent: DirEntryInner::Walkdir(dent), err: err }
+ DirEntry { dent: DirEntryInner::Walkdir(dent), err }
}
fn new_raw(dent: DirEntryRaw, err: Option<Error>) -> 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<DirEntryRaw, Error> {
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<DirEntryRaw, Error> {
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<dyn Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static>,
- ),
- ByPath(Arc<dyn Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
+ ByName(Arc<dyn Fn(&OsStr, &OsStr) -> Ordering + Send + Sync + 'static>),
+ ByPath(Arc<dyn Fn(&Path, &Path) -> Ordering + Send + Sync + 'static>),
}
#[derive(Clone)]
struct Filter(Arc<dyn Fn(&DirEntry) -> 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<F>(&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<F>(&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<WalkEventIter>)>,
+ its: std::vec::IntoIter<(PathBuf, Option<WalkEventIter>)>,
it: Option<WalkEventIter>,
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<dyn ParallelVisitor + 's>;
@@ -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<PathBuf>,
+ paths: std::vec::IntoIter<PathBuf>,
ig_root: Ignore,
max_filesize: Option<u64>,
max_depth: Option<usize>,
@@ -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<Message>,
+ /// The work stealers.
+ stealers: Arc<[Stealer<Message>]>,
+}
+
+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<Message>) -> Vec<Stack> {
+ // 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<Deque<Message>> =
+ std::iter::repeat_with(Deque::new_lifo).take(threads).collect();
+ let stealers = Arc::<[Stealer<Message>]>::from(
+ deques.iter().map(Deque::stealer).collect::<Vec<_>>(),
+ );
+ let stacks: Vec<Stack> = 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<Message> {
+ self.deque.pop().or_else(|| self.steal())
+ }
+
+ /// Steal a message from another queue.
+ fn steal(&self) -> Option<Message> {
+ // 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<dyn ParallelVisitor + 's>,
- /// 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<Mutex<Vec<Message>>>,
+ 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<AtomicBool>,
- /// The number of outstanding work items.
- num_pending: Arc<AtomicUsize>,
+ /// The number of currently active workers.
+ active_workers: Arc<AtomicUsize>,
/// The maximum depth of directories to descend. A value of `0` means no
/// descension at all.
max_depth: Option<usize>,
@@ -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<Message> {
- 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);
}
}