Repository: sharkdp/fd
Pull request #520 (2019-12-20 20:33:29)

Quit immediately if the channel::send call failed


Patch:
diff --git a/src/app.rs b/src/app.rs
index f42ac8c..b86169d 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -257,6 +257,14 @@ pub fn build_app() -> App<'static, 'static> {
                 .hidden_short_help(true)
                 .overrides_with("show-errors"),
         )
+        .arg(
+            arg("base-directory")
+                .long("base-directory")
+                .takes_value(true)
+                .value_name("path")
+                .number_of_values(1)
+                .hidden_short_help(true),
+        )
         .arg(arg("pattern"))
         .arg(
             arg("path-separator")
@@ -443,5 +451,11 @@ fn usage() -> HashMap<&'static str, Help> {
         , "(hidden)"
         , "Provide paths to search as an alternative to the positional <path> argument. \
            Changes the usage to `fd [FLAGS/OPTIONS] --search-path <path> --search-path <path2> [<pattern>]`");
+    doc!(h, "base-directory"
+        , "(hidden)"
+        , "Change the current working directory of fd to the provided path. The means that search \
+           results will be shown with respect to the given base path. Note that relative paths \
+           which are passed to fd via the positional <path> argument or the '--search-path' option \
+           will also be resolved relative to this directory.");
     h
 }
diff --git a/src/main.rs b/src/main.rs
index 426eb08..e17dc7d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -44,6 +44,23 @@ fn main() {
     let checked_args = transform_args_with_exec(env::args_os());
     let matches = app::build_app().get_matches_from(checked_args);
 
+    // Set the current working directory of the process
+    if let Some(base_directory) = matches.value_of("base-directory") {
+        let basedir = Path::new(base_directory);
+        if !fshelper::is_dir(basedir) {
+            print_error_and_exit!(
+                "The '--base-directory' path ('{}') is not a directory.",
+                basedir.to_string_lossy()
+            );
+        }
+        if let Err(e) = env::set_current_dir(basedir) {
+            print_error_and_exit!(
+                "Could not set '{}' as the current working directory: {}", 
+                basedir.to_string_lossy(), e
+            );
+        }
+    }
+
     // Get the search pattern
     let pattern = matches.value_of("pattern").unwrap_or("");
 
diff --git a/src/walk.rs b/src/walk.rs
index df25666..4554a95 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -373,10 +373,12 @@ fn spawn_senders(
                 }
             }
 
-            // TODO: take care of the unwrap call
-            tx_thread
-                .send(WorkerResult::Entry(entry_path.to_owned()))
-                .unwrap();
+            let send_result = tx_thread
+                .send(WorkerResult::Entry(entry_path.to_owned()));
+
+            if !send_result.is_ok() {
+                return ignore::WalkState::Quit;
+            }
 
             ignore::WalkState::Continue
         })


Test patch:
diff --git a/tests/tests.rs b/tests/tests.rs
index d9c0130..7237252 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1350,3 +1350,53 @@ fn test_custom_path_separator() {
         one=two=three=directory_foo",
     );
 }
+
+#[test]
+fn test_base_directory() {
+    let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
+
+    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",
+    );
+    
+    te.assert_output(
+        &["--base-directory", "one/two", "foo"],
+        "c.foo
+        C.Foo2
+        three/d.foo
+        three/directory_foo",
+    );
+
+    // Explicit root path
+    te.assert_output(
+        &["--base-directory", "one", "foo", "two"],
+        "two/c.foo
+        two/C.Foo2
+        two/three/d.foo
+        two/three/directory_foo",
+    );
+
+    // Ignore base directory when absolute path is used
+    let (te, abs_path) = get_test_env_with_abs_path(DEFAULT_DIRS, DEFAULT_FILES);
+    let abs_base_dir = &format!("{abs_path}/one/two", abs_path = &abs_path);
+    te.assert_output(
+        &["--base-directory", &abs_base_dir, "foo", &abs_path],
+        &format!(
+            "{abs_path}/a.foo
+            {abs_path}/one/b.foo
+            {abs_path}/one/two/c.foo
+            {abs_path}/one/two/C.Foo2
+            {abs_path}/one/two/three/d.foo
+            {abs_path}/one/two/three/directory_foo",
+            abs_path = &abs_path
+        ),
+    );
+
+}