From a256c65cbc60d2abd6bfbd3f8aee6caa4d018326 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 7 May 2026 18:08:42 +0800 Subject: [PATCH] fix: handle mirror file errors --- deps/common/src/logseq/common/graph.cljs | 10 ++++- .../common/test/logseq/common/graph_test.cljs | 15 ++++++- src/main/frontend/worker/markdown_mirror.cljs | 15 ++++++- .../frontend/worker/markdown_mirror_test.cljs | 45 +++++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/deps/common/src/logseq/common/graph.cljs b/deps/common/src/logseq/common/graph.cljs index 49e47a9a19..a9838ebf5d 100644 --- a/deps/common/src/logseq/common/graph.cljs +++ b/deps/common/src/logseq/common/graph.cljs @@ -51,6 +51,11 @@ (filter #(.isDirectory %)) (map #(.-name %))))) +(defn- path-at-or-under? + [path dir] + (or (= path dir) + (string/starts-with? path (str dir "/")))) + (defn ignored-path? "Given a graph directory and path, returns truthy value on whether the path is ignored. Useful for contexts like reading a graph's directory and file watcher @@ -73,8 +78,9 @@ Rules: rpath (path/trim-dir-prefix dir path)] (when (string? path) (or - (some #(string/starts-with? rpath %) - ["." "logseq/.recycle" "logseq/bak" "logseq/version-files" "mirror/markdown"]) + (string/starts-with? rpath ".") + (some #(path-at-or-under? rpath %) + ["logseq/.recycle" "logseq/bak" "logseq/version-files" "mirror/markdown"]) (contains? #{"logseq/graphs-txid.edn" "logseq/pages-metadata.edn"} rpath) (some #(string/includes? rpath (str "/" % "/")) ["node_modules"]) diff --git a/deps/common/test/logseq/common/graph_test.cljs b/deps/common/test/logseq/common/graph_test.cljs index 32d2d10563..b4380fb34f 100644 --- a/deps/common/test/logseq/common/graph_test.cljs +++ b/deps/common/test/logseq/common/graph_test.cljs @@ -27,11 +27,24 @@ ;; Create files that are recognized (fs/writeFileSync "tmp/test-graph/pages/foo.md" "") (fs/writeFileSync "tmp/test-graph/journals/2023_05_09.md" "") + (fs/mkdirSync (node-path/join "tmp/test-graph" "mirror" "markdown-notes") #js {:recursive true}) + (fs/mkdirSync (node-path/join "tmp/test-graph" "mirror" "markdown2") #js {:recursive true}) + (fs/writeFileSync "tmp/test-graph/mirror/markdown-notes/foo.md" "") + (fs/writeFileSync "tmp/test-graph/mirror/markdown2/foo.md" "") ;; Create files that are ignored (fs/mkdirSync (node-path/join "tmp/test-graph" "logseq" "bak")) (fs/mkdirSync (node-path/join "tmp/test-graph" "mirror" "markdown" "pages") #js {:recursive true}) (fs/writeFileSync "tmp/test-graph/logseq/bak/baz.md" "") (fs/writeFileSync "tmp/test-graph/logseq/.gitignore" "") (fs/writeFileSync "tmp/test-graph/mirror/markdown/pages/foo.md" "") - (is (= ["tmp/test-graph/journals/2023_05_09.md" "tmp/test-graph/pages/foo.md"] + (is (= ["tmp/test-graph/journals/2023_05_09.md" + "tmp/test-graph/mirror/markdown-notes/foo.md" + "tmp/test-graph/mirror/markdown2/foo.md" + "tmp/test-graph/pages/foo.md"] (common-graph/get-files "tmp/test-graph")))) + +(deftest ignored-markdown-mirror-path-honors-directory-boundary-test + (is (common-graph/ignored-path? "tmp/test-graph" "tmp/test-graph/mirror/markdown")) + (is (common-graph/ignored-path? "tmp/test-graph" "tmp/test-graph/mirror/markdown/pages/foo.md")) + (is (not (common-graph/ignored-path? "tmp/test-graph" "tmp/test-graph/mirror/markdown-notes/foo.md"))) + (is (not (common-graph/ignored-path? "tmp/test-graph" "tmp/test-graph/mirror/markdown2/foo.md")))) diff --git a/src/main/frontend/worker/markdown_mirror.cljs b/src/main/frontend/worker/markdown_mirror.cljs index 9acb6d663a..15fbf4b8d4 100644 --- a/src/main/frontend/worker/markdown_mirror.cljs +++ b/src/main/frontend/worker/markdown_mirror.cljs @@ -145,12 +145,25 @@ [platform*] (:storage platform*)) +(defn- not-found-error? + [error] + (let [data (ex-data error) + code (or (:code data) (some-> error .-code)) + name (some-> error .-name) + message (some-> error .-message)] + (or (contains? #{:not-found :enoent "ENOENT" "NotFoundError"} code) + (= "NotFoundError" name) + (boolean (some-> message (string/starts-with? "ENOENT:")))))) + (defn- (f path) - (p/catch (constantly nil))) + (p/catch (fn [error] + (if (not-found-error? error) + nil + (p/rejected error))))) (p/rejected (ex-info "platform storage/read-text! missing" {:path path})))) (defn- page :block/_page first)) @@ -149,6 +156,44 @@ (p/catch (fn [e] (is false (str "unexpected error: " e)))) (p/finally done))))) +(deftest missing-mirror-file-read-still-writes-page-mirror-test + (async done + (let [{:keys [platform files writes]} (fake-platform) + missing-error (js-error "ENOENT: missing mirror file" {:code "ENOENT"}) + conn (db-test/create-conn-with-blocks + {:pages-and-blocks [{:page {:block/title "Page A"} + :blocks [{:block/title "hello"}]}]}) + page (db-test/find-page-by-title @conn "Page A")] + (-> (markdown-mirror/ (markdown-mirror/