Explorar o código

refactor(fs): handle asset deletion

Andelf %!s(int64=2) %!d(string=hai) anos
pai
achega
bbb655ff43

+ 1 - 1
src/main/frontend/components/block.cljs

@@ -202,7 +202,7 @@
                         (if (string/blank? asset-path)
                           (reset! *exist? false)
                           ;; FIXME(andelf): possible bug here
-                          (p/let [exist? (fs/file-or-href-exists? "" asset-path)]
+                          (p/let [exist? (fs/asset-href-exists? asset-path)]
                             (reset! *exist? (boolean exist?))))
                         (assoc state ::asset-path asset-path ::asset-file? true))
                       state)))

+ 3 - 2
src/main/frontend/config.cljs

@@ -2,6 +2,7 @@
   "App config and fns built on top of configuration"
   (:require [clojure.set :as set]
             [clojure.string :as string]
+            [frontend.fs2.path :as fs2-path]
             [frontend.mobile.util :as mobile-util]
             [frontend.state :as state]
             [frontend.util :as util]
@@ -396,11 +397,11 @@
               (str "/" (string/capitalize app-name) "/")))
     (get-repo-dir repo-dir)))
 
-(defn get-repo-path
+(defn get-repo-fpath
   [repo-url path]
   (if (and (or (util/electron?) (mobile-util/native-platform?))
            (local-db? repo-url))
-    path
+    (fs2-path/path-join (get-repo-dir repo-url) path)
     (util/node-path.join (get-repo-dir repo-url) path)))
 
 ;; FIXME: There is another normalize-file-protocol-path at src/main/frontend/fs/capacitor_fs.cljs

+ 10 - 10
src/main/frontend/fs.cljs

@@ -65,8 +65,8 @@
 
 (defn unlink!
   "Should move the path to logseq/recycle instead of deleting it."
-  [repo path opts]
-  (protocol/unlink! (get-fs path) repo path opts))
+  [repo fpath opts]
+  (protocol/unlink! (get-fs fpath) repo fpath opts))
 
 (defn rmdir!
   "Remove the directory recursively.
@@ -234,14 +234,14 @@
    (fn [stat] (not (nil? stat)))
    (fn [_e] false)))
 
-(defn file-or-href-exists?
-  "It not only accept path, but also href (url encoded path)"
-  [dir href]
-  (p/let [exist? (file-exists? dir href)
-          decoded-href   (gp-util/safe-decode-uri-component href)
-          decoded-exist? (when (not= decoded-href href)
-                           (file-exists? dir decoded-href))]
-    (or exist? decoded-exist?)))
+(defn asset-href-exists?
+  "href is from `make-asset-url`, so it's most likely a full-path"
+  [href]
+  (p/let [repo-dir (config/get-repo-dir (state/get-current-repo))
+          rpath (fs2-path/relative-path repo-dir href)
+          exist? (file-exists? repo-dir rpath)]
+    (prn ::href href exist?)
+    exist?))
 
 (defn dir-exists?
   [dir]

+ 8 - 9
src/main/frontend/fs/capacitor_fs.cljs

@@ -360,17 +360,16 @@
                 (str "file://" dir)
                 dir)]
       (readdir dir)))
-  (unlink! [this repo path _opts]
-    (p/let [_ (prn ::unlink path)
-            repo-url (config/get-local-dir repo)
-            recycle-dir (util/safe-path-join repo-url config/app-name ".recycle") ;; logseq/.recycle
+  (unlink! [this repo fpath _opts]
+    (p/let [_ (prn ::unlink fpath)
+            repo-dir (config/get-local-dir repo)
+            recycle-dir (fs2-path/path-join repo-dir config/app-name ".recycle") ;; logseq/.recycle
             ;; convert url to pure path
-            file-name (-> (string/replace path repo-url "")
-                          (string/replace "/" "_")
-                          (string/replace "\\" "_"))
-            new-path (str recycle-dir "/" file-name)
+            file-name (-> (fs2-path/trim-dir-prefix repo-dir fpath)
+                          (string/replace "/" "_"))
+            new-path (fs2-path/path-join recycle-dir file-name)
             _ (protocol/mkdir-recur! this recycle-dir)]
-      (protocol/rename! this repo path new-path)))
+      (protocol/rename! this repo fpath new-path)))
   (rmdir! [_this _dir]
     ;; Too dangerous!!! We'll never implement this.
     nil)

+ 1 - 2
src/main/frontend/fs/watcher_handler.cljs

@@ -57,8 +57,7 @@
           ;; on the client to correctly identify it
           repo (if global-dir (state/get-current-repo) (config/get-local-repo dir))
           {:keys [mtime]} stat
-          db-content (or (db/get-file repo path) "")
-          _ (prn ::read-out-db-cont db-content content)]
+          db-content (or (db/get-file repo path) "")]
       
       (when (or content (contains? #{"unlink" "unlinkDir" "addDir"} type))
         (cond

+ 45 - 6
src/main/frontend/fs2/path.cljs

@@ -63,9 +63,7 @@
   "Joins the given path segments into a single path, handling relative paths,
   '..' and '.' normalization."
   [& segments]
-  (let [segments (remove nil? segments) ;; handle (path-join nil path)
-        _ (prn ::join-seg segments)
-        ;; _ (js/console.trace)
+  (let [segments (remove string/blank? segments) ;; handle (path-join nil path)
         segments (map #(string/replace % #"[/\\]+" "/") segments)
         ;; a fix for clojure.string/split
         split-fn (fn [s]
@@ -105,7 +103,7 @@
   '..' and '.' normalization."
   [& segments]
   (let [segments (remove nil? segments) ;; handle (path-join nil path)
-        _ (prn ::uri-join-seg segments)
+        ; _ (prn ::uri-join-seg segments)
         ; _ (js/console.trace)
         segments (map #(string/replace % #"[/\\]+" "/") segments)
         ;; a fix for clojure.string/split
@@ -156,6 +154,11 @@
 (defn path-join
   "Join path segments, or URL base and path segments"
   [base & segments]
+  (prn ::join base segments)
+  (when (string/blank? base)
+    (prn ::SHOULD-NOT-JOIN-EMPTY)
+    (js/console.trace))
+
   (if (is-file-url base)
     (apply url-join base segments)
     (apply path-join-internal base segments)))
@@ -212,21 +215,57 @@
         (gp-util/safe-decode-uri-component (string/replace (subs sub-path (count base-path)) #"^/+", ""))
         (string/replace (subs sub-path (count base-path)) #"^/+", ""))
        ;; append as many .. 
+      ;; NOTE: buggy impl
       (let [base-segs (string/split base-path #"/" -1)
             path-segs (string/split sub-path #"/" -1)
             common-segs (take-while #(= (first %) (second %)) (map vector base-segs path-segs))
             base-segs (drop (count common-segs) base-segs)
             remain-segs (drop (count common-segs) path-segs)
             base-prefix (apply str (repeat (max 0 (dec (count base-segs))) "../"))]
+        (js/console.error (js/Error. "buggy"))
         #_{:clj-kondo/ignore [:path-invalid-construct/string-join]}
         (if is-url?
           (gp-util/safe-decode-uri-component (str base-prefix (string/join "/" remain-segs)))
           (str base-prefix (string/join "/" remain-segs)))))))
 
 
+
 (defn parent
   "Parent, containing directory"
   [path]
-  ;; ugly but works
-  (path-normalize (str path "/..")))
+  (if (string/includes? path "/")
+    ;; ugly but works
+    (path-normalize (str path "/.."))
+    nil))
+
+
+
+(defn resolve-relative-path
+  "Assume current-path is a file"
+  [current-path rel-path]
+  (if-let [base-dir (parent current-path)]
+    (path-join base-dir rel-path)
+    rel-path))
+
+(defn get-relative-path
+  "Assume current-path is a file, and target-path is a file or directory.
+   Return relative path from current-path to target-path.
+   Works for both path and URL. Also works for relative path.
+   The opposite operation is `resolve-relative-path`"
+  [current-path target-path]
+  (let [base-path (parent current-path)
+        sub-path (path-normalize target-path)
+        is-url? (is-file-url base-path)
+        base-segs (if base-path
+                    (string/split base-path #"/" -1)
+                    [])
+        path-segs (string/split sub-path #"/" -1)
+        common-segs (take-while #(= (first %) (second %)) (map vector base-segs path-segs))
+        base-segs (drop (count common-segs) base-segs)
+        remain-segs (drop (count common-segs) path-segs)
+        base-prefix (apply str (repeat (max 0 (count base-segs)) "../"))]
+    #_{:clj-kondo/ignore [:path-invalid-construct/string-join]}
+    (if is-url?
+      (gp-util/safe-decode-uri-component (str base-prefix (string/join "/" remain-segs)))
+      (str base-prefix (string/join "/" remain-segs)))))
 

+ 12 - 10
src/main/frontend/handler/editor.cljs

@@ -55,7 +55,8 @@
             [logseq.graph-parser.util.page-ref :as page-ref]
             [promesa.core :as p]
             [rum.core :as rum]
-            [frontend.fs2.path :as fs2-path]))
+            [frontend.fs2.path :as fs2-path]
+            [frontend.db.model :as model]))
 
 ;; FIXME: should support multiple images concurrently uploading
 
@@ -381,8 +382,8 @@
      (let [block' (wrap-parse-block block)
            opts' (merge opts {:outliner-op :save-block})]
        (outliner-tx/transact!
-         opts'
-         (outliner-core/save-block! block'))
+        opts'
+        (outliner-core/save-block! block'))
 
        ;; sanitized page name changed
        (when-let [title (get-in block' [:block/properties :title])]
@@ -1494,14 +1495,15 @@
         content (string/replace text full-text "")]
     (save-block! repo block content)
     (when (and local? delete-local?)
-      ;; FIXME: should be relative to current block page path
       (when-let [href (if (util/electron?) href
-                        (second (re-find #"\((.+)\)$" full-text)))]
-        (fs/unlink! repo
-                    (config/get-repo-path
-                     repo (-> href
-                              (string/replace #"^../" "/")
-                              (string/replace #"^assets://" ""))) nil)))))
+                          (second (re-find #"\((.+)\)$" full-text)))]
+        (let [block-file-rpath (model/get-block-file-path block)
+              asset-fpath (if (string/starts-with? href "asset://")
+                            (throw (js/Error. "unimpl"))
+                            (config/get-repo-fpath
+                             repo
+                             (fs2-path/resolve-relative-path block-file-rpath href)))]
+          (fs/unlink! repo asset-fpath nil))))))
 
 ;; assets/journals_2021_02_03_1612350230540_0.png
 (defn resolve-relative-path

+ 1 - 1
src/main/frontend/handler/page.cljs

@@ -183,7 +183,7 @@
     (when-not (string/blank? file-path)
       (db/transact! [[:db.fn/retractEntity [:file/path file-path]]])
       (when unlink-file?
-        (-> (fs/unlink! repo (config/get-repo-path repo file-path) nil)
+        (-> (fs/unlink! repo (config/get-repo-fpath repo file-path) nil)
             (p/catch (fn [error] (js/console.error error))))))))
 
 (defn- compute-new-file-path