From 0e12b285cd6d0d2cfceecfcaf67b71b5df315dbe Mon Sep 17 00:00:00 2001
From: sigoden <sigoden@gmail.com>
Date: Fri, 3 Mar 2023 07:15:46 +0800
Subject: [PATCH] fix: hidden don't works on some files (#188)

like --hidden '*.abc-cba' matches xyz.abc-cba but do not matches 123.xyz.abc-cba
---
 Cargo.lock   |  7 +++++++
 Cargo.toml   |  1 +
 README.md    | 13 +++++--------
 src/utils.rs | 49 ++++++++++---------------------------------------
 4 files changed, 23 insertions(+), 47 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 49fb386..400effa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -444,6 +444,7 @@ dependencies = [
  "diqwest",
  "form_urlencoded",
  "futures",
+ "glob",
  "headers",
  "hyper",
  "if-addrs",
@@ -683,6 +684,12 @@ dependencies = [
  "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
 [[package]]
 name = "globset"
 version = "0.4.10"
diff --git a/Cargo.toml b/Cargo.toml
index 8a7a68c..72bf47b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -43,6 +43,7 @@ alphanumeric-sort = "1.4"
 content_inspector = "0.2"
 anyhow = "1.0"
 chardetng = "0.1"
+glob = "0.3.1"
 
 [features]
 default = ["tls"]
diff --git a/README.md b/README.md
index 1f6b1de..3ff314d 100644
--- a/README.md
+++ b/README.md
@@ -243,21 +243,18 @@ Since dufs only allows viewing/downloading, `admin` can only view/download files
 
 ### Hide Paths
 
-Dufs supports hiding paths from directory listings via option `--hidden`.
+Dufs supports hiding paths from directory listings via option `--hidden <glob>,...`.
 
 ```
 dufs --hidden .git,.DS_Store,tmp
 ```
 
-`--hidden` also supports a variant glob:
-
-- `?` matches any single character
-- `*` matches any (possibly empty) sequence of characters
-- `**`, `[..]`, `[!..]` is not supported
+> The glob used in --hidden only matches file and directory names, not paths. So `--hidden dir1/file` is invalid.
 
 ```sh
-dufs --hidden '.*'
-dufs --hidden '*.log,*.lock'
+dufs --hidden '.*'            # hidden dotfiles
+dufs --hidden '*/'            # hidden all folders
+dufs --hidden '*.log,*.lock'  # hidden by exts
 ```
 
 ### Log Format
diff --git a/src/utils.rs b/src/utils.rs
index 4a8a6fe..b9e11b7 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -34,45 +34,12 @@ pub fn try_get_file_name(path: &Path) -> Result<&str> {
         .ok_or_else(|| anyhow!("Failed to get file name of `{}`", path.display()))
 }
 
-pub fn glob(source: &str, target: &str) -> bool {
-    let ss: Vec<char> = source.chars().collect();
-    let mut iter = target.chars();
-    let mut i = 0;
-    'outer: while i < ss.len() {
-        let s = ss[i];
-        match s {
-            '*' => match ss.get(i + 1) {
-                Some(s_next) => {
-                    for t in iter.by_ref() {
-                        if t == *s_next {
-                            i += 2;
-                            continue 'outer;
-                        }
-                    }
-                    return false;
-                }
-                None => return true,
-            },
-            '?' => match iter.next() {
-                Some(_) => {
-                    i += 1;
-                    continue;
-                }
-                None => return false,
-            },
-            _ => match iter.next() {
-                Some(t) => {
-                    if s == t {
-                        i += 1;
-                        continue;
-                    }
-                    return false;
-                }
-                None => return false,
-            },
-        }
-    }
-    iter.next().is_none()
+pub fn glob(pattern: &str, target: &str) -> bool {
+    let pat = match ::glob::Pattern::new(pattern) {
+        Ok(pat) => pat,
+        Err(_) => return false,
+    };
+    pat.matches(target)
 }
 
 #[test]
@@ -91,6 +58,10 @@ fn test_glob_key() {
     assert!(!glob("abc", "abcd"));
     assert!(!glob("a?c", "abbc"));
     assert!(!glob("*.log", "log"));
+    assert!(glob("*.abc-cba", "xyz.abc-cba"));
+    assert!(glob("*.abc-cba", "123.xyz.abc-cba"));
     assert!(glob("*.log", ".log"));
     assert!(glob("*.log", "a.log"));
+    assert!(glob("*/", "abc/"));
+    assert!(!glob("*/", "abc"));
 }