diff --git a/CHANGELOG.md b/CHANGELOG.md index f3b4e3c..529cd52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ ## Bugfixes +- Always show the `./` prefix for search results unless the output is a TTY or `--strip-cwd-prefix` is set, see #760 and #861 (@jcaplan) - Set default path separator to `/` in MSYS, see #537 and #730 (@aswild) - fd cannot search files under a RAM disk, see #752 - fd doesn't show substituted drive on Windows, see #365 diff --git a/src/app.rs b/src/app.rs index ee514b4..dd4282b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -704,6 +704,17 @@ pub fn build_app() -> App<'static, 'static> { argument. Changes the usage to `fd [FLAGS/OPTIONS] --search-path \ --search-path []`", ), + ) + .arg( + Arg::with_name("strip-cwd-prefix") + .long("strip-cwd-prefix") + .conflicts_with_all(&["path", "search-path"]) + .hidden_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 \ + interactive terminal (TTY). Use this flag to disable this behaviour." + ) ); if cfg!(unix) { diff --git a/src/config.rs b/src/config.rs index c11f88b..5a71714 100644 --- a/src/config.rs +++ b/src/config.rs @@ -113,4 +113,7 @@ pub struct Config { /// The maximum number of search results pub max_results: Option, + + /// Whether or not to strip the './' prefix for search results + pub strip_cwd_prefix: bool, } diff --git a/src/exec/mod.rs b/src/exec/mod.rs index fc22e6f..3f93acd 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -14,7 +14,6 @@ use once_cell::sync::Lazy; use regex::Regex; use crate::exit_codes::ExitCode; -use crate::filesystem::strip_current_dir; use self::command::execute_command; use self::input::{basename, dirname, remove_extension}; @@ -144,8 +143,6 @@ impl CommandTemplate { out_perm: Arc>, buffer_output: bool, ) -> ExitCode { - let input = strip_current_dir(input); - let mut cmd = Command::new(self.args[0].generate(&input, self.path_separator.as_deref())); for arg in &self.args[1..] { cmd.arg(arg.generate(&input, self.path_separator.as_deref())); @@ -177,7 +174,7 @@ impl CommandTemplate { // 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(strip_current_dir(path), self.path_separator.as_deref())); + cmd.arg(arg.generate(path, self.path_separator.as_deref())); has_path = true; } } else { diff --git a/src/main.rs b/src/main.rs index 172d570..cb6dfa8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -380,6 +380,9 @@ fn construct_config(matches: clap::ArgMatches, pattern_regex: &str) -> Result, ) { - let path = if entry.is_absolute() { - entry - } else { + let path = if config.strip_cwd_prefix { strip_current_dir(entry) + } else { + entry }; let r = if let Some(ref ls_colors) = config.ls_colors { diff --git a/tests/tests.rs b/tests/tests.rs index 54b4ecc..807b91b 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -61,18 +61,18 @@ fn create_file_with_size>(path: P, size_in_bytes: usize) { fn test_simple() { let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); - te.assert_output(&["a.foo"], "a.foo"); - te.assert_output(&["b.foo"], "one/b.foo"); - te.assert_output(&["d.foo"], "one/two/three/d.foo"); + te.assert_output(&["a.foo"], "./a.foo"); + te.assert_output(&["b.foo"], "./one/b.foo"); + te.assert_output(&["d.foo"], "./one/two/three/d.foo"); te.assert_output( &["foo"], - "a.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -80,17 +80,17 @@ fn test_simple() { #[test] fn test_empty_pattern() { let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); - let expected = "a.foo - e1 e2 - one - one/b.foo - one/two - one/two/c.foo - one/two/C.Foo2 - one/two/three - one/two/three/d.foo - one/two/three/directory_foo - symlink"; + let expected = "./a.foo + ./e1 e2 + ./one + ./one/b.foo + ./one/two + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three + ./one/two/three/d.foo + ./one/two/three/directory_foo + ./symlink"; te.assert_output(&["--regex"], expected); te.assert_output(&["--fixed-strings"], expected); @@ -209,17 +209,17 @@ fn test_regex_searches() { te.assert_output( &["[a-c].foo"], - "a.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2", + "./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2", ); te.assert_output( &["--case-sensitive", "[a-c].foo"], - "a.foo - one/b.foo - one/two/c.foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo", ); } @@ -230,21 +230,21 @@ fn test_smart_case() { te.assert_output( &["c.foo"], - "one/two/c.foo - one/two/C.Foo2", + "./one/two/c.foo + ./one/two/C.Foo2", ); - te.assert_output(&["C.Foo"], "one/two/C.Foo2"); + te.assert_output(&["C.Foo"], "./one/two/C.Foo2"); - te.assert_output(&["Foo"], "one/two/C.Foo2"); + te.assert_output(&["Foo"], "./one/two/C.Foo2"); // Only literal uppercase chars should trigger case sensitivity. te.assert_output( &["\\Ac"], - "one/two/c.foo - one/two/C.Foo2", + "./one/two/c.foo + ./one/two/C.Foo2", ); - te.assert_output(&["\\AC"], "one/two/C.Foo2"); + te.assert_output(&["\\AC"], "./one/two/C.Foo2"); } /// Case sensitivity (--case-sensitive) @@ -252,13 +252,13 @@ fn test_smart_case() { fn test_case_sensitive() { let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); - te.assert_output(&["--case-sensitive", "c.foo"], "one/two/c.foo"); + te.assert_output(&["--case-sensitive", "c.foo"], "./one/two/c.foo"); - te.assert_output(&["--case-sensitive", "C.Foo"], "one/two/C.Foo2"); + te.assert_output(&["--case-sensitive", "C.Foo"], "./one/two/C.Foo2"); te.assert_output( &["--ignore-case", "--case-sensitive", "C.Foo"], - "one/two/C.Foo2", + "./one/two/C.Foo2", ); } @@ -269,14 +269,14 @@ fn test_case_insensitive() { te.assert_output( &["--ignore-case", "C.Foo"], - "one/two/c.foo - one/two/C.Foo2", + "./one/two/c.foo + ./one/two/C.Foo2", ); te.assert_output( &["--case-sensitive", "--ignore-case", "C.Foo"], - "one/two/c.foo - one/two/C.Foo2", + "./one/two/c.foo + ./one/two/C.Foo2", ); } @@ -287,25 +287,25 @@ fn test_glob_searches() { te.assert_output( &["--glob", "*.foo"], - "a.foo - one/b.foo - one/two/c.foo - one/two/three/d.foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/three/d.foo", ); te.assert_output( &["--glob", "[a-c].foo"], - "a.foo - one/b.foo - one/two/c.foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo", ); te.assert_output( &["--glob", "[a-c].foo*"], - "a.foo - one/b.foo - one/two/C.Foo2 - one/two/c.foo", + "./a.foo + ./one/b.foo + ./one/two/C.Foo2 + ./one/two/c.foo", ); } @@ -317,19 +317,19 @@ fn test_full_path_glob_searches() { te.assert_output( &["--glob", "--full-path", "**/one/**/*.foo"], - "one/b.foo - one/two/c.foo - one/two/three/d.foo", + "./one/b.foo + ./one/two/c.foo + ./one/two/three/d.foo", ); te.assert_output( &["--glob", "--full-path", "**/one/*/*.foo"], - " one/two/c.foo", + " ./one/two/c.foo", ); te.assert_output( &["--glob", "--full-path", "**/one/*/*/*.foo"], - " one/two/three/d.foo", + " ./one/two/three/d.foo", ); } @@ -339,11 +339,11 @@ fn test_smart_case_glob_searches() { te.assert_output( &["--glob", "c.foo*"], - "one/two/C.Foo2 - one/two/c.foo", + "./one/two/C.Foo2 + ./one/two/c.foo", ); - te.assert_output(&["--glob", "C.Foo*"], "one/two/C.Foo2"); + te.assert_output(&["--glob", "C.Foo*"], "./one/two/C.Foo2"); } /// Glob-based searches (--glob) in combination with --case-sensitive @@ -351,7 +351,7 @@ fn test_smart_case_glob_searches() { fn test_case_sensitive_glob_searches() { let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); - te.assert_output(&["--glob", "--case-sensitive", "c.foo*"], "one/two/c.foo"); + te.assert_output(&["--glob", "--case-sensitive", "c.foo*"], "./one/two/c.foo"); } /// Glob-based searches (--glob) in combination with --extension @@ -361,7 +361,7 @@ fn test_glob_searches_with_extension() { te.assert_output( &["--glob", "--extension", "foo2", "[a-z].*"], - "one/two/C.Foo2", + "./one/two/C.Foo2", ); } @@ -370,7 +370,7 @@ fn test_glob_searches_with_extension() { fn test_regex_overrides_glob() { let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); - te.assert_output(&["--glob", "--regex", "Foo2$"], "one/two/C.Foo2"); + te.assert_output(&["--glob", "--regex", "Foo2$"], "./one/two/C.Foo2"); } /// Full path search (--full-path) @@ -386,8 +386,8 @@ fn test_full_path() { "--full-path", &format!("^{prefix}.*three.*foo$", prefix = prefix), ], - "one/two/three/d.foo - one/two/three/directory_foo", + "./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -398,13 +398,13 @@ fn test_hidden() { te.assert_output( &["--hidden", "foo"], - ".hidden.foo - a.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./.hidden.foo + ./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -426,7 +426,7 @@ fn test_hidden_file_attribute() { .open(te.test_root().join("hidden-file.txt")) .unwrap(); - te.assert_output(&["--hidden", "hidden-file.txt"], "hidden-file.txt"); + te.assert_output(&["--hidden", "hidden-file.txt"], "./hidden-file.txt"); te.assert_output(&["hidden-file.txt"], ""); } @@ -437,27 +437,27 @@ fn test_no_ignore() { te.assert_output( &["--no-ignore", "foo"], - "a.foo - fdignored.foo - gitignored.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./a.foo + ./fdignored.foo + ./gitignored.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); te.assert_output( &["--hidden", "--no-ignore", "foo"], - ".hidden.foo - a.foo - fdignored.foo - gitignored.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./.hidden.foo + ./a.foo + ./fdignored.foo + ./gitignored.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -482,20 +482,20 @@ fn test_gitignore_and_fdignore() { .write_all(b"ignored-by-gitignore\nignored-by-both") .unwrap(); - te.assert_output(&["ignored"], "ignored-by-nothing"); + te.assert_output(&["ignored"], "./ignored-by-nothing"); te.assert_output( &["--no-ignore-vcs", "ignored"], - "ignored-by-nothing - ignored-by-gitignore", + "./ignored-by-nothing + ./ignored-by-gitignore", ); te.assert_output( &["--no-ignore", "ignored"], - "ignored-by-nothing - ignored-by-fdignore - ignored-by-gitignore - ignored-by-both", + "./ignored-by-nothing + ./ignored-by-fdignore + ./ignored-by-gitignore + ./ignored-by-both", ); } @@ -521,13 +521,13 @@ fn test_no_ignore_parent() { .write_all(b"child-ignored") .unwrap(); - te.assert_output_subdirectory("inner", &[], "not-ignored"); + te.assert_output_subdirectory("inner", &[], "./not-ignored"); te.assert_output_subdirectory( "inner", &["--no-ignore-parent"], - "parent-ignored - not-ignored", + "./parent-ignored + ./not-ignored", ); } @@ -559,15 +559,15 @@ fn test_no_ignore_parent_inner_git() { te.assert_output_subdirectory( "inner", &[], - "not-ignored - parent-ignored", + "./not-ignored + ./parent-ignored", ); te.assert_output_subdirectory( "inner", &["--no-ignore-parent"], - "not-ignored - parent-ignored", + "./not-ignored + ./parent-ignored", ); } @@ -590,11 +590,11 @@ fn test_custom_ignore_precedence() { .write_all(b"!foo") .unwrap(); - te.assert_output(&["foo"], "inner/foo"); + te.assert_output(&["foo"], "./inner/foo"); - te.assert_output(&["--no-ignore-vcs", "foo"], "inner/foo"); + te.assert_output(&["--no-ignore-vcs", "foo"], "./inner/foo"); - te.assert_output(&["--no-ignore", "foo"], "inner/foo"); + te.assert_output(&["--no-ignore", "foo"], "./inner/foo"); } /// VCS ignored files (--no-ignore-vcs) @@ -604,13 +604,13 @@ fn test_no_ignore_vcs() { te.assert_output( &["--no-ignore-vcs", "foo"], - "a.foo - gitignored.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./a.foo + ./gitignored.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -627,9 +627,9 @@ fn test_custom_ignore_files() { te.assert_output( &["--ignore-file", "custom.ignore", "foo"], - "a.foo - one/b.foo - one/two/c.foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo", ); } @@ -640,27 +640,27 @@ fn test_no_ignore_aliases() { te.assert_output( &["-u", "foo"], - "a.foo - fdignored.foo - gitignored.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./a.foo + ./fdignored.foo + ./gitignored.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); te.assert_output( &["-uu", "foo"], - ".hidden.foo - a.foo - fdignored.foo - gitignored.foo - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo - one/two/three/directory_foo", + "./.hidden.foo + ./a.foo + ./fdignored.foo + ./gitignored.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -671,10 +671,10 @@ fn test_follow() { te.assert_output( &["--follow", "c.foo"], - "one/two/c.foo - one/two/C.Foo2 - symlink/c.foo - symlink/C.Foo2", + "./one/two/c.foo + ./one/two/C.Foo2 + ./symlink/c.foo + ./symlink/C.Foo2", ); } @@ -729,20 +729,20 @@ fn test_follow_broken_symlink() { te.assert_output( &["symlink"], - "broken_symlink - symlink", + "./broken_symlink + ./symlink", ); te.assert_output( &["--type", "symlink", "symlink"], - "broken_symlink - symlink", + "./broken_symlink + ./symlink", ); te.assert_output(&["--type", "file", "symlink"], ""); te.assert_output( &["--follow", "--type", "symlink", "symlink"], - "broken_symlink", + "./broken_symlink", ); te.assert_output(&["--follow", "--type", "file", "symlink"], ""); } @@ -754,12 +754,12 @@ fn test_print0() { te.assert_output( &["--print0", "foo"], - "a.fooNULL - one/b.fooNULL - one/two/C.Foo2NULL - one/two/c.fooNULL - one/two/three/d.fooNULL - one/two/three/directory_fooNULL", + "./a.fooNULL + ./one/b.fooNULL + ./one/two/C.Foo2NULL + ./one/two/c.fooNULL + ./one/two/three/d.fooNULL + ./one/two/three/directory_fooNULL", ); } @@ -770,33 +770,33 @@ fn test_max_depth() { te.assert_output( &["--max-depth", "3"], - "a.foo - e1 e2 - one - one/b.foo - one/two - one/two/c.foo - one/two/C.Foo2 - one/two/three - symlink", + "./a.foo + ./e1 e2 + ./one + ./one/b.foo + ./one/two + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three + ./symlink", ); te.assert_output( &["--max-depth", "2"], - "a.foo - e1 e2 - one - one/b.foo - one/two - symlink", + "./a.foo + ./e1 e2 + ./one + ./one/b.foo + ./one/two + ./symlink", ); te.assert_output( &["--max-depth", "1"], - "a.foo - e1 e2 - one - symlink", + "./a.foo + ./e1 e2 + ./one + ./symlink", ); } @@ -807,17 +807,17 @@ fn test_min_depth() { te.assert_output( &["--min-depth", "3"], - "one/two/c.foo - one/two/C.Foo2 - one/two/three - one/two/three/d.foo - one/two/three/directory_foo", + "./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); te.assert_output( &["--min-depth", "4"], - "one/two/three/d.foo - one/two/three/directory_foo", + "./one/two/three/d.foo + ./one/two/three/directory_foo", ); } @@ -828,9 +828,9 @@ fn test_exact_depth() { te.assert_output( &["--exact-depth", "3"], - "one/two/c.foo - one/two/C.Foo2 - one/two/three", + "./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three", ); } @@ -839,32 +839,32 @@ fn test_exact_depth() { fn test_prune() { let dirs = &["foo/bar", "bar/foo", "baz"]; let files = &[ - "foo/foo.file", - "foo/bar/foo.file", - "bar/foo.file", - "bar/foo/foo.file", - "baz/foo.file", + "./foo/foo.file", + "./foo/bar/foo.file", + "./bar/foo.file", + "./bar/foo/foo.file", + "./baz/foo.file", ]; let te = TestEnv::new(dirs, files); te.assert_output( &["foo"], - "foo - foo/foo.file - foo/bar/foo.file - bar/foo.file - bar/foo - bar/foo/foo.file - baz/foo.file", + "./foo + ./foo/foo.file + ./foo/bar/foo.file + ./bar/foo.file + ./bar/foo + ./bar/foo/foo.file + ./baz/foo.file", ); te.assert_output( &["--prune", "foo"], - "foo - bar/foo - bar/foo.file - baz/foo.file", + "./foo + ./bar/foo + ./bar/foo.file + ./baz/foo.file", ); } @@ -951,34 +951,34 @@ fn test_type() { te.assert_output( &["--type", "f"], - "a.foo - e1 e2 - one/b.foo - one/two/c.foo - one/two/C.Foo2 - one/two/three/d.foo", + "./a.foo + ./e1 e2 + ./one/b.foo + ./one/two/c.foo + ./one/two/C.Foo2 + ./one/two/three/d.foo", ); - te.assert_output(&["--type", "f", "e1"], "e1 e2"); + te.assert_output(&["--type", "f", "e1"], "./e1 e2"); te.assert_output( &["--type", "d"], - "one - one/two - one/two/three - one/two/three/directory_foo", + "./one + ./one/two + ./one/two/three + ./one/two/three/directory_foo", ); te.assert_output( &["--type", "d", "--type", "l"], - "one - one/two - one/two/three - one/two/three/directory_foo - symlink", + "./one + ./one/two + ./one/two/three + ./one/two/three/directory_foo + ./symlink", ); - te.assert_output(&["--type", "l"], "symlink"); + te.assert_output(&["--type", "l"], "./symlink"); } /// Test `--type executable` @@ -996,15 +996,15 @@ fn test_type_executable() { .open(te.test_root().join("executable-file.sh")) .unwrap(); - te.assert_output(&["--type", "executable"], "executable-file.sh"); + te.assert_output(&["--type", "executable"], "./executable-file.sh"); te.assert_output( &["--type", "executable", "--type", "directory"], - "executable-file.sh - one - one/two - one/two/three - one/two/three/directory_foo", + "./executable-file.sh + ./one + ./one/two + ./one/two/three + ./one/two/three/directory_foo", ); } @@ -1020,19 +1020,19 @@ fn test_type_empty() { te.assert_output( &["--type", "empty"], - "0_bytes.foo - dir_empty", + "./0_bytes.foo + ./dir_empty", ); te.assert_output( &["--type", "empty", "--type", "file", "--type", "directory"], - "0_bytes.foo - dir_empty", + "./0_bytes.foo + ./dir_empty", ); - te.assert_output(&["--type", "empty", "--type", "file"], "0_bytes.foo"); + te.assert_output(&["--type", "empty", "--type", "file"], "./0_bytes.foo"); - te.assert_output(&["--type", "empty", "--type", "directory"], "dir_empty"); + te.assert_output(&["--type", "empty", "--type", "directory"], "./dir_empty"); } /// File extension (--extension) @@ -1042,54 +1042,54 @@ fn test_extension() { te.assert_output( &["--extension", "foo"], - "a.foo - one/b.foo - one/two/c.foo - one/two/three/d.foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/three/d.foo", ); te.assert_output( &["--extension", ".foo"], - "a.foo - one/b.foo - one/two/c.foo - one/two/three/d.foo", + "./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/three/d.foo", ); te.assert_output( &["--extension", ".foo", "--extension", "foo2"], - "a.foo - one/b.foo - one/two/c.foo - one/two/three/d.foo - one/two/C.Foo2", + "./a.foo + ./one/b.foo + ./one/two/c.foo + ./one/two/three/d.foo + ./one/two/C.Foo2", ); - te.assert_output(&["--extension", ".foo", "a"], "a.foo"); + te.assert_output(&["--extension", ".foo", "a"], "./a.foo"); - te.assert_output(&["--extension", "foo2"], "one/two/C.Foo2"); + te.assert_output(&["--extension", "foo2"], "./one/two/C.Foo2"); let te2 = TestEnv::new(&[], &["spam.bar.baz", "egg.bar.baz", "yolk.bar.baz.sig"]); te2.assert_output( &["--extension", ".bar.baz"], - "spam.bar.baz - egg.bar.baz", + "./spam.bar.baz + ./egg.bar.baz", ); - te2.assert_output(&["--extension", "sig"], "yolk.bar.baz.sig"); + te2.assert_output(&["--extension", "sig"], "./yolk.bar.baz.sig"); - te2.assert_output(&["--extension", "bar.baz.sig"], "yolk.bar.baz.sig"); + te2.assert_output(&["--extension", "bar.baz.sig"], "./yolk.bar.baz.sig"); let te3 = TestEnv::new(&[], &["latin1.e\u{301}xt", "smiley.☻"]); - te3.assert_output(&["--extension", "☻"], "smiley.☻"); + te3.assert_output(&["--extension", "☻"], "./smiley.☻"); - te3.assert_output(&["--extension", ".e\u{301}xt"], "latin1.e\u{301}xt"); + te3.assert_output(&["--extension", ".e\u{301}xt"], "./latin1.e\u{301}xt"); let te4 = TestEnv::new(&[], &[".hidden", "test.hidden"]); - te4.assert_output(&["--hidden", "--extension", ".hidden"], "test.hidden"); + te4.assert_output(&["--hidden", "--extension", ".hidden"], "./test.hidden"); } /// No file extension (test for the pattern provided in the --help text) @@ -1102,21 +1102,21 @@ fn test_no_extension() { te.assert_output( &["^[^.]+$"], - "aa - one - one/bb - one/two - one/two/three - one/two/three/d - one/two/three/directory_foo - symlink", + "./aa + ./one + ./one/bb + ./one/two + ./one/two/three + ./one/two/three/d + ./one/two/three/directory_foo + ./symlink", ); te.assert_output( &["^[^.]+$", "--type", "file"], - "aa - one/bb - one/two/three/d", + "./aa + ./one/bb + ./one/two/three/d", ); } @@ -1251,46 +1251,46 @@ fn test_excludes() { te.assert_output( &["--exclude", "*.foo"], - "one - one/two - one/two/C.Foo2 - one/two/three - one/two/three/directory_foo - e1 e2 - symlink", + "./one + ./one/two + ./one/two/C.Foo2 + ./one/two/three + ./one/two/three/directory_foo + ./e1 e2 + ./symlink", ); te.assert_output( &["--exclude", "*.foo", "--exclude", "*.Foo2"], - "one - one/two - one/two/three - one/two/three/directory_foo - e1 e2 - symlink", + "./one + ./one/two + ./one/two/three + ./one/two/three/directory_foo + ./e1 e2 + ./symlink", ); te.assert_output( &["--exclude", "*.foo", "--exclude", "*.Foo2", "foo"], - "one/two/three/directory_foo", + "./one/two/three/directory_foo", ); te.assert_output( &["--exclude", "one/two", "foo"], - "a.foo - one/b.foo", + "./a.foo + ./one/b.foo", ); te.assert_output( &["--exclude", "one/**/*.foo"], - "a.foo - e1 e2 - one - one/two - one/two/C.Foo2 - one/two/three - one/two/three/directory_foo - symlink", + "./a.foo + ./e1 e2 + ./one + ./one/two + ./one/two/C.Foo2 + ./one/two/three + ./one/two/three/directory_foo + ./symlink", ); } @@ -1315,12 +1315,12 @@ fn test_exec() { te.assert_output( &["foo", "--exec", "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 + ./one/b.foo + ./one/two/C.Foo2 + ./one/two/c.foo + ./one/two/three/d.foo + ./one/two/three/directory_foo", ); te.assert_output( @@ -1356,14 +1356,14 @@ fn test_exec() { te.assert_output( &["foo", "--exec", "echo", "{//}"], ". - one - one/two - one/two - one/two/three - one/two/three", + ./one + ./one/two + ./one/two + ./one/two/three + ./one/two/three", ); - te.assert_output(&["e1", "--exec", "printf", "%s.%s\n"], "e1 e2."); + te.assert_output(&["e1", "--exec", "printf", "%s.%s\n"], "./e1 e2."); } } @@ -1384,7 +1384,7 @@ fn test_exec_batch() { te.assert_output( &["foo", "--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 ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo", ); te.assert_output( @@ -1430,7 +1430,7 @@ fn test_exec_batch_with_limit() { te.assert_output( &["foo", "--batch-size", "0", "--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 ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo", ); let output = te.assert_success_and_get_output( @@ -1451,12 +1451,12 @@ fn test_exec_batch_with_limit() { assert_eq!( &paths, &[ - "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", + "./one/b.foo", + "./one/two/C.Foo2", + "./one/two/c.foo", + "./one/two/three/d.foo", + "./one/two/three/directory_foo" ], ); } @@ -1486,12 +1486,12 @@ fn test_exec_with_separator() { te.assert_output( &["--path-separator=#", "foo", "--exec", "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 + .#one#b.foo + .#one#two#C.Foo2 + .#one#two#c.foo + .#one#two#three#d.foo + .#one#two#three#directory_foo", ); te.assert_output( @@ -1527,16 +1527,16 @@ fn test_exec_with_separator() { te.assert_output( &["--path-separator=#", "foo", "--exec", "echo", "{//}"], ". - one - one#two - one#two - one#two#three - one#two#three", + .#one + .#one#two + .#one#two + .#one#two#three + .#one#two#three", ); te.assert_output( &["--path-separator=#", "e1", "--exec", "printf", "%s.%s\n"], - "e1 e2.", + ".#e1 e2.", ); } @@ -1563,12 +1563,12 @@ fn test_fixed_strings() { // Regex search, dot is treated as "any character" te.assert_output( &["a.foo"], - "test1/a.foo - test1/a_foo", + "./test1/a.foo + ./test1/a_foo", ); // Literal search, dot is treated as character - te.assert_output(&["--fixed-strings", "a.foo"], "test1/a.foo"); + te.assert_output(&["--fixed-strings", "a.foo"], "./test1/a.foo"); // Regex search, parens are treated as group te.assert_output(&["download (1)"], ""); @@ -1576,7 +1576,7 @@ fn test_fixed_strings() { // Literal search, parens are treated as characters te.assert_output( &["--fixed-strings", "download (1)"], - "test2/Download (1).tar.gz", + "./test2/Download (1).tar.gz", ); // Combine with --case-sensitive @@ -1622,69 +1622,81 @@ fn test_size() { // Zero and non-zero sized files. te.assert_output( &["", "--size", "+0B"], - "0_bytes.foo - 11_bytes.foo - 30_bytes.foo - 3_kilobytes.foo - 4_kibibytes.foo", + "./0_bytes.foo + ./11_bytes.foo + ./30_bytes.foo + ./3_kilobytes.foo + ./4_kibibytes.foo", ); // Zero sized files. - te.assert_output(&["", "--size", "-0B"], "0_bytes.foo"); - te.assert_output(&["", "--size", "0B"], "0_bytes.foo"); - te.assert_output(&["", "--size=0B"], "0_bytes.foo"); - te.assert_output(&["", "-S", "0B"], "0_bytes.foo"); + te.assert_output(&["", "--size", "-0B"], "./0_bytes.foo"); + te.assert_output(&["", "--size", "0B"], "./0_bytes.foo"); + te.assert_output(&["", "--size=0B"], "./0_bytes.foo"); + te.assert_output(&["", "-S", "0B"], "./0_bytes.foo"); // Files with 2 bytes or more. te.assert_output( &["", "--size", "+2B"], - "11_bytes.foo - 30_bytes.foo - 3_kilobytes.foo - 4_kibibytes.foo", + "./11_bytes.foo + ./30_bytes.foo + ./3_kilobytes.foo + ./4_kibibytes.foo", ); // Files with 2 bytes or less. - te.assert_output(&["", "--size", "-2B"], "0_bytes.foo"); + te.assert_output(&["", "--size", "-2B"], "./0_bytes.foo"); // Files with size between 1 byte and 11 bytes. - te.assert_output(&["", "--size", "+1B", "--size", "-11B"], "11_bytes.foo"); + te.assert_output(&["", "--size", "+1B", "--size", "-11B"], "./11_bytes.foo"); // Files with size equal 11 bytes. - te.assert_output(&["", "--size", "11B"], "11_bytes.foo"); + te.assert_output(&["", "--size", "11B"], "./11_bytes.foo"); // Files with size between 1 byte and 30 bytes. te.assert_output( &["", "--size", "+1B", "--size", "-30B"], - "11_bytes.foo - 30_bytes.foo", + "./11_bytes.foo + ./30_bytes.foo", ); // Combine with a search pattern - te.assert_output(&["^11_", "--size", "+1B", "--size", "-30B"], "11_bytes.foo"); + te.assert_output( + &["^11_", "--size", "+1B", "--size", "-30B"], + "./11_bytes.foo", + ); // Files with size between 12 and 30 bytes. - te.assert_output(&["", "--size", "+12B", "--size", "-30B"], "30_bytes.foo"); + te.assert_output(&["", "--size", "+12B", "--size", "-30B"], "./30_bytes.foo"); // Files with size between 31 and 100 bytes. te.assert_output(&["", "--size", "+31B", "--size", "-100B"], ""); // Files with size between 3 kibibytes and 5 kibibytes. - te.assert_output(&["", "--size", "+3ki", "--size", "-5ki"], "4_kibibytes.foo"); + te.assert_output( + &["", "--size", "+3ki", "--size", "-5ki"], + "./4_kibibytes.foo", + ); // Files with size between 3 kilobytes and 5 kilobytes. te.assert_output( &["", "--size", "+3k", "--size", "-5k"], - "3_kilobytes.foo - 4_kibibytes.foo", + "./3_kilobytes.foo + ./4_kibibytes.foo", ); // Files with size greater than 3 kilobytes and less than 3 kibibytes. - te.assert_output(&["", "--size", "+3k", "--size", "-3ki"], "3_kilobytes.foo"); + te.assert_output( + &["", "--size", "+3k", "--size", "-3ki"], + "./3_kilobytes.foo", + ); // Files with size equal 4 kibibytes. - te.assert_output(&["", "--size", "+4ki", "--size", "-4ki"], "4_kibibytes.foo"); - te.assert_output(&["", "--size", "4ki"], "4_kibibytes.foo"); + te.assert_output( + &["", "--size", "+4ki", "--size", "-4ki"], + "./4_kibibytes.foo", + ); + te.assert_output(&["", "--size", "4ki"], "./4_kibibytes.foo"); } #[cfg(test)] @@ -1720,23 +1732,23 @@ fn test_modified_relative() { te.assert_output( &["", "--changed-within", "15min"], - "foo_0_now - bar_1_min - foo_10_min", + "./foo_0_now + ./bar_1_min + ./foo_10_min", ); te.assert_output( &["", "--change-older-than", "15min"], - "bar_1_h - foo_2_h - bar_1_day", + "./bar_1_h + ./foo_2_h + ./bar_1_day", ); te.assert_output( &["foo", "--changed-within", "12h"], - "foo_0_now - foo_10_min - foo_2_h", + "./foo_0_now + ./foo_10_min + ./foo_2_h", ); } @@ -1756,11 +1768,11 @@ fn test_modified_absolute() { te.assert_output( &["", "--change-newer-than", "2018-01-01 00:00:00"], - "15mar2018", + "./15mar2018", ); te.assert_output( &["", "--changed-before", "2018-01-01 00:00:00"], - "30dec2017", + "./30dec2017", ); } @@ -1784,21 +1796,21 @@ fn test_base_directory() { te.assert_output( &["--base-directory", "one"], - "b.foo - two - two/c.foo - two/C.Foo2 - two/three - two/three/d.foo - two/three/directory_foo", + "./b.foo + ./two + ./two/c.foo + ./two/C.Foo2 + ./two/three + ./two/three/d.foo + ./two/three/directory_foo", ); te.assert_output( &["--base-directory", "one/two", "foo"], - "c.foo - C.Foo2 - three/d.foo - three/directory_foo", + "./c.foo + ./C.Foo2 + ./three/d.foo + ./three/directory_foo", ); // Explicit root path @@ -1834,15 +1846,15 @@ fn test_max_results() { // Unrestricted te.assert_output( &["--max-results=0", "c.foo"], - "one/two/C.Foo2 - one/two/c.foo", + "./one/two/C.Foo2 + ./one/two/c.foo", ); // Limited to two results te.assert_output( &["--max-results=2", "c.foo"], - "one/two/C.Foo2 - one/two/c.foo", + "./one/two/C.Foo2 + ./one/two/c.foo", ); // Limited to one result. We could find either C.Foo2 or c.foo @@ -1851,7 +1863,7 @@ fn test_max_results() { let stdout = String::from_utf8_lossy(&output.stdout) .trim() .replace(&std::path::MAIN_SEPARATOR.to_string(), "/"); - assert!(stdout == "one/two/C.Foo2" || stdout == "one/two/c.foo"); + assert!(stdout == "./one/two/C.Foo2" || stdout == "./one/two/c.foo"); }; assert_just_one_result_with_option("--max-results=1"); assert_just_one_result_with_option("-1"); @@ -1964,7 +1976,27 @@ fn test_error_if_hidden_not_set_and_pattern_starts_with_dot() { te.assert_failure(&["^\\.gitignore"]); te.assert_failure(&["--glob", ".gitignore"]); - te.assert_output(&["--hidden", "^\\.gitignore"], ".gitignore"); - te.assert_output(&["--hidden", "--glob", ".gitignore"], ".gitignore"); + te.assert_output(&["--hidden", "^\\.gitignore"], "./.gitignore"); + te.assert_output(&["--hidden", "--glob", ".gitignore"], "./.gitignore"); te.assert_output(&[".gitignore"], ""); } + +#[test] +fn test_strip_cwd_prefix() { + let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); + + te.assert_output( + &["--strip-cwd-prefix", "."], + "a.foo + e1 e2 + one + one/b.foo + one/two + one/two/c.foo + one/two/C.Foo2 + one/two/three + one/two/three/d.foo + one/two/three/directory_foo + symlink", + ); +}