From b7e077320dfd8293e593e72e2b437b12b4845146 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Wed, 22 Dec 2021 22:38:00 -0800 Subject: [PATCH 01/46] Fix logic for --no-ignore-parent (#908) Make sure that using `--no-ignore-vcs` or `--no-ignore` don't also enable `--no-ignore-parent`. So that if `--no-ignore-vcs` is enabled, it continues to respect .fdignore and .ignore in the parent directories. Fixes: #907 Fixes: #901 --- src/main.rs | 5 +---- src/walk.rs | 2 +- tests/tests.rs | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4f4ab14..56d6bfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -260,10 +260,7 @@ fn construct_config(matches: clap::ArgMatches, pattern_regex: &str) -> Result, config: Arc) -> R walker .hidden(config.ignore_hidden) .ignore(config.read_fdignore) - .parents(config.read_parent_ignore) + .parents(config.read_parent_ignore && (config.read_fdignore || config.read_vcsignore)) .git_ignore(config.read_vcsignore) .git_global(config.read_vcsignore) .git_exclude(config.read_vcsignore) diff --git a/tests/tests.rs b/tests/tests.rs index 807b91b..e6cee6c 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -614,6 +614,22 @@ fn test_no_ignore_vcs() { ); } +/// Test that --no-ignore-vcs still respects .fdignored in parent directory +#[test] +fn test_no_ignore_vcs_child_dir() { + let te = TestEnv::new( + &["inner"], + &["inner/fdignored.foo", "inner/foo", "inner/gitignored.foo"], + ); + + te.assert_output_subdirectory( + "inner", + &["--no-ignore-vcs", "foo"], + "./foo + ./gitignored.foo", + ); +} + /// Custom ignore files (--ignore-file) #[test] fn test_custom_ignore_files() { From da7ea790348c352b74c6ffb7c30b1e8b4e09a9b8 Mon Sep 17 00:00:00 2001 From: David Peter Date: Tue, 28 Dec 2021 14:00:36 +0100 Subject: [PATCH 02/46] Use correct description for Debian package, closes #915 --- .github/workflows/CICD.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 03d59a2..b84459f 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -313,8 +313,11 @@ jobs: Architecture: ${DPKG_ARCH} Provides: ${{ env.PROJECT_NAME }} Conflicts: ${DPKG_CONFLICTS} - Description: cat(1) clone with wings. - A cat(1) clone with syntax highlighting and Git integration. + Description: simple, fast and user-friendly alternative to find + fd is a program to find entries in your filesystem. + It is a simple, fast and user-friendly alternative to find. + While it does not aim to support all of finds powerful functionality, it provides + sensible (opinionated) defaults for a majority of use cases. EOF DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}" From 639ed34791b7341aa2fe192d638f6f14eaab7088 Mon Sep 17 00:00:00 2001 From: eatradish Date: Thu, 23 Dec 2021 16:13:44 +0800 Subject: [PATCH 03/46] Allow use to disable jemalloc jemalloc will require special flags on devices where page size is not 4K. With default options fd will not work on a Mac Mini M1 where hardware only allow 16K paging size. This commit will allow the user to turn off jemalloc (using --no-default-features) under special circumstances where jemalloc is not usable. --- Cargo.toml | 6 +++++- src/main.rs | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 670e80f..5135fa5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,7 @@ libc = "0.2" # jemalloc is currently disabled on macOS due to a bug in jemalloc in combination with macOS # Catalina. See https://github.com/sharkdp/fd/issues/498 for details. [target.'cfg(all(not(windows), not(target_os = "android"), not(target_os = "macos"), not(target_os = "freebsd"), not(target_env = "musl")))'.dependencies] -jemallocator = "0.3.0" +jemallocator = {version = "0.3.0", optional = true} [dev-dependencies] diff = "0.1" @@ -77,3 +77,7 @@ test-case = "1.2" [profile.release] lto = true codegen-units = 1 + +[features] +use-jemalloc = ["jemallocator"] +default = ["use-jemalloc"] \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 56d6bfb..8ff1478 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,7 +39,8 @@ use crate::regex_helper::{pattern_has_uppercase_char, pattern_matches_strings_wi not(target_os = "android"), not(target_os = "macos"), not(target_os = "freebsd"), - not(target_env = "musl") + not(target_env = "musl"), + feature = "use-jemalloc" ))] #[global_allocator] static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; From dade9736acd08c062bb81434fa1f5fa065179b5e Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Mon, 27 Dec 2021 00:43:22 -0700 Subject: [PATCH 04/46] Add entry to changelog for no-ignore-vcs fix I forgot to add it when I made the PR. See commit 8bdbbd8e0cbe8ba010ce5c7f863e23af44386741 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47bfb05..8bf38d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ## Bugfixes +- Stop implying `--no-ignore-parent` when `--no-vcs-ignore` is supplied, see #907, #901 + ## Changes ## Other From 30add71233a9e9088d9ce2915e516b77e5b00372 Mon Sep 17 00:00:00 2001 From: Ryan Lue Date: Thu, 23 Dec 2021 13:28:34 -0800 Subject: [PATCH 05/46] Update manpage to match --help output Three command line options were added in late 2021 that never made their way into the manpage: * f8ae334 introduced --no-ignore-parent; * bf9e6fd introduced --strip-prefix (later renamed strip-cwd-prefix); and * 17dd2a6 introduced --batch-size. This commit updates the manpage content to reflect the auto-generated output of `fd --help`. --- doc/fd.1 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/fd.1 b/doc/fd.1 index 51deaff..b5809c7 100644 --- a/doc/fd.1 +++ b/doc/fd.1 @@ -66,6 +66,10 @@ git setting, which defaults to .IR $HOME/.config/git/ignore ). The flag can be overridden with '--ignore-vcs'. .TP +.B \-\-no\-ignore\-parent +Show search results from files and directories that would otherwise be ignored by gitignore files in +parent directories. +.TP .B \-s, \-\-case\-sensitive Perform a case-sensitive search. By default, fd uses case-insensitive searches, unless the pattern contains an uppercase character (smart case). @@ -126,6 +130,10 @@ can be used as an alias. Enable the display of filesystem errors for situations such as insufficient permissions or dead symlinks. .TP +.B \-\-strip-cwd-prefix +By default, relative paths are prefixed with './' when the output goes to a non interactive terminal +(TTY). Use this flag to disable this behaviour. +.TP .B \-\-one\-file\-system, \-\-mount, \-\-xdev By default, fd will traverse the file system tree as far as other options dictate. With this flag, fd ensures that it does not descend into a different file system than the one it started in. Comparable to the -mount or -xdev filters of find(1). .TP @@ -393,7 +401,11 @@ Examples: fd -e rs -X wc -l .RE - +.TP +.BI "\-\-batch-size " size +Maximum number of arguments to pass to the command given with -X. If the number of results is +greater than the given size, the command given with -X is run again with remaining arguments. A +batch size of zero means there is no limit. .SH PATTERN SYNTAX The regular expression syntax used by fd is documented here: From e5145ffb985ab1fdd72b680806dff4fc00c1877f Mon Sep 17 00:00:00 2001 From: Yujia Qiao Date: Tue, 14 Dec 2021 17:09:48 +0800 Subject: [PATCH 06/46] fix: disable jemalloc on risc-v target `jemallocator` does not support risc-v and fails the compilation. This fixes build for risc-v. --- Cargo.toml | 4 ++-- src/main.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5135fa5..67e2325 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ libc = "0.2" # FIXME: Re-enable jemalloc on macOS # jemalloc is currently disabled on macOS due to a bug in jemalloc in combination with macOS # Catalina. See https://github.com/sharkdp/fd/issues/498 for details. -[target.'cfg(all(not(windows), not(target_os = "android"), not(target_os = "macos"), not(target_os = "freebsd"), not(target_env = "musl")))'.dependencies] +[target.'cfg(all(not(windows), not(target_os = "android"), not(target_os = "macos"), not(target_os = "freebsd"), not(target_env = "musl"), not(target_arch = "riscv64")))'.dependencies] jemallocator = {version = "0.3.0", optional = true} [dev-dependencies] @@ -80,4 +80,4 @@ codegen-units = 1 [features] use-jemalloc = ["jemallocator"] -default = ["use-jemalloc"] \ No newline at end of file +default = ["use-jemalloc"] diff --git a/src/main.rs b/src/main.rs index 8ff1478..2eccd06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ use crate::regex_helper::{pattern_has_uppercase_char, pattern_matches_strings_wi not(target_os = "macos"), not(target_os = "freebsd"), not(target_env = "musl"), + not(target_arch = "riscv64"), feature = "use-jemalloc" ))] #[global_allocator] From e7f192f1c6f16144c921bd5c33544750d2494f15 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 28 Dec 2021 12:11:32 -0500 Subject: [PATCH 07/46] Revert "Switch from std::sync::mpsc to crossbeam-channel" @sharkdp [noticed][1] a quite severe performance degredation due to this change. Switch back to std::sync::mpsc until we can fix the performance regression. This reverts commit a4bb734482c7bf3fd4d30081e7d3ce7786a3775e. [1]: https://github.com/sharkdp/fd/pull/895#issuecomment-1002099369 --- Cargo.lock | 11 ----------- Cargo.toml | 1 - src/exec/job.rs | 3 +-- src/walk.rs | 10 +++++++--- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa88064..45d3b4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,16 +99,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.5" @@ -165,7 +155,6 @@ dependencies = [ "atty", "chrono", "clap", - "crossbeam-channel", "ctrlc", "diff", "dirs-next", diff --git a/Cargo.toml b/Cargo.toml index 67e2325..25b8f78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,6 @@ dirs-next = "2.0" normpath = "0.3" chrono = "0.4" once_cell = "1.8.0" -crossbeam-channel = "0.5.1" [dependencies.clap] version = "2.34.0" diff --git a/src/exec/job.rs b/src/exec/job.rs index 0effc44..85b30f1 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -1,8 +1,7 @@ use std::path::PathBuf; +use std::sync::mpsc::Receiver; use std::sync::{Arc, Mutex}; -use crossbeam_channel::Receiver; - use crate::error::print_error; use crate::exit_codes::{merge_exitcodes, ExitCode}; use crate::walk::WorkerResult; diff --git a/src/walk.rs b/src/walk.rs index 037baae..0d412ba 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -4,13 +4,13 @@ use std::io; use std::mem; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; use std::{borrow::Cow, io::Write}; use anyhow::{anyhow, Result}; -use crossbeam_channel::{unbounded, Receiver, RecvTimeoutError, Sender}; use ignore::overrides::OverrideBuilder; use ignore::{self, WalkBuilder}; use once_cell::unsync::OnceCell; @@ -55,7 +55,7 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> R let first_path_buf = path_iter .next() .expect("Error: Path vector can not be empty"); - let (tx, rx) = unbounded(); + let (tx, rx) = channel(); let mut override_builder = OverrideBuilder::new(first_path_buf.as_path()); @@ -232,7 +232,11 @@ impl ReceiverBuffer { match self.mode { ReceiverMode::Buffering => { // Wait at most until we should switch to streaming - self.rx.recv_deadline(self.deadline) + let now = Instant::now(); + self.deadline + .checked_duration_since(now) + .ok_or(RecvTimeoutError::Timeout) + .and_then(|t| self.rx.recv_timeout(t)) } ReceiverMode::Streaming => { // Wait however long it takes for a result From c2e5075316a3022a3f6fa059d17dee1d12505d16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:25:06 -0700 Subject: [PATCH 08/46] Bump once_cell from 1.8.0 to 1.9.0 (#925) Bumps [once_cell](https://github.com/matklad/once_cell) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/matklad/once_cell/releases) - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa88064..467c80f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -394,9 +394,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "proc-macro2" diff --git a/Cargo.toml b/Cargo.toml index 67e2325..5043ea1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ anyhow = "1.0" dirs-next = "2.0" normpath = "0.3" chrono = "0.4" -once_cell = "1.8.0" +once_cell = "1.9.0" crossbeam-channel = "0.5.1" [dependencies.clap] From 0dc49b07a0cd9bf766f2eace945fa9b6830817f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:25:33 -0700 Subject: [PATCH 09/46] Bump libc from 0.2.108 to 0.2.112 (#924) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.108 to 0.2.112. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.108...0.2.112) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 467c80f..c22aeb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,9 +304,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.108" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "log" From f6bbeb35f5f5c96907449168bb730fd5422562af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:26:00 -0700 Subject: [PATCH 10/46] Bump nix from 0.23.0 to 0.23.1 (#922) Bumps [nix](https://github.com/nix-rust/nix) from 0.23.0 to 0.23.1. - [Release notes](https://github.com/nix-rust/nix/releases) - [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md) - [Commits](https://github.com/nix-rust/nix/compare/v0.23.0...v0.23.1) --- updated-dependencies: - dependency-name: nix dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c22aeb2..f9f6476 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,9 +343,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", diff --git a/Cargo.toml b/Cargo.toml index 5043ea1..8cc3de7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ features = ["suggestions", "color", "wrap_help"] [target.'cfg(unix)'.dependencies] users = "0.11.0" -nix = "0.23.0" +nix = "0.23.1" [target.'cfg(all(unix, not(target_os = "redox")))'.dependencies] libc = "0.2" From fbebaa299d177d492a10b5a1540bedf329244ff9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:26:25 -0700 Subject: [PATCH 11/46] Bump version_check from 0.9.3 to 0.9.4 (#921) Bumps [version_check](https://github.com/SergioBenitez/version_check) from 0.9.3 to 0.9.4. - [Release notes](https://github.com/SergioBenitez/version_check/releases) - [Commits](https://github.com/SergioBenitez/version_check/compare/v0.9.3...v0.9.4) --- updated-dependencies: - dependency-name: version_check dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9f6476..379d098 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -616,9 +616,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" From 075c1af7d8c6dc5ddaab222a77d0670cb4c45e15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:47:20 -0700 Subject: [PATCH 12/46] Bump num_cpus from 1.13.0 to 1.13.1 (#927) Bumps [num_cpus](https://github.com/seanmonstar/num_cpus) from 1.13.0 to 1.13.1. - [Release notes](https://github.com/seanmonstar/num_cpus/releases) - [Changelog](https://github.com/seanmonstar/num_cpus/blob/master/CHANGELOG.md) - [Commits](https://github.com/seanmonstar/num_cpus/compare/v1.13.0...v1.13.1) --- updated-dependencies: - dependency-name: num_cpus dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 379d098..a6e27e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", diff --git a/Cargo.toml b/Cargo.toml index 8cc3de7..65c8592 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ version_check = "0.9" ansi_term = "0.12" atty = "0.2" ignore = "0.4.3" -num_cpus = "1.8" +num_cpus = "1.13" regex = "1.5.4" regex-syntax = "0.6" ctrlc = "3.2" From c800c799764b2b258091c252b9a86e2f7caecd94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 16:26:25 +0000 Subject: [PATCH 13/46] Bump anyhow from 1.0.51 to 1.0.52 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.51 to 1.0.52. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.51...1.0.52) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6e27e7..d90989d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" [[package]] name = "atty" From d5f740c9d31a287d7f587edfdb7395d2edfccca9 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Wed, 5 Jan 2022 19:44:13 -0700 Subject: [PATCH 14/46] Add a couple of options to zsh completion --no-ignore-parent and --strip-cwd-prefix --- contrib/completion/_fd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/completion/_fd b/contrib/completion/_fd index f8521a7..45b8ca4 100644 --- a/contrib/completion/_fd +++ b/contrib/completion/_fd @@ -57,6 +57,7 @@ _fd() { + no-ignore-partial # some ignore files "(no-ignore-full --no-ignore-vcs)--no-ignore-vcs[don't respect .gitignore files]" "!(no-ignore-full --no-global-ignore-file)--no-global-ignore-file[don't respect the global ignore file]" + $no'(no-ignore-full --no-ignore-parent)--no-ignore-parent[]' + '(case)' # case-sensitivity {-s,--case-sensitive}'[perform a case-sensitive search]' @@ -154,6 +155,9 @@ _fd() { $no'(--base-directory)--base-directory=[change the current working directory to the given path]:directory:_files -/' $no'(*)*--search-path=[set search path (instead of positional arguments)]:directory:_files -/' + + strip-cwd-prefix + $no'(strip-cwd-prefix exec-cmds)--strip-cwd-prefix[Strip ./ prefix when output is redirected]' + + args # positional arguments '1: :_guard "^-*" pattern' '(--search-path)*:directory:_files -/' From aa1c0250b7053a88f2adb6ba7e2cf8c2f912a2a6 Mon Sep 17 00:00:00 2001 From: David Peter Date: Thu, 6 Jan 2022 13:59:04 +0100 Subject: [PATCH 15/46] Update CHANGELOG --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bf38d0..23d2134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,17 @@ ## Bugfixes -- Stop implying `--no-ignore-parent` when `--no-vcs-ignore` is supplied, see #907, #901 +- Stop implying `--no-ignore-parent` when `--no-vcs-ignore` is supplied, see #907, #901, #908 (@tmccombs) +- fd no longer waits for the whole traversal if the only matches arrive within max_buffer_time, see #868 and #895 (@tavianator) +- `--max-results=1` now immediately quits after the first result, see #867 +- `fd -h` does not panic anymore when stdout is closed, see #897 ## Changes +- Disable jemalloc on FreeBSD, see #896 (@xanderio) +- Updated man page, see #912 (@rlue) +- Updated zsh completions, see #932 (@tmccombs) + ## Other From 72895675efa5842a4fe9049dfbad5736d1bf23a1 Mon Sep 17 00:00:00 2001 From: David Peter Date: Thu, 6 Jan 2022 14:02:55 +0100 Subject: [PATCH 16/46] Bump version to v8.3.1 --- CHANGELOG.md | 18 +++++++++++++++--- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23d2134..4cdb9ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,23 @@ ## Performance improvements + ## Features + +## Bugfixes + + +## Changes + + +## Other + + + + +# v8.3.1 + ## Bugfixes - Stop implying `--no-ignore-parent` when `--no-vcs-ignore` is supplied, see #907, #901, #908 (@tmccombs) @@ -17,9 +32,6 @@ - Updated man page, see #912 (@rlue) - Updated zsh completions, see #932 (@tmccombs) -## Other - - # v8.3.0 diff --git a/Cargo.lock b/Cargo.lock index 404cec8..9b3edec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,7 +148,7 @@ dependencies = [ [[package]] name = "fd-find" -version = "8.3.0" +version = "8.3.1" dependencies = [ "ansi_term", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index b334fb2..f1a74db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ license = "MIT/Apache-2.0" name = "fd-find" readme = "README.md" repository = "https://github.com/sharkdp/fd" -version = "8.3.0" +version = "8.3.1" edition= "2018" [badges.appveyor] diff --git a/README.md b/README.md index 85894b0..d844163 100644 --- a/README.md +++ b/README.md @@ -535,7 +535,7 @@ Make sure that `$HOME/.local/bin` is in your `$PATH`. If you use an older version of Ubuntu, you can download the latest `.deb` package from the [release page](https://github.com/sharkdp/fd/releases) and install it via: ``` bash -sudo dpkg -i fd_8.3.0_amd64.deb # adapt version number and architecture +sudo dpkg -i fd_8.3.1_amd64.deb # adapt version number and architecture ``` ### On Debian From ef4abfc1d21b24418a7619215e8ee3dc42e6c4d1 Mon Sep 17 00:00:00 2001 From: Gabriel Barta Date: Fri, 7 Jan 2022 10:53:03 +1100 Subject: [PATCH 17/46] Update normpath to 0.3.2 to fix issue #931 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b3edec..da514c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,9 +345,9 @@ dependencies = [ [[package]] name = "normpath" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "640c20e9df4a2d4a5adad5b47e17d76dac3e824346b181931c3ec9f7a85687b1" +checksum = "04aaf5e9cb0fbf883cc0423159eacdf96a9878022084b35c462c428cab73bcaf" dependencies = [ "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index f1a74db..53007be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ lscolors = "0.8" globset = "0.4" anyhow = "1.0" dirs-next = "2.0" -normpath = "0.3" +normpath = "0.3.2" chrono = "0.4" once_cell = "1.9.0" From 06cd391845c0039dc70bd8dd972bdaf36b454872 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Fri, 7 Jan 2022 03:08:22 -0700 Subject: [PATCH 18/46] Change test_opposing to be less flaky. Make it resilient to the different invocations returning results in different orders. --- tests/testenv/mod.rs | 21 ++++++++++++++------- tests/tests.rs | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tests/testenv/mod.rs b/tests/testenv/mod.rs index cc439bc..510a7b2 100644 --- a/tests/testenv/mod.rs +++ b/tests/testenv/mod.rs @@ -203,6 +203,19 @@ impl TestEnv { output } + pub fn assert_success_and_get_normalized_output>( + &self, + path: P, + args: &[&str], + ) -> String { + let output = self.assert_success_and_get_output(path, args); + normalize_output( + &String::from_utf8_lossy(&output.stdout), + false, + self.normalize_line, + ) + } + /// Assert that calling *fd* with the specified arguments produces the expected output. pub fn assert_output(&self, args: &[&str], expected: &str) { self.assert_output_subdirectory(".", args, expected) @@ -224,15 +237,9 @@ impl TestEnv { args: &[&str], expected: &str, ) { - let output = self.assert_success_and_get_output(path, args); - // Normalize both expected and actual output. let expected = normalize_output(expected, true, self.normalize_line); - let actual = normalize_output( - &String::from_utf8_lossy(&output.stdout), - false, - self.normalize_line, - ); + let actual = self.assert_success_and_get_normalized_output(path, args); // Compare actual output to expected output. if expected != actual { diff --git a/tests/tests.rs b/tests/tests.rs index e6cee6c..fb0535c 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1970,8 +1970,8 @@ fn test_opposing(flag: &str, opposing_flags: &[&str]) { let mut flags = vec![flag]; flags.extend_from_slice(opposing_flags); - let out_no_flags = te.assert_success_and_get_output(".", &[]); - let out_opposing_flags = te.assert_success_and_get_output(".", &flags); + let out_no_flags = te.assert_success_and_get_normalized_output(".", &[]); + let out_opposing_flags = te.assert_success_and_get_normalized_output(".", &flags); assert_eq!( out_no_flags, From ec38e23d582e5e35cdeb5e57d5e3d86468ae2724 Mon Sep 17 00:00:00 2001 From: David Peter Date: Fri, 7 Jan 2022 17:39:24 +0100 Subject: [PATCH 19/46] Add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cdb9ae..f94d6a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ## Bugfixes +- Invalid absolute path on windows when searching from the drive root, see #931 and #936 (@gbarta) ## Changes From 43f276e0731b52ee9d07593dcdd6d702a10499ea Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Tue, 4 Jan 2022 00:35:49 -0700 Subject: [PATCH 20/46] Upgrade to clap 3.0 This wasn't backwards compatible so required some more substantial changes. --- Cargo.lock | 104 +++++++++++------- Cargo.toml | 7 +- build.rs | 11 +- src/app.rs | 250 ++++++++++++++++++++++--------------------- tests/testenv/mod.rs | 19 ++-- tests/tests.rs | 4 +- 6 files changed, 224 insertions(+), 171 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da514c7..94007af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,18 +85,28 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "f6f34b09b9ee8c7c7b400fe2f8df39cafc9538b03d6ba7f4ae13e4cb90bfbb7d" dependencies = [ - "ansi_term", "atty", "bitflags", + "indexmap", + "lazy_static", + "os_str_bytes", "strsim", - "term_size", + "termcolor", + "terminal_size", "textwrap", - "unicode-width", - "vec_map", +] + +[[package]] +name = "clap_complete" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a394f7ec0715b42a4e52b294984c27c9a61f77c8d82f7774c5198350be143f19" +dependencies = [ + "clap", ] [[package]] @@ -155,6 +165,7 @@ dependencies = [ "atty", "chrono", "clap", + "clap_complete", "ctrlc", "diff", "dirs-next", @@ -231,6 +242,12 @@ dependencies = [ "regex", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -264,6 +281,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "jemalloc-sys" version = "0.3.2" @@ -323,9 +350,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -388,19 +415,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] -name = "proc-macro2" -version = "1.0.32" +name = "os_str_bytes" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" dependencies = [ "proc-macro2", ] @@ -498,15 +534,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" dependencies = [ "proc-macro2", "quote", @@ -524,10 +560,19 @@ dependencies = [ ] [[package]] -name = "term_size" -version = "0.3.2" +name = "termcolor" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" dependencies = [ "libc", "winapi", @@ -548,12 +593,11 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.11.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" dependencies = [ - "term_size", - "unicode-width", + "terminal_size", ] [[package]] @@ -575,12 +619,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -597,12 +635,6 @@ dependencies = [ "log", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 53007be..420c6ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,8 @@ name = "fd" path = "src/main.rs" [build-dependencies] -clap = "2.34.0" +clap = "3.0" +clap_complete = "3.0" version_check = "0.9" [dependencies] @@ -51,8 +52,8 @@ chrono = "0.4" once_cell = "1.9.0" [dependencies.clap] -version = "2.34.0" -features = ["suggestions", "color", "wrap_help"] +version = "3.0" +features = ["suggestions", "color", "wrap_help", "cargo"] [target.'cfg(unix)'.dependencies] users = "0.11.0" diff --git a/build.rs b/build.rs index d2d9566..cb390f7 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,8 @@ use std::fs; -use clap::Shell; +use clap_complete::{generate_to, Shell}; +use Shell::*; +//use clap_complete::shells::Shel{Bash, Fish, PowerShell, Elvish}; include!("src/app.rs"); @@ -24,7 +26,8 @@ fn main() { fs::create_dir_all(&outdir).unwrap(); let mut app = build_app(); - app.gen_completions("fd", Shell::Bash, &outdir); - app.gen_completions("fd", Shell::Fish, &outdir); - app.gen_completions("fd", Shell::PowerShell, &outdir); + // NOTE: zsh completions are hand written in contrib/completion/_fd + for shell in [Bash, PowerShell, Fish, Elvish] { + generate_to(shell, &mut app, "fd", &outdir).unwrap(); + } } diff --git a/src/app.rs b/src/app.rs index dd4282b..bbf41b3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,25 +1,25 @@ -use clap::{crate_version, App, AppSettings, Arg}; +use clap::{crate_version, App, AppSettings, Arg, ColorChoice}; -pub fn build_app() -> App<'static, 'static> { - let clap_color_setting = if std::env::var_os("NO_COLOR").is_none() { - AppSettings::ColoredHelp +pub fn build_app() -> App<'static> { + let clap_color_choice = if std::env::var_os("NO_COLOR").is_none() { + ColorChoice::Auto } else { - AppSettings::ColorNever + ColorChoice::Never }; let mut app = App::new("fd") .version(crate_version!()) - .usage("fd [FLAGS/OPTIONS] [] [...]") - .setting(clap_color_setting) + .color(clap_color_choice) .setting(AppSettings::DeriveDisplayOrder) + .setting(AppSettings::DontCollapseArgsInUsage) .after_help( "Note: `fd -h` prints a short and concise overview while `fd --help` gives all \ details.", ) .arg( - Arg::with_name("hidden") + Arg::new("hidden") .long("hidden") - .short("H") + .short('H') .overrides_with("hidden") .help("Search hidden files and directories") .long_help( @@ -30,18 +30,18 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("no-hidden") + Arg::new("no-hidden") .long("no-hidden") .overrides_with("hidden") - .hidden(true) + .hide(true) .long_help( "Overrides --hidden.", ), ) .arg( - Arg::with_name("no-ignore") + Arg::new("no-ignore") .long("no-ignore") - .short("I") + .short('I') .overrides_with("no-ignore") .help("Do not respect .(git|fd)ignore files") .long_help( @@ -51,19 +51,19 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("ignore") + Arg::new("ignore") .long("ignore") .overrides_with("no-ignore") - .hidden(true) + .hide(true) .long_help( "Overrides --no-ignore.", ), ) .arg( - Arg::with_name("no-ignore-vcs") + Arg::new("no-ignore-vcs") .long("no-ignore-vcs") .overrides_with("no-ignore-vcs") - .hidden_short_help(true) + .hide_short_help(true) .help("Do not respect .gitignore files") .long_help( "Show search results from files and directories that would otherwise be \ @@ -71,19 +71,19 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("ignore-vcs") + Arg::new("ignore-vcs") .long("ignore-vcs") .overrides_with("no-ignore-vcs") - .hidden(true) + .hide(true) .long_help( "Overrides --no-ignore-vcs.", ), ) .arg( - Arg::with_name("no-ignore-parent") + Arg::new("no-ignore-parent") .long("no-ignore-parent") .overrides_with("no-ignore-parent") - .hidden_short_help(true) + .hide_short_help(true) .help("Do not respect .(git|fd)ignore files in parent directories") .long_help( "Show search results from files and directories that would otherwise be \ @@ -91,19 +91,19 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("no-global-ignore-file") + Arg::new("no-global-ignore-file") .long("no-global-ignore-file") - .hidden(true) + .hide(true) .help("Do not respect the global ignore file") .long_help("Do not respect the global ignore file."), ) .arg( - Arg::with_name("rg-alias-hidden-ignore") - .short("u") + Arg::new("rg-alias-hidden-ignore") + .short('u') .long("unrestricted") .overrides_with_all(&["ignore", "no-hidden"]) - .multiple(true) - .hidden_short_help(true) + .multiple_occurrences(true) + .hide_short_help(true) .help("Alias for '--no-ignore', and '--hidden' when given twice") .long_help( "Alias for '--no-ignore'. Can be repeated. '-uu' is an alias for \ @@ -111,9 +111,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("case-sensitive") + Arg::new("case-sensitive") .long("case-sensitive") - .short("s") + .short('s') .overrides_with_all(&["ignore-case", "case-sensitive"]) .help("Case-sensitive search (default: smart case)") .long_help( @@ -123,9 +123,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("ignore-case") + Arg::new("ignore-case") .long("ignore-case") - .short("i") + .short('i') .overrides_with_all(&["case-sensitive", "ignore-case"]) .help("Case-insensitive search (default: smart case)") .long_help( @@ -135,19 +135,19 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("glob") + Arg::new("glob") .long("glob") - .short("g") + .short('g') .conflicts_with("fixed-strings") .overrides_with("glob") .help("Glob-based search (default: regular expression)") .long_help("Perform a glob-based search instead of a regular expression search."), ) .arg( - Arg::with_name("regex") + Arg::new("regex") .long("regex") .overrides_with_all(&["glob", "regex"]) - .hidden_short_help(true) + .hide_short_help(true) .help("Regular-expression based search (default)") .long_help( "Perform a regular-expression based search (default). This can be used to \ @@ -155,12 +155,12 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("fixed-strings") + Arg::new("fixed-strings") .long("fixed-strings") - .short("F") + .short('F') .alias("literal") .overrides_with("fixed-strings") - .hidden_short_help(true) + .hide_short_help(true) .help("Treat pattern as literal string instead of regex") .long_help( "Treat the pattern as a literal string instead of a regular expression. Note \ @@ -169,9 +169,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("absolute-path") + Arg::new("absolute-path") .long("absolute-path") - .short("a") + .short('a') .overrides_with("absolute-path") .help("Show absolute instead of relative paths") .long_help( @@ -180,18 +180,18 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("relative-path") + Arg::new("relative-path") .long("relative-path") .overrides_with("absolute-path") - .hidden(true) + .hide(true) .long_help( "Overrides --absolute-path.", ), ) .arg( - Arg::with_name("list-details") + Arg::new("list-details") .long("list-details") - .short("l") + .short('l') .conflicts_with("absolute-path") .help("Use a long listing format with file metadata") .long_help( @@ -202,9 +202,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("follow") + Arg::new("follow") .long("follow") - .short("L") + .short('L') .alias("dereference") .overrides_with("follow") .help("Follow symbolic links") @@ -215,18 +215,18 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("no-follow") + Arg::new("no-follow") .long("no-follow") .overrides_with("follow") - .hidden(true) + .hide(true) .long_help( "Overrides --follow.", ), ) .arg( - Arg::with_name("full-path") + Arg::new("full-path") .long("full-path") - .short("p") + .short('p') .overrides_with("full-path") .help("Search full abs. path (default: filename only)") .long_help( @@ -237,12 +237,12 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("null_separator") + Arg::new("null_separator") .long("print0") - .short("0") + .short('0') .overrides_with("print0") .conflicts_with("list-details") - .hidden_short_help(true) + .hide_short_help(true) .help("Separate results by the null character") .long_help( "Separate search results by the null character (instead of newlines). \ @@ -250,9 +250,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("max-depth") + Arg::new("max-depth") .long("max-depth") - .short("d") + .short('d') .takes_value(true) .value_name("depth") .help("Set maximum search depth (default: none)") @@ -263,18 +263,18 @@ pub fn build_app() -> App<'static, 'static> { ) // support --maxdepth as well, for compatibility with rg .arg( - Arg::with_name("rg-depth") + Arg::new("rg-depth") .long("maxdepth") - .hidden(true) + .hide(true) .takes_value(true) .help("Set maximum search depth (default: none)") ) .arg( - Arg::with_name("min-depth") + Arg::new("min-depth") .long("min-depth") .takes_value(true) .value_name("depth") - .hidden_short_help(true) + .hide_short_help(true) .help("Only show results starting at given depth") .long_help( "Only show search results starting at the given depth. \ @@ -282,11 +282,11 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("exact-depth") + Arg::new("exact-depth") .long("exact-depth") .takes_value(true) .value_name("depth") - .hidden_short_help(true) + .hide_short_help(true) .conflicts_with_all(&["max-depth", "min-depth"]) .help("Only show results at exact given depth") .long_help( @@ -295,19 +295,19 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("prune") + Arg::new("prune") .long("prune") .conflicts_with_all(&["size", "exact-depth"]) - .hidden_short_help(true) + .hide_short_help(true) .help("Do not traverse into matching directories") .long_help("Do not traverse into directories that match the search criteria. If \ you want to exclude specific directories, use the '--exclude=…' option.") ) .arg( - Arg::with_name("file-type") + Arg::new("file-type") .long("type") - .short("t") - .multiple(true) + .short('t') + .multiple_occurrences(true) .number_of_values(1) .takes_value(true) .value_name("filetype") @@ -366,10 +366,10 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("extension") + Arg::new("extension") .long("extension") - .short("e") - .multiple(true) + .short('e') + .multiple_occurrences(true) .number_of_values(1) .takes_value(true) .value_name("ext") @@ -382,9 +382,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("exec") + Arg::new("exec") .long("exec") - .short("x") + .short('x') .min_values(1) .allow_hyphen_values(true) .value_terminator(";") @@ -413,9 +413,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("exec-batch") + Arg::new("exec-batch") .long("exec-batch") - .short("X") + .short('X') .min_values(1) .allow_hyphen_values(true) .value_terminator(";") @@ -440,11 +440,11 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("batch-size") + Arg::new("batch-size") .long("batch-size") .takes_value(true) .value_name("size") - .hidden_short_help(true) + .hide_short_help(true) .requires("exec-batch") .help("Max number of arguments to run as a batch with -X") .long_help( @@ -455,13 +455,13 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("exclude") + Arg::new("exclude") .long("exclude") - .short("E") + .short('E') .takes_value(true) .value_name("pattern") .number_of_values(1) - .multiple(true) + .multiple_occurrences(true) .help("Exclude entries that match the given glob pattern") .long_help( "Exclude files/directories that match the given glob pattern. This \ @@ -473,13 +473,13 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("ignore-file") + Arg::new("ignore-file") .long("ignore-file") .takes_value(true) .value_name("path") .number_of_values(1) - .multiple(true) - .hidden_short_help(true) + .multiple_occurrences(true) + .hide_short_help(true) .help("Add custom ignore-file in '.gitignore' format") .long_help( "Add a custom ignore-file in '.gitignore' format. These files have a low \ @@ -487,9 +487,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("color") + Arg::new("color") .long("color") - .short("c") + .short('c') .takes_value(true) .value_name("when") .possible_values(&["never", "auto", "always"]) @@ -503,12 +503,12 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("threads") + Arg::new("threads") .long("threads") - .short("j") + .short('j') .takes_value(true) .value_name("num") - .hidden_short_help(true) + .hide_short_help(true) .help("Set number of threads") .long_help( "Set number of threads to use for searching & executing (default: number \ @@ -516,13 +516,13 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("size") + Arg::new("size") .long("size") - .short("S") + .short('S') .takes_value(true) .number_of_values(1) .allow_hyphen_values(true) - .multiple(true) + .multiple_occurrences(true) .help("Limit results based on the size of files") .long_help( "Limit results based on the size of files using the format <+->.\n \ @@ -544,10 +544,10 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("max-buffer-time") + Arg::new("max-buffer-time") .long("max-buffer-time") .takes_value(true) - .hidden(true) + .hide(true) .help("Milliseconds to buffer before streaming search results to console") .long_help( "Amount of time in milliseconds to buffer, before streaming the search \ @@ -555,7 +555,7 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("changed-within") + Arg::new("changed-within") .long("changed-within") .alias("change-newer-than") .alias("newer") @@ -575,7 +575,7 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("changed-before") + Arg::new("changed-before") .long("changed-before") .alias("change-older-than") .alias("older") @@ -594,7 +594,7 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("max-results") + Arg::new("max-results") .long("max-results") .takes_value(true) .value_name("count") @@ -604,14 +604,14 @@ pub fn build_app() -> App<'static, 'static> { // same search with `--exec rm` attached and get a reliable removal of // the files they saw in the previous search. .conflicts_with_all(&["exec", "exec-batch", "list-details"]) - .hidden_short_help(true) + .hide_short_help(true) .help("Limit number of search results") .long_help("Limit the number of search results to 'count' and quit immediately."), ) .arg( - Arg::with_name("max-one-result") - .short("1") - .hidden_short_help(true) + Arg::new("max-one-result") + .short('1') + .hide_short_help(true) .overrides_with("max-results") .conflicts_with_all(&["exec", "exec-batch", "list-details"]) .help("Limit search to a single result") @@ -619,11 +619,11 @@ pub fn build_app() -> App<'static, 'static> { This is an alias for '--max-results=1'.") ) .arg( - Arg::with_name("quiet") + Arg::new("quiet") .long("quiet") - .short("q") + .short('q') .alias("has-results") - .hidden_short_help(true) + .hide_short_help(true) .conflicts_with_all(&["exec", "exec-batch", "list-details", "max-results"]) .help("Print nothing, exit code 0 if match found, 1 otherwise") .long_help( @@ -634,9 +634,9 @@ pub fn build_app() -> App<'static, 'static> { ) ) .arg( - Arg::with_name("show-errors") + Arg::new("show-errors") .long("show-errors") - .hidden_short_help(true) + .hide_short_help(true) .overrides_with("show-errors") .help("Show filesystem errors") .long_help( @@ -645,12 +645,13 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("base-directory") + Arg::new("base-directory") .long("base-directory") .takes_value(true) .value_name("path") .number_of_values(1) - .hidden_short_help(true) + .allow_invalid_utf8(true) + .hide_short_help(true) .help("Change current working directory") .long_help( "Change the current working directory of fd to the provided path. This \ @@ -661,7 +662,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("pattern").help( + Arg::new("pattern") + .allow_invalid_utf8(true) + .help( "the search pattern (a regular expression, unless '--glob' is used; optional)", ).long_help( "the search pattern which is either a regular expression (default) or a glob \ @@ -670,11 +673,11 @@ pub fn build_app() -> App<'static, 'static> { pass '--' first, or it will be considered as a flag (fd -- '-foo').") ) .arg( - Arg::with_name("path-separator") + Arg::new("path-separator") .takes_value(true) .value_name("separator") .long("path-separator") - .hidden_short_help(true) + .hide_short_help(true) .help("Set path separator when printing file paths") .long_help( "Set the path separator to use when printing file paths. The default is \ @@ -682,8 +685,9 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("path") - .multiple(true) + Arg::new("path") + .multiple_occurrences(true) + .allow_invalid_utf8(true) .help("the root directory for the filesystem search (optional)") .long_help( "The directory where the filesystem search is rooted (optional). If \ @@ -691,25 +695,26 @@ pub fn build_app() -> App<'static, 'static> { ), ) .arg( - Arg::with_name("search-path") + Arg::new("search-path") .long("search-path") .takes_value(true) .conflicts_with("path") - .multiple(true) - .hidden_short_help(true) + .multiple_occurrences(true) + .hide_short_help(true) .number_of_values(1) + .allow_invalid_utf8(true) .help("Provide paths to search as an alternative to the positional ") .long_help( "Provide paths to search as an alternative to the positional \ - argument. Changes the usage to `fd [FLAGS/OPTIONS] --search-path \ + argument. Changes the usage to `fd [OPTIONS] --search-path \ --search-path []`", ), ) .arg( - Arg::with_name("strip-cwd-prefix") + Arg::new("strip-cwd-prefix") .long("strip-cwd-prefix") .conflicts_with_all(&["path", "search-path"]) - .hidden_short_help(true) + .hide_short_help(true) .help("strip './' prefix from non-tty outputs") .long_help( "By default, relative paths are prefixed with './' when the output goes to a non \ @@ -719,9 +724,9 @@ pub fn build_app() -> App<'static, 'static> { if cfg!(unix) { app = app.arg( - Arg::with_name("owner") + Arg::new("owner") .long("owner") - .short("o") + .short('o') .takes_value(true) .value_name("user:group") .help("Filter by owning user and/or group") @@ -742,10 +747,10 @@ pub fn build_app() -> App<'static, 'static> { // Provide aliases `mount` and `xdev` for people coming from `find`. if cfg!(any(unix, windows)) { app = app.arg( - Arg::with_name("one-file-system") + Arg::new("one-file-system") .long("one-file-system") .aliases(&["mount", "xdev"]) - .hidden_short_help(true) + .hide_short_help(true) .help("Do not descend into a different file system") .long_help( "By default, fd will traverse the file system tree as far as other options \ @@ -758,3 +763,8 @@ pub fn build_app() -> App<'static, 'static> { app } + +#[test] +fn verify_app() { + build_app().debug_assert() +} diff --git a/tests/testenv/mod.rs b/tests/testenv/mod.rs index 510a7b2..c17ef4b 100644 --- a/tests/testenv/mod.rs +++ b/tests/testenv/mod.rs @@ -130,6 +130,17 @@ fn normalize_output(s: &str, trim_start: bool, normalize_line: bool) -> String { lines.join("\n") } +/// Trim whitespace from the beginning of each line. +fn trim_lines(s: &str) -> String { + s.lines() + .map(|line| line.trim_start()) + .fold(String::new(), |mut str, line| { + str.push_str(line); + str.push('\n'); + str + }) +} + impl TestEnv { pub fn new(directories: &[&'static str], files: &[&'static str]) -> TestEnv { let temp_dir = create_working_directory(directories, files).expect("working directory"); @@ -287,12 +298,8 @@ impl TestEnv { if let Some(expected) = expected { // Normalize both expected and actual output. - let expected_error = normalize_output(expected, true, self.normalize_line); - let actual_err = normalize_output( - &String::from_utf8_lossy(&output.stderr), - false, - self.normalize_line, - ); + let expected_error = trim_lines(expected); + let actual_err = trim_lines(&String::from_utf8_lossy(&output.stderr)); // Compare actual output to expected output. if !actual_err.trim_start().starts_with(&expected_error) { diff --git a/tests/tests.rs b/tests/tests.rs index fb0535c..ec95a9c 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1420,12 +1420,12 @@ fn test_exec_batch() { te.assert_failure_with_error( &["foo", "--exec-batch", "echo", "{/}", ";", "-x", "echo"], - "error: The argument '--exec ' cannot be used with '--exec-batch '", + "error: The argument '--exec-batch ...' cannot be used with '--exec ...'", ); te.assert_failure_with_error( &["foo", "--exec-batch"], - "error: The argument '--exec-batch ' requires a value but none was supplied", + "error: The argument '--exec-batch ...' requires a value but none was supplied", ); te.assert_failure_with_error( From 2e9be3e3f51a2191863d53c164c96e71864fdadd Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Wed, 5 Jan 2022 02:19:17 -0700 Subject: [PATCH 21/46] Bump MSRV to 1.54 Because that is needed by clap 3.0 --- .github/workflows/CICD.yml | 2 +- README.md | 2 +- build.rs | 2 +- clippy.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index b84459f..43f9078 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -1,7 +1,7 @@ name: CICD env: - MIN_SUPPORTED_RUST_VERSION: "1.53.0" + MIN_SUPPORTED_RUST_VERSION: "1.54.0" CICD_INTERMEDIATES_DIR: "_cicd-intermediates" on: diff --git a/README.md b/README.md index d844163..fda727e 100644 --- a/README.md +++ b/README.md @@ -652,7 +652,7 @@ With Rust's package manager [cargo](https://github.com/rust-lang/cargo), you can ``` cargo install fd-find ``` -Note that rust version *1.53.0* or later is required. +Note that rust version *1.54.0* or later is required. `make` is also needed for the build. diff --git a/build.rs b/build.rs index cb390f7..4a24cd8 100644 --- a/build.rs +++ b/build.rs @@ -7,7 +7,7 @@ use Shell::*; include!("src/app.rs"); fn main() { - let min_version = "1.53"; + let min_version = "1.54"; match version_check::is_min_version(min_version) { Some(true) => {} diff --git a/clippy.toml b/clippy.toml index e51b4f3..0f31b88 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.53.0" +msrv = "1.54.0" From 4377954cf9f8eae9d1ded194dab7912fc47bcbed Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 29 Jan 2022 12:51:16 +0100 Subject: [PATCH 22/46] Add tavianator sponsoring link --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..c81bc07 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [sharkdp, tavianator] From b3399c239bfc702915606c415b5ce9f755e9d437 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 29 Jan 2022 12:48:19 +0100 Subject: [PATCH 23/46] Add clippy run in CI/CD --- .github/workflows/CICD.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 43f9078..a40f409 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -46,11 +46,18 @@ jobs: steps: - name: Checkout source code uses: actions/checkout@v2 + - name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }}) uses: actions-rs/toolchain@v1 with: toolchain: ${{ env.MIN_SUPPORTED_RUST_VERSION }} default: true + components: clippy + - name: Run clippy (on minimum supported rust version to prevent warnings we can't fix) + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --locked --all-targets --all-features profile: minimal # minimal component installation (ie, no documentation) - name: Run tests uses: actions-rs/cargo@v1 From c48d02e0a9f50a7aeb8fa86b4b5f39588753ddab Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 29 Jan 2022 16:49:09 +0100 Subject: [PATCH 24/46] Bump version to v8.3.2 --- CHANGELOG.md | 6 +++++- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f94d6a1..5ef3b18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ ## Bugfixes -- Invalid absolute path on windows when searching from the drive root, see #931 and #936 (@gbarta) ## Changes @@ -16,6 +15,11 @@ ## Other +# v8.3.2 + +## Bugfixes + +- Invalid absolute path on windows when searching from the drive root, see #931 and #936 (@gbarta) # v8.3.1 diff --git a/Cargo.lock b/Cargo.lock index 94007af..cf60919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,7 +158,7 @@ dependencies = [ [[package]] name = "fd-find" -version = "8.3.1" +version = "8.3.2" dependencies = [ "ansi_term", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 420c6ea..81526e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ license = "MIT/Apache-2.0" name = "fd-find" readme = "README.md" repository = "https://github.com/sharkdp/fd" -version = "8.3.1" +version = "8.3.2" edition= "2018" [badges.appveyor] diff --git a/README.md b/README.md index fda727e..e11a7c8 100644 --- a/README.md +++ b/README.md @@ -535,7 +535,7 @@ Make sure that `$HOME/.local/bin` is in your `$PATH`. If you use an older version of Ubuntu, you can download the latest `.deb` package from the [release page](https://github.com/sharkdp/fd/releases) and install it via: ``` bash -sudo dpkg -i fd_8.3.1_amd64.deb # adapt version number and architecture +sudo dpkg -i fd_8.3.2_amd64.deb # adapt version number and architecture ``` ### On Debian From 9f5ed8534e824b3e2a0934ff3aa0b781cb370688 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 29 Jan 2022 16:53:13 +0100 Subject: [PATCH 25/46] Add temporary version of logo --- doc/logo.png | Bin 0 -> 10183 bytes doc/logo.svg | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 doc/logo.png create mode 100644 doc/logo.svg diff --git a/doc/logo.png b/doc/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..483dfdacfde2371d71bdc0137d091538e89defa3 GIT binary patch literal 10183 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 + + + + + + + + + + + fd + fd + + + + + + + + + + + + + + + + + + + + + + From 1844ed6b8c3c351ec38c45c3d7221179efffeec2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 17:03:32 +0000 Subject: [PATCH 26/46] Bump clap from 3.0.5 to 3.0.13 Bumps [clap](https://github.com/clap-rs/clap) from 3.0.5 to 3.0.13. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v3.0.5...v3.0.13) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf60919..296dad0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.5" +version = "3.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f34b09b9ee8c7c7b400fe2f8df39cafc9538b03d6ba7f4ae13e4cb90bfbb7d" +checksum = "08799f92c961c7a1cf0cc398a9073da99e21ce388b46372c37f3191f2f3eed3e" dependencies = [ "atty", "bitflags", From abaed6686d8e5fc112cfa83267bb725edefb179c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 17:03:39 +0000 Subject: [PATCH 27/46] Bump clap_complete from 3.0.2 to 3.0.5 Bumps [clap_complete](https://github.com/clap-rs/clap) from 3.0.2 to 3.0.5. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v3.0.2...clap_complete-v3.0.5) --- updated-dependencies: - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf60919..b19ba07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,9 +102,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.0.2" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a394f7ec0715b42a4e52b294984c27c9a61f77c8d82f7774c5198350be143f19" +checksum = "be4dabb7e2f006497e1da045feaa512acf0686f76b68d94925da2d9422dcb521" dependencies = [ "clap", ] From 2395e7cac55201f89c36d1198834e12eaebd51f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 17:03:42 +0000 Subject: [PATCH 28/46] Bump anyhow from 1.0.52 to 1.0.53 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.52 to 1.0.53. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.52...1.0.53) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf60919..dbe7cc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" +checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" [[package]] name = "atty" From 43f683469b1851f7a8425b0c1a92034280e4b258 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 17:03:47 +0000 Subject: [PATCH 29/46] Bump libc from 0.2.112 to 0.2.116 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.112 to 0.2.116. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.112...0.2.116) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf60919..f8d74e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,9 +320,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" [[package]] name = "log" From 1ac2c38b6b2c1e2906d62fd419ebe6ea71941134 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 17:03:57 +0000 Subject: [PATCH 30/46] Bump libc from 0.2.116 to 0.2.119 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.116 to 0.2.119. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.116...0.2.119) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ada7e32..a51dfab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,9 +320,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.116" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "log" From 4e0b193ab6f813cf6123466429d7193a4d4ddbf9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 17:04:08 +0000 Subject: [PATCH 31/46] Bump anyhow from 1.0.53 to 1.0.55 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.53 to 1.0.55. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.53...1.0.55) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a51dfab..c3a1b93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.53" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" [[package]] name = "atty" From efedd9c4e0395b22a223bdd7328334ce0a14376e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 20:29:59 +0000 Subject: [PATCH 32/46] Bump test-case from 1.2.1 to 2.0.0 Bumps [test-case](https://github.com/frondeus/test-case) from 1.2.1 to 2.0.0. - [Release notes](https://github.com/frondeus/test-case/releases) - [Changelog](https://github.com/frondeus/test-case/blob/master/CHANGELOG.md) - [Commits](https://github.com/frondeus/test-case/compare/v1.2.1...v2.0.0) --- updated-dependencies: - dependency-name: test-case dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 34 +++++++++++++++++++++++++++++----- Cargo.toml | 2 +- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ada7e32..115285c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,9 +320,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.116" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "log" @@ -423,6 +423,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.36" @@ -580,15 +604,15 @@ dependencies = [ [[package]] name = "test-case" -version = "1.2.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cad0a06f9a61e94355aa3b3dc92d85ab9c83406722b1ca5e918d4297c12c23" +checksum = "4f7d58e237f65d5fe5eaf1105188c94c9a441e1fbc298ed5df45ec9c9af236d3" dependencies = [ "cfg-if", + "proc-macro-error", "proc-macro2", "quote", "syn", - "version_check", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 81526e7..6ae27a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ jemallocator = {version = "0.3.0", optional = true} diff = "0.1" tempdir = "0.3" filetime = "0.2" -test-case = "1.2" +test-case = "2.0" [profile.release] lto = true From 6b8056ca86a16ee7d780b0b790f10674170e5187 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Wed, 2 Mar 2022 00:49:30 -0700 Subject: [PATCH 33/46] More prominently document that fd uses regex by default Fixes: #948 --- doc/fd.1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/fd.1 b/doc/fd.1 index b5809c7..f917b12 100644 --- a/doc/fd.1 +++ b/doc/fd.1 @@ -24,6 +24,11 @@ fd \- find entries in the filesystem .B fd is a simple, fast and user-friendly alternative to .BR find (1). +.P +By default +.B fd +uses regular expressions for the pattern. However, this can be changed to use simple glob patterns +with the '\-\-glob' option. .SH OPTIONS .TP .B \-H, \-\-hidden From bbdb8b9d9e74c2c8b5cbe3fac4b6af5f12955c10 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Mon, 28 Feb 2022 00:48:57 -0700 Subject: [PATCH 34/46] Upgrade to clap 3.1 And fix deprecations --- Cargo.lock | 48 ++++++++++++++++++++++++------------------------ Cargo.toml | 4 ++-- src/app.rs | 8 ++++---- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9ec58f..476b796 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -60,9 +60,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.13" +version = "3.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08799f92c961c7a1cf0cc398a9073da99e21ce388b46372c37f3191f2f3eed3e" +checksum = "ced1892c55c910c1219e98d6fc8d71f6bddba7905866ce740066d8bfea859312" dependencies = [ "atty", "bitflags", @@ -102,18 +102,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.0.5" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dabb7e2f006497e1da045feaa512acf0686f76b68d94925da2d9422dcb521" +checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25" dependencies = [ "clap", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ "cfg-if", "lazy_static", @@ -220,9 +220,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if", "libc", @@ -458,9 +458,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] @@ -504,9 +504,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] @@ -564,9 +564,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -585,9 +585,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -617,18 +617,18 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" dependencies = [ "terminal_size", ] [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] diff --git a/Cargo.toml b/Cargo.toml index 6ae27a3..0305137 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,8 +30,8 @@ name = "fd" path = "src/main.rs" [build-dependencies] -clap = "3.0" -clap_complete = "3.0" +clap = "3.1" +clap_complete = "3.1" version_check = "0.9" [dependencies] diff --git a/src/app.rs b/src/app.rs index bbf41b3..4ceebcd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,17 +1,17 @@ -use clap::{crate_version, App, AppSettings, Arg, ColorChoice}; +use clap::{crate_version, AppSettings, Arg, ColorChoice, Command}; -pub fn build_app() -> App<'static> { +pub fn build_app() -> Command<'static> { let clap_color_choice = if std::env::var_os("NO_COLOR").is_none() { ColorChoice::Auto } else { ColorChoice::Never }; - let mut app = App::new("fd") + let mut app = Command::new("fd") .version(crate_version!()) .color(clap_color_choice) .setting(AppSettings::DeriveDisplayOrder) - .setting(AppSettings::DontCollapseArgsInUsage) + .dont_collapse_args_in_usage(true) .after_help( "Note: `fd -h` prints a short and concise overview while `fd --help` gives all \ details.", From 6e5c8d9c20f6006592ba34f237eabef7389c7c5c Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Mon, 28 Feb 2022 01:16:42 -0700 Subject: [PATCH 35/46] Fix some clippy warnings --- src/exec/input.rs | 4 ++-- src/main.rs | 2 +- src/walk.rs | 10 ++-------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/exec/input.rs b/src/exec/input.rs index d803eae..af7ba25 100644 --- a/src/exec/input.rs +++ b/src/exec/input.rs @@ -5,13 +5,13 @@ use crate::filesystem::strip_current_dir; /// Removes the parent component of the path pub fn basename(path: &Path) -> &OsStr { - path.file_name().unwrap_or_else(|| path.as_os_str()) + path.file_name().unwrap_or(path.as_os_str()) } /// Removes the extension from the path pub fn remove_extension(path: &Path) -> OsString { let dirname = dirname(path); - let stem = path.file_stem().unwrap_or_else(|| path.as_os_str()); + let stem = path.file_stem().unwrap_or(path.as_os_str()); let path = PathBuf::from(dirname).join(stem); diff --git a/src/main.rs b/src/main.rs index 2eccd06..7e55da1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,7 +112,7 @@ fn ensure_current_directory_exists(current_directory: &Path) -> Result<()> { } } -fn extract_search_pattern<'a>(matches: &'a clap::ArgMatches) -> Result<&'a str> { +fn extract_search_pattern(matches: &clap::ArgMatches) -> Result<&'_ str> { let pattern = matches .value_of_os("pattern") .map(|p| { diff --git a/src/walk.rs b/src/walk.rs index 0d412ba..4343bc3 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -104,10 +104,7 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> R match result { Some(ignore::Error::Partial(_)) => (), Some(err) => { - print_error(format!( - "Malformed pattern in global ignore file. {}.", - err.to_string() - )); + print_error(format!("Malformed pattern in global ignore file. {}.", err)); } None => (), } @@ -119,10 +116,7 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> R match result { Some(ignore::Error::Partial(_)) => (), Some(err) => { - print_error(format!( - "Malformed pattern in custom ignore file. {}.", - err.to_string() - )); + print_error(format!("Malformed pattern in custom ignore file. {}.", err)); } None => (), } From ba473fc92571ed0bb4a4815c457ff504e2519eb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 17:04:03 +0000 Subject: [PATCH 36/46] Bump lscolors from 0.8.1 to 0.9.0 Bumps [lscolors](https://github.com/sharkdp/lscolors) from 0.8.1 to 0.9.0. - [Release notes](https://github.com/sharkdp/lscolors/releases) - [Commits](https://github.com/sharkdp/lscolors/compare/v0.8.1...v0.9.0) --- updated-dependencies: - dependency-name: lscolors dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 2 +- Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- README.md | 2 +- build.rs | 2 +- clippy.toml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index a40f409..930db3b 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -1,7 +1,7 @@ name: CICD env: - MIN_SUPPORTED_RUST_VERSION: "1.54.0" + MIN_SUPPORTED_RUST_VERSION: "1.56.0" CICD_INTERMEDIATES_DIR: "_cicd-intermediates" on: diff --git a/Cargo.lock b/Cargo.lock index 476b796..8895415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "lscolors" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd58d8727f3035fa6d5272f16b519741fd4875936b99d8a7cde21291b7d9174" +checksum = "4e9323b3525d4efad2dead1837a105e313253bfdbad1d470994038eededa4d62" dependencies = [ "ansi_term", ] diff --git a/Cargo.toml b/Cargo.toml index 0305137..d20ea9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ name = "fd-find" readme = "README.md" repository = "https://github.com/sharkdp/fd" version = "8.3.2" -edition= "2018" +edition= "2021" [badges.appveyor] repository = "sharkdp/fd" @@ -43,7 +43,7 @@ regex = "1.5.4" regex-syntax = "0.6" ctrlc = "3.2" humantime = "2.1" -lscolors = "0.8" +lscolors = "0.9" globset = "0.4" anyhow = "1.0" dirs-next = "2.0" diff --git a/README.md b/README.md index e11a7c8..d7b3266 100644 --- a/README.md +++ b/README.md @@ -652,7 +652,7 @@ With Rust's package manager [cargo](https://github.com/rust-lang/cargo), you can ``` cargo install fd-find ``` -Note that rust version *1.54.0* or later is required. +Note that rust version *1.56.0* or later is required. `make` is also needed for the build. diff --git a/build.rs b/build.rs index 4a24cd8..d78641a 100644 --- a/build.rs +++ b/build.rs @@ -7,7 +7,7 @@ use Shell::*; include!("src/app.rs"); fn main() { - let min_version = "1.54"; + let min_version = "1.56"; match version_check::is_min_version(min_version) { Some(true) => {} diff --git a/clippy.toml b/clippy.toml index 0f31b88..0d369b5 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.54.0" +msrv = "1.56.0" From 0fd7ec5c2a5d59616c272fd5438f3187e3685412 Mon Sep 17 00:00:00 2001 From: David Peter Date: Fri, 4 Mar 2022 08:16:52 +0100 Subject: [PATCH 37/46] Fix missing clap feature --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d20ea9a..c939dc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ name = "fd" path = "src/main.rs" [build-dependencies] -clap = "3.1" +clap = { version = "3.1", features = ["cargo"] } clap_complete = "3.1" version_check = "0.9" @@ -52,7 +52,7 @@ chrono = "0.4" once_cell = "1.9.0" [dependencies.clap] -version = "3.0" +version = "3.1" features = ["suggestions", "color", "wrap_help", "cargo"] [target.'cfg(unix)'.dependencies] From 45f490a407fb012b6ac6c1e92c5eaca02f5ee9e1 Mon Sep 17 00:00:00 2001 From: Jacob Chapman <7908073+chapmanjacobd@users.noreply.github.com> Date: Tue, 8 Mar 2022 06:46:57 +0700 Subject: [PATCH 38/46] Looks like the COPR repo is no longer maintained or only available on fedora rawhide --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index d7b3266..ff114d1 100644 --- a/README.md +++ b/README.md @@ -557,12 +557,6 @@ Starting with Fedora 28, you can install `fd` from the official package sources: dnf install fd-find ``` -For older versions, you can use this [Fedora copr](https://copr.fedorainfracloud.org/coprs/keefle/fd/) to install `fd`: -``` bash -dnf copr enable keefle/fd -dnf install fd -``` - ### On Alpine Linux You can install [the fd package](https://pkgs.alpinelinux.org/packages?name=fd) From 0aee9b0fd950fbe4862f92e1445966a995ca06ee Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Fri, 18 Feb 2022 01:21:00 -0700 Subject: [PATCH 39/46] Support multiple `--exec` instances and `--exec-batch`. Fixes: #406 --- Cargo.toml | 2 +- src/app.rs | 2 + src/config.rs | 4 +- src/exec/job.rs | 12 +-- src/exec/mod.rs | 255 ++++++++++++++++++++++++++++++------------------ src/main.rs | 22 ++--- 6 files changed, 178 insertions(+), 119 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c939dc5..6502428 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ once_cell = "1.9.0" [dependencies.clap] version = "3.1" -features = ["suggestions", "color", "wrap_help", "cargo"] +features = ["suggestions", "color", "wrap_help", "cargo", "unstable-grouped"] [target.'cfg(unix)'.dependencies] users = "0.11.0" diff --git a/src/app.rs b/src/app.rs index 4ceebcd..01ddc1d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -386,6 +386,7 @@ pub fn build_app() -> Command<'static> { .long("exec") .short('x') .min_values(1) + .multiple_occurrences(true) .allow_hyphen_values(true) .value_terminator(";") .value_name("cmd") @@ -417,6 +418,7 @@ pub fn build_app() -> Command<'static> { .long("exec-batch") .short('X') .min_values(1) + .multiple_occurrences(true) .allow_hyphen_values(true) .value_terminator(";") .value_name("cmd") diff --git a/src/config.rs b/src/config.rs index 5a71714..697744b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,7 +3,7 @@ use std::{path::PathBuf, sync::Arc, time::Duration}; use lscolors::LsColors; use regex::bytes::RegexSet; -use crate::exec::CommandTemplate; +use crate::exec::CommandSet; use crate::filetypes::FileTypes; #[cfg(unix)] use crate::filter::OwnerFilter; @@ -83,7 +83,7 @@ pub struct Config { pub extensions: Option, /// If a value is supplied, each item found will be used to generate and execute commands. - pub command: Option>, + pub command: Option>, /// Maximum number of search results to pass to each `command`. If zero, the number is /// unlimited. diff --git a/src/exec/job.rs b/src/exec/job.rs index 85b30f1..feda262 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -6,14 +6,14 @@ use crate::error::print_error; use crate::exit_codes::{merge_exitcodes, ExitCode}; use crate::walk::WorkerResult; -use super::CommandTemplate; +use super::CommandSet; /// An event loop that listens for inputs from the `rx` receiver. Each received input will /// generate a command with the supplied command template. The generated command will then /// be executed, and this process will continue until the receiver's sender has closed. pub fn job( rx: Arc>>, - cmd: Arc, + cmd: Arc, out_perm: Arc>, show_filesystem_errors: bool, buffer_output: bool, @@ -39,7 +39,7 @@ pub fn job( // Drop the lock so that other threads can read from the receiver. drop(lock); // Generate a command, execute it and store its exit code. - results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm), buffer_output)) + results.push(cmd.execute(&value, Arc::clone(&out_perm), buffer_output)) } // Returns error in case of any error. merge_exitcodes(results) @@ -47,7 +47,7 @@ pub fn job( pub fn batch( rx: Receiver, - cmd: &CommandTemplate, + cmd: &CommandSet, show_filesystem_errors: bool, buffer_output: bool, limit: usize, @@ -63,14 +63,14 @@ pub fn batch( }); if limit == 0 { // no limit - return cmd.generate_and_execute_batch(paths, buffer_output); + return cmd.execute_batch(paths, buffer_output); } let mut exit_codes = Vec::new(); let mut peekable = paths.peekable(); while peekable.peek().is_some() { let limited = peekable.by_ref().take(limit); - let exit_code = cmd.generate_and_execute_batch(limited, buffer_output); + let exit_code = cmd.execute_batch(limited, buffer_output); exit_codes.push(exit_code); } merge_exitcodes(exit_codes) diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 3f93acd..e420c81 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -29,44 +29,101 @@ pub enum ExecutionMode { Batch, } +#[derive(Debug, Clone, PartialEq)] +pub struct CommandSet { + mode: ExecutionMode, + path_separator: Option, + commands: Vec, +} + +impl CommandSet { + pub fn new(input: I, path_separator: Option) -> CommandSet + where + I: IntoIterator>, + S: AsRef, + { + CommandSet { + mode: ExecutionMode::OneByOne, + path_separator, + commands: input.into_iter().map(CommandTemplate::new).collect(), + } + } + + pub fn new_batch(input: I, path_separator: Option) -> Result + where + I: IntoIterator>, + S: AsRef, + { + Ok(CommandSet { + mode: ExecutionMode::Batch, + path_separator, + commands: input + .into_iter() + .map(|args| { + let cmd = CommandTemplate::new(args); + if cmd.number_of_tokens() > 1 { + return Err(anyhow!("Only one placeholder allowed for batch commands")); + } + if cmd.args[0].has_tokens() { + return Err(anyhow!( + "First argument of exec-batch is expected to be a fixed executable" + )); + } + Ok(cmd) + }) + .collect::>>()?, + }) + } + + pub fn in_batch_mode(&self) -> bool { + self.mode == ExecutionMode::Batch + } + + pub fn execute( + &self, + input: &Path, + mut out_perm: Arc>, + buffer_output: bool, + ) -> ExitCode { + let path_separator = self.path_separator.as_deref(); + for cmd in &self.commands { + let exit = + cmd.generate_and_execute(input, path_separator, &mut out_perm, buffer_output); + if exit != ExitCode::Success { + return exit; + } + } + ExitCode::Success + } + + pub fn execute_batch(&self, paths: I, buffer_output: bool) -> ExitCode + where + I: Iterator, + { + let path_separator = self.path_separator.as_deref(); + let mut paths = paths.collect::>(); + paths.sort(); + for cmd in &self.commands { + let exit = cmd.generate_and_execute_batch(&paths, path_separator, buffer_output); + if exit != ExitCode::Success { + return exit; + } + } + ExitCode::Success + } +} + /// Represents a template that is utilized to generate command strings. /// /// The template is meant to be coupled with an input in order to generate a command. The /// `generate_and_execute()` method will be used to generate a command and execute it. #[derive(Debug, Clone, PartialEq)] -pub struct CommandTemplate { +struct CommandTemplate { args: Vec, - mode: ExecutionMode, - path_separator: Option, } impl CommandTemplate { - pub fn new(input: I, path_separator: Option) -> CommandTemplate - where - I: IntoIterator, - S: AsRef, - { - Self::build(input, ExecutionMode::OneByOne, path_separator) - } - - pub fn new_batch(input: I, path_separator: Option) -> Result - where - I: IntoIterator, - S: AsRef, - { - let cmd = Self::build(input, ExecutionMode::Batch, path_separator); - if cmd.number_of_tokens() > 1 { - return Err(anyhow!("Only one placeholder allowed for batch commands")); - } - if cmd.args[0].has_tokens() { - return Err(anyhow!( - "First argument of exec-batch is expected to be a fixed executable" - )); - } - Ok(cmd) - } - - fn build(input: I, mode: ExecutionMode, path_separator: Option) -> CommandTemplate + fn new(input: I) -> CommandTemplate where I: IntoIterator, S: AsRef, @@ -122,11 +179,7 @@ impl CommandTemplate { args.push(ArgumentTemplate::Tokens(vec![Token::Placeholder])); } - CommandTemplate { - args, - mode, - path_separator, - } + CommandTemplate { args } } fn number_of_tokens(&self) -> usize { @@ -137,44 +190,38 @@ impl CommandTemplate { /// /// Using the internal `args` field, and a supplied `input` variable, a `Command` will be /// build. Once all arguments have been processed, the command is executed. - pub fn generate_and_execute( + fn generate_and_execute( &self, input: &Path, - out_perm: Arc>, + path_separator: Option<&str>, + out_perm: &mut Arc>, buffer_output: bool, ) -> ExitCode { - let mut cmd = Command::new(self.args[0].generate(&input, self.path_separator.as_deref())); + let mut cmd = Command::new(self.args[0].generate(&input, path_separator)); for arg in &self.args[1..] { - cmd.arg(arg.generate(&input, self.path_separator.as_deref())); + cmd.arg(arg.generate(&input, path_separator)); } execute_command(cmd, &out_perm, buffer_output) } - pub fn in_batch_mode(&self) -> bool { - self.mode == ExecutionMode::Batch - } - - pub fn generate_and_execute_batch(&self, paths: I, buffer_output: bool) -> ExitCode - where - I: Iterator, - { + fn generate_and_execute_batch( + &self, + paths: &Vec, + path_separator: Option<&str>, + buffer_output: bool, + ) -> ExitCode { let mut cmd = Command::new(self.args[0].generate("", None)); cmd.stdin(Stdio::inherit()); cmd.stdout(Stdio::inherit()); cmd.stderr(Stdio::inherit()); - let mut paths: Vec<_> = paths.collect(); let mut has_path = false; for arg in &self.args[1..] { if arg.has_tokens() { - paths.sort(); - - // A single `Tokens` is expected - // So we can directly consume the iterator once and for all - for path in &mut paths { - cmd.arg(arg.generate(path, self.path_separator.as_deref())); + for path in paths { + cmd.arg(arg.generate(path, path_separator)); has_path = true; } } else { @@ -302,13 +349,15 @@ mod tests { #[test] fn tokens_with_placeholder() { assert_eq!( - CommandTemplate::new(&[&"echo", &"${SHELL}:"], None), - CommandTemplate { - args: vec![ - ArgumentTemplate::Text("echo".into()), - ArgumentTemplate::Text("${SHELL}:".into()), - ArgumentTemplate::Tokens(vec![Token::Placeholder]), - ], + CommandSet::new(vec![vec![&"echo", &"${SHELL}:"]], None), + CommandSet { + commands: vec![CommandTemplate { + args: vec![ + ArgumentTemplate::Text("echo".into()), + ArgumentTemplate::Text("${SHELL}:".into()), + ArgumentTemplate::Tokens(vec![Token::Placeholder]), + ] + }], mode: ExecutionMode::OneByOne, path_separator: None, } @@ -318,12 +367,14 @@ mod tests { #[test] fn tokens_with_no_extension() { assert_eq!( - CommandTemplate::new(&["echo", "{.}"], None), - CommandTemplate { - args: vec![ - ArgumentTemplate::Text("echo".into()), - ArgumentTemplate::Tokens(vec![Token::NoExt]), - ], + CommandSet::new(vec![vec!["echo", "{.}"]], None), + CommandSet { + commands: vec![CommandTemplate { + args: vec![ + ArgumentTemplate::Text("echo".into()), + ArgumentTemplate::Tokens(vec![Token::NoExt]), + ], + }], mode: ExecutionMode::OneByOne, path_separator: None, } @@ -333,12 +384,14 @@ mod tests { #[test] fn tokens_with_basename() { assert_eq!( - CommandTemplate::new(&["echo", "{/}"], None), - CommandTemplate { - args: vec![ - ArgumentTemplate::Text("echo".into()), - ArgumentTemplate::Tokens(vec![Token::Basename]), - ], + CommandSet::new(vec![vec!["echo", "{/}"]], None), + CommandSet { + commands: vec![CommandTemplate { + args: vec![ + ArgumentTemplate::Text("echo".into()), + ArgumentTemplate::Tokens(vec![Token::Basename]), + ], + }], mode: ExecutionMode::OneByOne, path_separator: None, } @@ -348,12 +401,14 @@ mod tests { #[test] fn tokens_with_parent() { assert_eq!( - CommandTemplate::new(&["echo", "{//}"], None), - CommandTemplate { - args: vec![ - ArgumentTemplate::Text("echo".into()), - ArgumentTemplate::Tokens(vec![Token::Parent]), - ], + CommandSet::new(vec![vec!["echo", "{//}"]], None), + CommandSet { + commands: vec![CommandTemplate { + args: vec![ + ArgumentTemplate::Text("echo".into()), + ArgumentTemplate::Tokens(vec![Token::Parent]), + ], + }], mode: ExecutionMode::OneByOne, path_separator: None, } @@ -363,12 +418,14 @@ mod tests { #[test] fn tokens_with_basename_no_extension() { assert_eq!( - CommandTemplate::new(&["echo", "{/.}"], None), - CommandTemplate { - args: vec![ - ArgumentTemplate::Text("echo".into()), - ArgumentTemplate::Tokens(vec![Token::BasenameNoExt]), - ], + CommandSet::new(vec![vec!["echo", "{/.}"]], None), + CommandSet { + commands: vec![CommandTemplate { + args: vec![ + ArgumentTemplate::Text("echo".into()), + ArgumentTemplate::Tokens(vec![Token::BasenameNoExt]), + ], + }], mode: ExecutionMode::OneByOne, path_separator: None, } @@ -378,16 +435,18 @@ mod tests { #[test] fn tokens_multiple() { assert_eq!( - CommandTemplate::new(&["cp", "{}", "{/.}.ext"], None), - CommandTemplate { - args: vec![ - ArgumentTemplate::Text("cp".into()), - ArgumentTemplate::Tokens(vec![Token::Placeholder]), - ArgumentTemplate::Tokens(vec![ - Token::BasenameNoExt, - Token::Text(".ext".into()) - ]), - ], + CommandSet::new(vec![vec!["cp", "{}", "{/.}.ext"]], None), + CommandSet { + commands: vec![CommandTemplate { + args: vec![ + ArgumentTemplate::Text("cp".into()), + ArgumentTemplate::Tokens(vec![Token::Placeholder]), + ArgumentTemplate::Tokens(vec![ + Token::BasenameNoExt, + Token::Text(".ext".into()) + ]), + ], + }], mode: ExecutionMode::OneByOne, path_separator: None, } @@ -397,12 +456,14 @@ mod tests { #[test] fn tokens_single_batch() { assert_eq!( - CommandTemplate::new_batch(&["echo", "{.}"], None).unwrap(), - CommandTemplate { + CommandSet::new_batch(vec![vec!["echo", "{.}"]], None).unwrap(), + CommandSet { + commands: vec![CommandTemplate { args: vec![ ArgumentTemplate::Text("echo".into()), ArgumentTemplate::Tokens(vec![Token::NoExt]), ], + }], mode: ExecutionMode::Batch, path_separator: None, } @@ -411,7 +472,7 @@ mod tests { #[test] fn tokens_multiple_batch() { - assert!(CommandTemplate::new_batch(&["echo", "{.}", "{}"], None).is_err()); + assert!(CommandSet::new_batch(vec![vec!["echo", "{.}", "{}"]], None).is_err()); } #[test] diff --git a/src/main.rs b/src/main.rs index 7e55da1..88e7aad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ use regex::bytes::{RegexBuilder, RegexSetBuilder}; use crate::config::Config; use crate::error::print_error; -use crate::exec::CommandTemplate; +use crate::exec::CommandSet; use crate::exit_codes::ExitCode; use crate::filetypes::FileTypes; #[cfg(unix)] @@ -390,19 +390,16 @@ fn extract_command( matches: &clap::ArgMatches, path_separator: Option<&str>, colored_output: bool, -) -> Result> { +) -> Result> { None.or_else(|| { - matches.values_of("exec").map(|args| { - Ok(CommandTemplate::new( - args, - path_separator.map(str::to_string), - )) - }) + matches + .grouped_values_of("exec") + .map(|args| Ok(CommandSet::new(args, path_separator.map(str::to_string)))) }) .or_else(|| { matches - .values_of("exec-batch") - .map(|args| CommandTemplate::new_batch(args, path_separator.map(str::to_string))) + .grouped_values_of("exec-batch") + .map(|args| CommandSet::new_batch(args, path_separator.map(str::to_string))) }) .or_else(|| { if !matches.is_present("list-details") { @@ -412,9 +409,8 @@ fn extract_command( let color = matches.value_of("color").unwrap_or("auto"); let color_arg = format!("--color={}", color); - let res = determine_ls_command(&color_arg, colored_output).map(|cmd| { - CommandTemplate::new_batch(cmd, path_separator.map(str::to_string)).unwrap() - }); + let res = determine_ls_command(&color_arg, colored_output) + .map(|cmd| CommandSet::new_batch([cmd], path_separator.map(str::to_string)).unwrap()); Some(res) }) From f27332ee8d08df574e91b8e4df75080ce0211d57 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Fri, 18 Feb 2022 01:27:40 -0700 Subject: [PATCH 40/46] Fix clippy lints --- src/exec/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/exec/mod.rs b/src/exec/mod.rs index e420c81..5cf8414 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -202,12 +202,12 @@ impl CommandTemplate { cmd.arg(arg.generate(&input, path_separator)); } - execute_command(cmd, &out_perm, buffer_output) + execute_command(cmd, out_perm, buffer_output) } fn generate_and_execute_batch( &self, - paths: &Vec, + paths: &[PathBuf], path_separator: Option<&str>, buffer_output: bool, ) -> ExitCode { @@ -459,10 +459,10 @@ mod tests { CommandSet::new_batch(vec![vec!["echo", "{.}"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { - args: vec![ - ArgumentTemplate::Text("echo".into()), - ArgumentTemplate::Tokens(vec![Token::NoExt]), - ], + args: vec![ + ArgumentTemplate::Text("echo".into()), + ArgumentTemplate::Tokens(vec![Token::NoExt]), + ], }], mode: ExecutionMode::Batch, path_separator: None, From e54e3520356bcf600ec3c2dfb738c4b98754bad9 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Sat, 26 Feb 2022 01:03:13 -0700 Subject: [PATCH 41/46] Add description of multiple --exec to man page --- doc/fd.1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/fd.1 b/doc/fd.1 index f917b12..620af8b 100644 --- a/doc/fd.1 +++ b/doc/fd.1 @@ -341,6 +341,9 @@ Note that all subsequent positional arguments are considered to be arguments to It is therefore recommended to place the \-x/\-\-exec option last. Alternatively, you can supply a ';' argument to end the argument list and continue with more fd options. Most shells require ';' to be escaped: '\\;'. +This option can be specified multiple times, in which case all commands are run for each +file found, in the order they are provided. In that case, you must supply a ';' argument for +all but the last commands. The following placeholders are substituted before the command is executed: .RS @@ -394,6 +397,9 @@ basename without file extension If no placeholder is present, an implicit "{}" at the end is assumed. +Like \-\-exec, this can be used multiple times, in which case each command will be run in +the order given. + Examples: - Find all test_*.py files and open them in your favorite editor: From 9fb0c5d372062d6193798519526cb7b14ea24fcc Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Mon, 28 Feb 2022 00:39:52 -0700 Subject: [PATCH 42/46] Group together output from multi exec commands So that if multiple `--exec` options are given, and the commands are run in parallel, the buffered output for related commands will be consecutive. --- src/exec/command.rs | 122 ++++++++++++++++++++++++++++++-------------- src/exec/job.rs | 5 +- src/exec/mod.rs | 38 ++++++-------- src/walk.rs | 8 +-- 4 files changed, 102 insertions(+), 71 deletions(-) diff --git a/src/exec/command.rs b/src/exec/command.rs index 9c2c5e2..b373ca2 100644 --- a/src/exec/command.rs +++ b/src/exec/command.rs @@ -6,47 +6,93 @@ use std::sync::Mutex; use crate::error::print_error; use crate::exit_codes::ExitCode; -/// Executes a command. -pub fn execute_command( - mut cmd: Command, - out_perm: &Mutex<()>, - enable_output_buffering: bool, -) -> ExitCode { - // Spawn the supplied command. - let output = if enable_output_buffering { - cmd.output() - } else { - // If running on only one thread, don't buffer output - // Allows for viewing and interacting with intermediate command output - cmd.spawn().and_then(|c| c.wait_with_output()) - }; +struct Outputs { + stdout: Vec, + stderr: Vec, +} +struct OutputBuf<'a> { + out_perm: &'a Mutex<()>, + outputs: Vec, +} - // Then wait for the command to exit, if it was spawned. - match output { - Ok(output) => { - // While this lock is active, this thread will be the only thread allowed - // to write its outputs. - let _lock = out_perm.lock().unwrap(); - - let stdout = io::stdout(); - let stderr = io::stderr(); - - let _ = stdout.lock().write_all(&output.stdout); - let _ = stderr.lock().write_all(&output.stderr); - - if output.status.code() == Some(0) { - ExitCode::Success - } else { - ExitCode::GeneralError - } +impl<'a> OutputBuf<'a> { + fn new(out_perm: &'a Mutex<()>) -> Self { + Self { + out_perm, + outputs: Vec::new(), } - Err(ref why) if why.kind() == io::ErrorKind::NotFound => { - print_error(format!("Command not found: {:?}", cmd)); - ExitCode::GeneralError + } + + fn push(&mut self, stdout: Vec, stderr: Vec) { + self.outputs.push(Outputs { stdout, stderr }); + } + + fn write(self) { + // avoid taking the lock if there is nothing to do + if self.outputs.is_empty() { + return; } - Err(why) => { - print_error(format!("Problem while executing command: {}", why)); - ExitCode::GeneralError + // While this lock is active, this thread will be the only thread allowed + // to write its outputs. + let _lock = self.out_perm.lock().unwrap(); + + let stdout = io::stdout(); + let stderr = io::stderr(); + + let mut stdout = stdout.lock(); + let mut stderr = stderr.lock(); + + for output in self.outputs.iter() { + let _ = stdout.write_all(&output.stdout); + let _ = stderr.write_all(&output.stderr); } } } + +/// Executes a command. +pub fn execute_commands>( + cmds: I, + out_perm: &Mutex<()>, + enable_output_buffering: bool, +) -> ExitCode { + let mut out_buf = OutputBuf::new(out_perm); + for mut cmd in cmds { + // Spawn the supplied command. + let output = if enable_output_buffering { + cmd.output() + } else { + // If running on only one thread, don't buffer output + // Allows for viewing and interacting with intermediate command output + cmd.spawn().and_then(|c| c.wait_with_output()) + }; + + // Then wait for the command to exit, if it was spawned. + match output { + Ok(output) => { + if enable_output_buffering { + out_buf.push(output.stdout, output.stderr); + } + if output.status.code() != Some(0) { + out_buf.write(); + return ExitCode::GeneralError; + } + } + Err(why) => { + out_buf.write(); + return handle_cmd_error(&cmd, why); + } + } + } + out_buf.write(); + ExitCode::Success +} + +pub fn handle_cmd_error(cmd: &Command, err: io::Error) -> ExitCode { + if err.kind() == io::ErrorKind::NotFound { + print_error(format!("Command not found: {:?}", cmd)); + ExitCode::GeneralError + } else { + print_error(format!("Problem while executing command: {}", err)); + ExitCode::GeneralError + } +} diff --git a/src/exec/job.rs b/src/exec/job.rs index feda262..f192543 100644 --- a/src/exec/job.rs +++ b/src/exec/job.rs @@ -49,7 +49,6 @@ pub fn batch( rx: Receiver, cmd: &CommandSet, show_filesystem_errors: bool, - buffer_output: bool, limit: usize, ) -> ExitCode { let paths = rx.iter().filter_map(|value| match value { @@ -63,14 +62,14 @@ pub fn batch( }); if limit == 0 { // no limit - return cmd.execute_batch(paths, buffer_output); + return cmd.execute_batch(paths); } let mut exit_codes = Vec::new(); let mut peekable = paths.peekable(); while peekable.peek().is_some() { let limited = peekable.by_ref().take(limit); - let exit_code = cmd.execute_batch(limited, buffer_output); + let exit_code = cmd.execute_batch(limited); exit_codes.push(exit_code); } merge_exitcodes(exit_codes) diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 5cf8414..633b44a 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -15,7 +15,7 @@ use regex::Regex; use crate::exit_codes::ExitCode; -use self::command::execute_command; +use self::command::{execute_commands, handle_cmd_error}; use self::input::{basename, dirname, remove_extension}; pub use self::job::{batch, job}; use self::token::Token; @@ -86,17 +86,14 @@ impl CommandSet { buffer_output: bool, ) -> ExitCode { let path_separator = self.path_separator.as_deref(); - for cmd in &self.commands { - let exit = - cmd.generate_and_execute(input, path_separator, &mut out_perm, buffer_output); - if exit != ExitCode::Success { - return exit; - } - } - ExitCode::Success + let commands = self + .commands + .iter() + .map(|c| c.generate(input, path_separator)); + execute_commands(commands, &mut out_perm, buffer_output) } - pub fn execute_batch(&self, paths: I, buffer_output: bool) -> ExitCode + pub fn execute_batch(&self, paths: I) -> ExitCode where I: Iterator, { @@ -104,7 +101,7 @@ impl CommandSet { let mut paths = paths.collect::>(); paths.sort(); for cmd in &self.commands { - let exit = cmd.generate_and_execute_batch(&paths, path_separator, buffer_output); + let exit = cmd.generate_and_execute_batch(&paths, path_separator); if exit != ExitCode::Success { return exit; } @@ -189,27 +186,19 @@ impl CommandTemplate { /// Generates and executes a command. /// /// Using the internal `args` field, and a supplied `input` variable, a `Command` will be - /// build. Once all arguments have been processed, the command is executed. - fn generate_and_execute( - &self, - input: &Path, - path_separator: Option<&str>, - out_perm: &mut Arc>, - buffer_output: bool, - ) -> ExitCode { + /// build. + fn generate(&self, input: &Path, path_separator: Option<&str>) -> Command { let mut cmd = Command::new(self.args[0].generate(&input, path_separator)); for arg in &self.args[1..] { cmd.arg(arg.generate(&input, path_separator)); } - - execute_command(cmd, out_perm, buffer_output) + cmd } fn generate_and_execute_batch( &self, paths: &[PathBuf], path_separator: Option<&str>, - buffer_output: bool, ) -> ExitCode { let mut cmd = Command::new(self.args[0].generate("", None)); cmd.stdin(Stdio::inherit()); @@ -230,7 +219,10 @@ impl CommandTemplate { } if has_path { - execute_command(cmd, &Mutex::new(()), buffer_output) + match cmd.spawn().and_then(|mut c| c.wait()) { + Ok(_) => ExitCode::Success, + Err(e) => handle_cmd_error(&cmd, e), + } } else { ExitCode::Success } diff --git a/src/walk.rs b/src/walk.rs index 4343bc3..d947ade 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -350,13 +350,7 @@ fn spawn_receiver( // This will be set to `Some` if the `--exec` argument was supplied. if let Some(ref cmd) = config.command { if cmd.in_batch_mode() { - exec::batch( - rx, - cmd, - show_filesystem_errors, - enable_output_buffering, - config.batch_size, - ) + exec::batch(rx, cmd, show_filesystem_errors, config.batch_size) } else { let shared_rx = Arc::new(Mutex::new(rx)); From 9f39f1d75b05da4fb85fbfa9fee84428bbc7d466 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Tue, 1 Mar 2022 00:46:23 -0700 Subject: [PATCH 43/46] Add tests for multiple execs --- tests/tests.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/tests/tests.rs b/tests/tests.rs index ec95a9c..3436437 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1383,6 +1383,67 @@ fn test_exec() { } } +#[test] +fn test_exec_multi() { + // TODO test for windows + if cfg!(windows) { + return; + } + let (te, abs_path) = get_test_env_with_abs_path(DEFAULT_DIRS, DEFAULT_FILES); + + te.assert_output( + &[ + "--absolute-path", + "foo", + "--exec", + "echo", + ";", + "--exec", + "echo", + "test", + "{/}", + ], + &format!( + "{abs_path}/a.foo + {abs_path}/one/b.foo + {abs_path}/one/two/C.Foo2 + {abs_path}/one/two/c.foo + {abs_path}/one/two/three/d.foo + {abs_path}/one/two/three/directory_foo + test a.foo + test b.foo + test C.Foo2 + test c.foo + test d.foo + test directory_foo", + abs_path = &abs_path + ), + ); + + te.assert_output( + &[ + "e1", "--exec", "echo", "{.}", ";", "--exec", "echo", "{/}", ";", "--exec", "echo", + "{//}", ";", "--exec", "echo", "{/.}", + ], + "e1 e2 + e1 e2 + . + e1 e2", + ); + + te.assert_output( + &[ + "foo", "--exec", "echo", "-n", "{/}: ", ";", "--exec", "echo", "{//}", + ], + "a.foo: . + b.foo: ./one + C.Foo2: ./one/two + c.foo: ./one/two + d.foo: ./one/two/three + directory_foo: ./one/two/three", + ); +} + #[test] fn test_exec_batch() { let (te, abs_path) = get_test_env_with_abs_path(DEFAULT_DIRS, DEFAULT_FILES); @@ -1435,6 +1496,21 @@ fn test_exec_batch() { } } +#[test] +fn test_exec_batch_multi() { + // TODO test for windows + if cfg!(windows) { + return; + } + let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); + + te.assert_output( + &["foo", "--exec-batch", "echo", "{}", ";", "--exec-batch", "echo", "{/}"], + "./a.foo ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo + a.foo b.foo C.Foo2 c.foo d.foo directory_foo", + ); +} + #[test] fn test_exec_batch_with_limit() { // TODO Test for windows From 5a12a5e421d5ffcec145fb2a7b0fbfa7250c129f Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Sun, 6 Mar 2022 23:41:03 -0700 Subject: [PATCH 44/46] Use full names in command.rs --- src/exec/command.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/exec/command.rs b/src/exec/command.rs index b373ca2..935b6f4 100644 --- a/src/exec/command.rs +++ b/src/exec/command.rs @@ -10,15 +10,15 @@ struct Outputs { stdout: Vec, stderr: Vec, } -struct OutputBuf<'a> { - out_perm: &'a Mutex<()>, +struct OutputBuffer<'a> { + output_permission: &'a Mutex<()>, outputs: Vec, } -impl<'a> OutputBuf<'a> { - fn new(out_perm: &'a Mutex<()>) -> Self { +impl<'a> OutputBuffer<'a> { + fn new(output_permission: &'a Mutex<()>) -> Self { Self { - out_perm, + output_permission, outputs: Vec::new(), } } @@ -34,7 +34,7 @@ impl<'a> OutputBuf<'a> { } // While this lock is active, this thread will be the only thread allowed // to write its outputs. - let _lock = self.out_perm.lock().unwrap(); + let _lock = self.output_permission.lock().unwrap(); let stdout = io::stdout(); let stderr = io::stderr(); @@ -55,7 +55,7 @@ pub fn execute_commands>( out_perm: &Mutex<()>, enable_output_buffering: bool, ) -> ExitCode { - let mut out_buf = OutputBuf::new(out_perm); + let mut output_buffer = OutputBuffer::new(out_perm); for mut cmd in cmds { // Spawn the supplied command. let output = if enable_output_buffering { @@ -70,20 +70,20 @@ pub fn execute_commands>( match output { Ok(output) => { if enable_output_buffering { - out_buf.push(output.stdout, output.stderr); + output_buffer.push(output.stdout, output.stderr); } if output.status.code() != Some(0) { - out_buf.write(); + output_buffer.write(); return ExitCode::GeneralError; } } Err(why) => { - out_buf.write(); + output_buffer.write(); return handle_cmd_error(&cmd, why); } } } - out_buf.write(); + output_buffer.write(); ExitCode::Success } From c577b0838b2e8da07c266f19ffb52dfee7a53f1a Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Mon, 7 Mar 2022 00:58:19 -0700 Subject: [PATCH 45/46] Error out if no args provided to --exec or --exec-batch Accepting multiple occurances means we need to check this ourselves. See https://github.com/clap-rs/clap/issues/3542. --- src/exec/mod.rs | 65 ++++++++++++++++++++++++++++++------------------- src/main.rs | 2 +- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 633b44a..d140528 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -9,7 +9,7 @@ use std::path::{Component, Path, PathBuf, Prefix}; use std::process::{Command, Stdio}; use std::sync::{Arc, Mutex}; -use anyhow::{anyhow, Result}; +use anyhow::{bail, Result}; use once_cell::sync::Lazy; use regex::Regex; @@ -37,16 +37,19 @@ pub struct CommandSet { } impl CommandSet { - pub fn new(input: I, path_separator: Option) -> CommandSet + pub fn new(input: I, path_separator: Option) -> Result where I: IntoIterator>, S: AsRef, { - CommandSet { + Ok(CommandSet { mode: ExecutionMode::OneByOne, path_separator, - commands: input.into_iter().map(CommandTemplate::new).collect(), - } + commands: input + .into_iter() + .map(CommandTemplate::new) + .collect::>()?, + }) } pub fn new_batch(input: I, path_separator: Option) -> Result @@ -60,14 +63,12 @@ impl CommandSet { commands: input .into_iter() .map(|args| { - let cmd = CommandTemplate::new(args); + let cmd = CommandTemplate::new(args)?; if cmd.number_of_tokens() > 1 { - return Err(anyhow!("Only one placeholder allowed for batch commands")); + bail!("Only one placeholder allowed for batch commands"); } if cmd.args[0].has_tokens() { - return Err(anyhow!( - "First argument of exec-batch is expected to be a fixed executable" - )); + bail!("First argument of exec-batch is expected to be a fixed executable"); } Ok(cmd) }) @@ -79,18 +80,13 @@ impl CommandSet { self.mode == ExecutionMode::Batch } - pub fn execute( - &self, - input: &Path, - mut out_perm: Arc>, - buffer_output: bool, - ) -> ExitCode { + pub fn execute(&self, input: &Path, out_perm: Arc>, buffer_output: bool) -> ExitCode { let path_separator = self.path_separator.as_deref(); let commands = self .commands .iter() .map(|c| c.generate(input, path_separator)); - execute_commands(commands, &mut out_perm, buffer_output) + execute_commands(commands, &out_perm, buffer_output) } pub fn execute_batch(&self, paths: I) -> ExitCode @@ -120,7 +116,7 @@ struct CommandTemplate { } impl CommandTemplate { - fn new(input: I) -> CommandTemplate + fn new(input: I) -> Result where I: IntoIterator, S: AsRef, @@ -171,12 +167,21 @@ impl CommandTemplate { args.push(ArgumentTemplate::Tokens(tokens)); } + // We need to check that we have at least one argument, because if not + // it will try to execute each file and directory it finds. + // + // Sadly, clap can't currently handle this for us, see + // https://github.com/clap-rs/clap/issues/3542 + if args.is_empty() { + bail!("No executable provided for --exec or --exec-batch"); + } + // If a placeholder token was not supplied, append one at the end of the command. if !has_placeholder { args.push(ArgumentTemplate::Tokens(vec![Token::Placeholder])); } - CommandTemplate { args } + Ok(CommandTemplate { args }) } fn number_of_tokens(&self) -> usize { @@ -341,7 +346,7 @@ mod tests { #[test] fn tokens_with_placeholder() { assert_eq!( - CommandSet::new(vec![vec![&"echo", &"${SHELL}:"]], None), + CommandSet::new(vec![vec![&"echo", &"${SHELL}:"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { args: vec![ @@ -359,7 +364,7 @@ mod tests { #[test] fn tokens_with_no_extension() { assert_eq!( - CommandSet::new(vec![vec!["echo", "{.}"]], None), + CommandSet::new(vec![vec!["echo", "{.}"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { args: vec![ @@ -376,7 +381,7 @@ mod tests { #[test] fn tokens_with_basename() { assert_eq!( - CommandSet::new(vec![vec!["echo", "{/}"]], None), + CommandSet::new(vec![vec!["echo", "{/}"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { args: vec![ @@ -393,7 +398,7 @@ mod tests { #[test] fn tokens_with_parent() { assert_eq!( - CommandSet::new(vec![vec!["echo", "{//}"]], None), + CommandSet::new(vec![vec!["echo", "{//}"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { args: vec![ @@ -410,7 +415,7 @@ mod tests { #[test] fn tokens_with_basename_no_extension() { assert_eq!( - CommandSet::new(vec![vec!["echo", "{/.}"]], None), + CommandSet::new(vec![vec!["echo", "{/.}"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { args: vec![ @@ -427,7 +432,7 @@ mod tests { #[test] fn tokens_multiple() { assert_eq!( - CommandSet::new(vec![vec!["cp", "{}", "{/.}.ext"]], None), + CommandSet::new(vec![vec!["cp", "{}", "{/.}.ext"]], None).unwrap(), CommandSet { commands: vec![CommandTemplate { args: vec![ @@ -467,6 +472,16 @@ mod tests { assert!(CommandSet::new_batch(vec![vec!["echo", "{.}", "{}"]], None).is_err()); } + #[test] + fn template_no_args() { + assert!(CommandTemplate::new::, &'static str>(vec![]).is_err()); + } + + #[test] + fn command_set_no_args() { + assert!(CommandSet::new(vec![vec!["echo"], vec![]], None).is_err()); + } + #[test] fn generate_custom_path_separator() { let arg = ArgumentTemplate::Tokens(vec![Token::Placeholder]); diff --git a/src/main.rs b/src/main.rs index 88e7aad..8bcd05e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -394,7 +394,7 @@ fn extract_command( None.or_else(|| { matches .grouped_values_of("exec") - .map(|args| Ok(CommandSet::new(args, path_separator.map(str::to_string)))) + .map(|args| CommandSet::new(args, path_separator.map(str::to_string))) }) .or_else(|| { matches From db2fd00c4acf9e6d1322def46cadc56f26583e21 Mon Sep 17 00:00:00 2001 From: Max Coplan Date: Mon, 14 Mar 2022 10:44:36 -0700 Subject: [PATCH 46/46] =?UTF-8?q?=F0=9F=93=9D=20Update=20README=20formatti?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Probably meant to use `code styling` instead of *italicizing* --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff114d1..8d28ce7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Quick links: * Intuitive syntax: `fd PATTERN` instead of `find -iname '*PATTERN*'`. * Regular expression (default) and glob-based patterns. * [Very fast](#benchmark) due to parallelized directory traversal. -* Uses colors to highlight different file types (same as *ls*). +* Uses colors to highlight different file types (same as `ls`). * Supports [parallel command execution](#command-execution) * Smart case: the search is case-insensitive by default. It switches to case-sensitive if the pattern contains an uppercase