Compare commits

...

16 Commits

Author SHA1 Message Date
Braden Godley 6dd11c17d5
Merge 8360c9eaf4 into 8acd7722f0 2024-05-06 13:19:41 +01:00
Thayne McCombs 8acd7722f0
Merge pull request #1548 from tmccombs/release-9.1.0
Release 10.0.0
2024-05-06 00:01:31 -06:00
Thayne McCombs 92fab6e058 Prepare for 10.0.0 release 2024-05-05 23:52:50 -06:00
Thayne McCombs a0ee0856db Add @timestamp to --help 2024-05-05 23:52:50 -06:00
Thayne McCombs b8df500a70 Add script to automate some of release process. 2024-05-05 23:52:50 -06:00
Braden Godley 8360c9eaf4 run cargo fmt 2024-05-02 00:36:21 -07:00
Braden Godley aefd6ac7af simply mod by removing unnecessary function 2024-05-01 23:16:24 -07:00
Braden Godley d1b3bf41c1 some small tweaks and fixes for command execution 2024-05-01 23:10:54 -07:00
Braden Godley 6fe670d45a update changelog for filter feature 2024-05-01 22:30:43 -07:00
Braden Godley dc0cc1a770 Merge branch 'feature-filter' 2024-05-01 22:27:47 -07:00
Braden Godley 500b8517de add docstrings, simplify filter 2024-05-01 22:20:43 -07:00
Braden Godley 6f61c18d40 update usage 2024-05-01 22:11:23 -07:00
Braden Godley ee1de0f6d8 finish filter command 2024-05-01 22:01:45 -07:00
Braden Godley ad9cd5d8bf start work on filtering logic 2024-05-01 00:29:32 -07:00
Braden Godley 30cd3eaa97 added docstring to error handling function 2024-05-01 00:29:11 -07:00
Braden Godley a93fa7563c added filter command to cli 2024-05-01 00:26:20 -07:00
11 changed files with 256 additions and 97 deletions

View File

@ -1,4 +1,4 @@
# Upcoming release # v10.0.0
## Features ## Features
@ -8,20 +8,20 @@
was often useful, it also broke some existing workflows, and there wasn't a good way to opt out of it. And there isn't really a good way for us to add was often useful, it also broke some existing workflows, and there wasn't a good way to opt out of it. And there isn't really a good way for us to add
a way to opt out of it. And you can easily get similar behavior by adding `.git/` to your global fdignore file. a way to opt out of it. And you can easily get similar behavior by adding `.git/` to your global fdignore file.
See #1457. See #1457.
- Add `-f` \ `--filter <command>` argument that allows you to filter results based on the output of a command, as requested in #400.
## Bugfixes ## Bugfixes
- Respect NO_COLOR environment variable with `--list-details` option. (#1455) - Respect NO_COLOR environment variable with `--list-details` option. (#1455)
- Fix bug that would cause hidden files to be included despite gitignore rules - Fix bug that would cause hidden files to be included despite gitignore rules
if search path is "." (#1461, BurntSushi/ripgrep#2711). if search path is "." (#1461, BurntSushi/ripgrep#2711).
- aarch64 builds now use 64k page sizes with jemalloc. This fixes issues on some systems, such as ARM Macs that
have a larger system page size than the system that the binary was built on. (#1547)
- Address [CVE-2024-24576](https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html), by increasing minimum rust version.
## Changes ## Changes
- Minimum supported rust version is now 1.77.2
## Other
# v9.0.0 # v9.0.0

134
Cargo.lock generated
View File

@ -28,47 +28,48 @@ dependencies = [
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.13" version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
"anstyle-query", "anstyle-query",
"anstyle-wincon", "anstyle-wincon",
"colorchoice", "colorchoice",
"is_terminal_polyfill",
"utf8parse", "utf8parse",
] ]
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.6" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
version = "0.2.3" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [ dependencies = [
"utf8parse", "utf8parse",
] ]
[[package]] [[package]]
name = "anstyle-query" name = "anstyle-query"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "anstyle-wincon" name = "anstyle-wincon"
version = "3.0.2" version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"windows-sys 0.52.0", "windows-sys 0.52.0",
@ -93,9 +94,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
@ -127,9 +128,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.92" version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -152,7 +153,7 @@ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
"num-traits", "num-traits",
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -207,9 +208,9 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
@ -301,13 +302,13 @@ dependencies = [
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.2" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]] [[package]]
name = "fd-find" name = "fd-find"
version = "9.0.0" version = "10.0.0"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"anyhow", "anyhow",
@ -422,6 +423,12 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]] [[package]]
name = "jemalloc-sys" name = "jemalloc-sys"
version = "0.5.4+5.3.0-patched" version = "0.5.4+5.3.0-patched"
@ -533,9 +540,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -548,9 +555,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.79" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -604,9 +611,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.32" version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.5.0",
"errno", "errno",
@ -626,18 +633,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.200"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.197" version = "1.0.200"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -652,9 +659,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.58" version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -816,11 +823,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.6" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [ dependencies = [
"winapi", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -835,7 +842,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -853,7 +860,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -873,17 +880,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.4", "windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.4", "windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.4", "windows_i686_gnu 0.52.5",
"windows_i686_msvc 0.52.4", "windows_i686_gnullvm",
"windows_x86_64_gnu 0.52.4", "windows_i686_msvc 0.52.5",
"windows_x86_64_gnullvm 0.52.4", "windows_x86_64_gnu 0.52.5",
"windows_x86_64_msvc 0.52.4", "windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
] ]
[[package]] [[package]]
@ -894,9 +902,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -906,9 +914,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -918,9 +926,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -930,9 +944,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -942,9 +956,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -954,9 +968,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -966,6 +980,6 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

View File

@ -16,7 +16,7 @@ license = "MIT OR Apache-2.0"
name = "fd-find" name = "fd-find"
readme = "README.md" readme = "README.md"
repository = "https://github.com/sharkdp/fd" repository = "https://github.com/sharkdp/fd"
version = "9.0.0" version = "10.0.0"
edition= "2021" edition= "2021"
rust-version = "1.77.2" rust-version = "1.77.2"

View File

@ -333,8 +333,8 @@ Options:
-d, --max-depth <depth> Set maximum search depth (default: none) -d, --max-depth <depth> Set maximum search depth (default: none)
-E, --exclude <pattern> Exclude entries that match the given glob pattern -E, --exclude <pattern> Exclude entries that match the given glob pattern
-t, --type <filetype> Filter by type: file (f), directory (d/dir), symlink (l), -t, --type <filetype> Filter by type: file (f), directory (d/dir), symlink (l),
executable (x), empty (e), socket (s), pipe (p), executable (x), empty (e), socket (s), pipe (p), char-device
block-device (b), char-device (c) (c), block-device (b)
-e, --extension <ext> Filter by file extension -e, --extension <ext> Filter by file extension
-S, --size <size> Limit results based on the size of files -S, --size <size> Limit results based on the size of files
--changed-within <date|dur> Filter by file modification time (newer than) --changed-within <date|dur> Filter by file modification time (newer than)

22
scripts/version-bump.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/bash
set -eu
# This script automates the "Version bump" section
version="$1"
if [[ -z $version ]]; then
echo "Usage: must supply version as first argument" >&2
exit 1
fi
git switch -C "release-$version"
sed -i -e "0,/^\[badges/{s/^version =.*/version = \"$version\"/}" Cargo.toml
msrv="$(grep -F rust-version Cargo.toml | sed -e 's/^rust-version= "\(.*\)"/\1/')"
sed -i -e "s/Note that rust version \*[0-9.]+\* or later/Note that rust version *$msrv* or later/" README.md
sed -i -e "s/^# Upcoming release/# $version/" CHANGELOG.md

View File

@ -398,7 +398,7 @@ pub struct Opts {
/// Filter results based on the file modification time. Files with modification times /// Filter results based on the file modification time. Files with modification times
/// greater than the argument are returned. The argument can be provided /// greater than the argument are returned. The argument can be provided
/// as a specific point in time (YYYY-MM-DD HH:MM:SS) or as a duration (10h, 1d, 35min). /// as a specific point in time (YYYY-MM-DD HH:MM:SS or @timestamp) or as a duration (10h, 1d, 35min).
/// If the time is not specified, it defaults to 00:00:00. /// If the time is not specified, it defaults to 00:00:00.
/// '--change-newer-than', '--newer', or '--changed-after' can be used as aliases. /// '--change-newer-than', '--newer', or '--changed-after' can be used as aliases.
/// ///
@ -420,7 +420,7 @@ pub struct Opts {
/// Filter results based on the file modification time. Files with modification times /// Filter results based on the file modification time. Files with modification times
/// less than the argument are returned. The argument can be provided /// less than the argument are returned. The argument can be provided
/// as a specific point in time (YYYY-MM-DD HH:MM:SS) or as a duration (10h, 1d, 35min). /// as a specific point in time (YYYY-MM-DD HH:MM:SS or @timestamp) or as a duration (10h, 1d, 35min).
/// '--change-older-than' or '--older' can be used as aliases. /// '--change-older-than' or '--older' can be used as aliases.
/// ///
/// Examples: /// Examples:
@ -776,6 +776,11 @@ impl clap::FromArgMatches for Exec {
.get_occurrences::<String>("exec_batch") .get_occurrences::<String>("exec_batch")
.map(CommandSet::new_batch) .map(CommandSet::new_batch)
}) })
.or_else(|| {
matches
.get_occurrences::<String>("filter")
.map(CommandSet::new_filter)
})
.transpose() .transpose()
.map_err(|e| clap::Error::raw(ErrorKind::InvalidValue, e))?; .map_err(|e| clap::Error::raw(ErrorKind::InvalidValue, e))?;
Ok(Exec { command }) Ok(Exec { command })
@ -797,7 +802,7 @@ impl clap::Args for Exec {
.allow_hyphen_values(true) .allow_hyphen_values(true)
.value_terminator(";") .value_terminator(";")
.value_name("cmd") .value_name("cmd")
.conflicts_with("list_details") .conflicts_with_all(["list_details", "exec_batch"])
.help("Execute a command for each search result") .help("Execute a command for each search result")
.long_help( .long_help(
"Execute a command for each search result in parallel (use --threads=1 for sequential command execution). \ "Execute a command for each search result in parallel (use --threads=1 for sequential command execution). \
@ -851,7 +856,35 @@ impl clap::Args for Exec {
fd -g 'test_*.py' -X vim\n\n \ fd -g 'test_*.py' -X vim\n\n \
- Find all *.rs files and count the lines with \"wc -l ...\":\n\n \ - Find all *.rs files and count the lines with \"wc -l ...\":\n\n \
fd -e rs -X wc -l\ fd -e rs -X wc -l\
" "
),
)
.arg(
Arg::new("filter")
.action(ArgAction::Append)
.long("filter")
.short('f')
.num_args(1..)
.allow_hyphen_values(true)
.value_terminator(";")
.value_name("cmd")
.conflicts_with_all(["exec", "exec_batch", "list_details"])
.help("Execute a command to determine whether each result should be filtered")
.long_help(
"Execute a command in parallel for each search result, filtering out results where the exit code is non-zero. \
There is no guarantee of the order commands are executed in, and the order should not be depended upon. \
All positional arguments following --filter are considered to be arguments to the command - not to fd. \
It is therefore recommended to place the '-f'/'--filter' option last.\n\
The following placeholders are substituted before the command is executed:\n \
'{}': path (of the current search result)\n \
'{/}': basename\n \
'{//}': parent directory\n \
'{.}': path without file extension\n \
'{/.}': basename without file extension\n \
'{{': literal '{' (for escaping)\n \
'}}': literal '}' (for escaping)\n\n\
If no placeholder is present, an implicit \"{}\" at the end is assumed.\n\n\
"
), ),
) )
} }

View File

@ -11,6 +11,8 @@ struct Outputs {
stdout: Vec<u8>, stdout: Vec<u8>,
stderr: Vec<u8>, stderr: Vec<u8>,
} }
/// Used to print the results of commands that run on results in a thread-safe way
struct OutputBuffer<'a> { struct OutputBuffer<'a> {
output_permission: &'a Mutex<()>, output_permission: &'a Mutex<()>,
outputs: Vec<Outputs>, outputs: Vec<Outputs>,
@ -67,8 +69,9 @@ pub fn execute_commands<I: Iterator<Item = io::Result<Command>>>(
let output = if enable_output_buffering { let output = if enable_output_buffering {
cmd.output() cmd.output()
} else { } else {
// If running on only one thread, don't buffer output // If running on only one thread, don't buffer output; instead just
// Allows for viewing and interacting with intermediate command output // write directly to stdout. Allows for viewing and interacting with
// intermediate command output
cmd.spawn().and_then(|c| c.wait_with_output()) cmd.spawn().and_then(|c| c.wait_with_output())
}; };
@ -78,7 +81,7 @@ pub fn execute_commands<I: Iterator<Item = io::Result<Command>>>(
if enable_output_buffering { if enable_output_buffering {
output_buffer.push(output.stdout, output.stderr); output_buffer.push(output.stdout, output.stderr);
} }
if output.status.code() != Some(0) { if !output.status.success() {
output_buffer.write(); output_buffer.write();
return ExitCode::GeneralError; return ExitCode::GeneralError;
} }
@ -93,6 +96,59 @@ pub fn execute_commands<I: Iterator<Item = io::Result<Command>>>(
ExitCode::Success ExitCode::Success
} }
/// Executes a command and pushes the path to the buffer if it succeeded with a
/// non-zero exit code.
pub fn execute_commands_filtering<I: Iterator<Item = io::Result<Command>>>(
path: &std::path::Path,
cmds: I,
out_perm: &Mutex<()>,
enable_output_buffering: bool,
) -> ExitCode {
let mut output_buffer = OutputBuffer::new(out_perm);
// Convert path to bufferable path string
let path_str = match path.to_str() {
Some(path) => format!("{}\n", path),
None => {
// Probably had non UTF-8 chars in the path somehow
return ExitCode::GeneralError;
}
};
let path_u8 = path_str.as_bytes().to_vec();
for result in cmds {
let mut cmd = match result {
Ok(cmd) => cmd,
Err(e) => return handle_cmd_error(None, e),
};
// Spawn the supplied command.
let output = cmd.output();
match output {
Ok(output) => {
if output.status.success() {
if enable_output_buffering {
// Push nothing to stderr because, well, there's nothing to push.
output_buffer.push(path_u8.clone(), vec![]);
} else {
print!("{}", path_str);
}
} else {
return ExitCode::GeneralError;
}
}
Err(why) => {
return handle_cmd_error(Some(&cmd), why);
}
}
}
output_buffer.write();
ExitCode::Success
}
/// Displays user-friendly error message based on the kind of error that occurred while
/// running a command
pub fn handle_cmd_error(cmd: Option<&Command>, err: io::Error) -> ExitCode { pub fn handle_cmd_error(cmd: Option<&Command>, err: io::Error) -> ExitCode {
match (cmd, err) { match (cmd, err) {
(Some(cmd), err) if err.kind() == io::ErrorKind::NotFound => { (Some(cmd), err) if err.kind() == io::ErrorKind::NotFound => {

View File

@ -15,6 +15,7 @@ pub fn job(
cmd: &CommandSet, cmd: &CommandSet,
out_perm: &Mutex<()>, out_perm: &Mutex<()>,
config: &Config, config: &Config,
filter: bool,
) -> ExitCode { ) -> ExitCode {
// Output should be buffered when only running a single thread // Output should be buffered when only running a single thread
let buffer_output: bool = config.threads > 1; let buffer_output: bool = config.threads > 1;
@ -39,7 +40,9 @@ pub fn job(
config.path_separator.as_deref(), config.path_separator.as_deref(),
out_perm, out_perm,
buffer_output, buffer_output,
filter,
); );
ret = merge_exitcodes([ret, code]); ret = merge_exitcodes([ret, code]);
} }
// Returns error in case of any error. // Returns error in case of any error.

View File

@ -16,7 +16,7 @@ use argmax::Command;
use crate::exit_codes::{merge_exitcodes, ExitCode}; use crate::exit_codes::{merge_exitcodes, ExitCode};
use self::command::{execute_commands, handle_cmd_error}; use self::command::{execute_commands, execute_commands_filtering, handle_cmd_error};
use self::input::{basename, dirname, remove_extension}; use self::input::{basename, dirname, remove_extension};
pub use self::job::{batch, job}; pub use self::job::{batch, job};
use self::token::{tokenize, Token}; use self::token::{tokenize, Token};
@ -28,6 +28,8 @@ pub enum ExecutionMode {
OneByOne, OneByOne,
/// Command is run for a batch of results at once /// Command is run for a batch of results at once
Batch, Batch,
/// Command is executed for each search result to determine if it should be filtered
FilterResults,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -76,6 +78,25 @@ impl CommandSet {
}) })
} }
pub fn new_filter<I, T, S>(input: I) -> Result<CommandSet>
where
I: IntoIterator<Item = T>,
T: IntoIterator<Item = S>,
S: AsRef<str>,
{
Ok(CommandSet {
mode: ExecutionMode::FilterResults,
commands: input
.into_iter()
.map(CommandTemplate::new)
.collect::<Result<_>>()?,
})
}
pub fn get_mode(&self) -> ExecutionMode {
self.mode
}
pub fn in_batch_mode(&self) -> bool { pub fn in_batch_mode(&self) -> bool {
self.mode == ExecutionMode::Batch self.mode == ExecutionMode::Batch
} }
@ -86,12 +107,18 @@ impl CommandSet {
path_separator: Option<&str>, path_separator: Option<&str>,
out_perm: &Mutex<()>, out_perm: &Mutex<()>,
buffer_output: bool, buffer_output: bool,
filter: bool,
) -> ExitCode { ) -> ExitCode {
let commands = self let commands = self
.commands .commands
.iter() .iter()
.map(|c| c.generate(input, path_separator)); .map(|c| c.generate(input, path_separator));
execute_commands(commands, out_perm, buffer_output)
if filter {
execute_commands_filtering(input, commands, out_perm, buffer_output)
} else {
execute_commands(commands, out_perm, buffer_output)
}
} }
pub fn execute_batch<I>(&self, paths: I, limit: usize, path_separator: Option<&str>) -> ExitCode pub fn execute_batch<I>(&self, paths: I, limit: usize, path_separator: Option<&str>) -> ExitCode

View File

@ -43,6 +43,7 @@ impl ExitCode {
} }
} }
/// If any of the exit codes was an error, this returns a GeneralError
pub fn merge_exitcodes(results: impl IntoIterator<Item = ExitCode>) -> ExitCode { pub fn merge_exitcodes(results: impl IntoIterator<Item = ExitCode>) -> ExitCode {
if results.into_iter().any(ExitCode::is_error) { if results.into_iter().any(ExitCode::is_error) {
return ExitCode::GeneralError; return ExitCode::GeneralError;

View File

@ -408,28 +408,31 @@ impl WorkerState {
// This will be set to `Some` if the `--exec` argument was supplied. // This will be set to `Some` if the `--exec` argument was supplied.
if let Some(ref cmd) = config.command { if let Some(ref cmd) = config.command {
if cmd.in_batch_mode() { match cmd.get_mode() {
exec::batch(rx.into_iter().flatten(), cmd, config) exec::ExecutionMode::Batch => exec::batch(rx.into_iter().flatten(), cmd, config),
} else { exec::ExecutionMode::OneByOne | exec::ExecutionMode::FilterResults => {
let out_perm = Mutex::new(()); let out_perm = Mutex::new(());
let filter = cmd.get_mode() == exec::ExecutionMode::FilterResults;
thread::scope(|scope| { thread::scope(|scope| {
// Each spawned job will store its thread handle in here. // Each spawned job will store its thread handle in here.
let threads = config.threads; let threads = config.threads;
let mut handles = Vec::with_capacity(threads); let mut handles = Vec::with_capacity(threads);
for _ in 0..threads { for _ in 0..threads {
let rx = rx.clone(); let rx = rx.clone();
// Spawn a job thread that will listen for and execute inputs. // Spawn a job thread that will listen for and execute inputs.
let handle = scope let handle = scope.spawn(|| {
.spawn(|| exec::job(rx.into_iter().flatten(), cmd, &out_perm, config)); exec::job(rx.into_iter().flatten(), cmd, &out_perm, config, filter)
});
// Push the handle of the spawned thread into the vector for later joining. // Push the handle of the spawned thread into the vector for later joining.
handles.push(handle); handles.push(handle);
} }
let exit_codes = handles.into_iter().map(|handle| handle.join().unwrap()); let exit_codes = handles.into_iter().map(|handle| handle.join().unwrap());
merge_exitcodes(exit_codes) merge_exitcodes(exit_codes)
}) })
}
} }
} else { } else {
let stdout = io::stdout().lock(); let stdout = io::stdout().lock();