fix: handle mirror file errors

This commit is contained in:
Tienson Qin
2026-05-07 18:08:42 +08:00
parent 0a4b59f0e0
commit a256c65cbc
4 changed files with 81 additions and 4 deletions

View File

@@ -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"])

View File

@@ -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"))))

View File

@@ -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- <read-text
[platform* path]
(if-let [f (or (:mirror-read-text! (storage platform*))
(:read-text! (storage platform*)))]
(-> (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- <write-text-atomic!

View File

@@ -35,6 +35,13 @@
(defn- page-path [path]
(str (markdown-mirror/repo-mirror-dir test-repo) "/" path))
(defn- js-error
[message data]
(let [error (js/Error. message)]
(doseq [[k v] data]
(aset error (name k) v))
error))
(defn- first-block [page]
(-> 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/<mirror-page!
test-repo @conn (:db/id page)
{:platform (assoc-in platform [:storage :read-text!]
(fn [_path] (p/rejected missing-error)))})
(p/then (fn [_]
(let [path (page-path "pages/Page A.md")]
(is (= "- hello" (get @files path)))
(is (= [[path "- hello"]] @writes)))))
(p/catch (fn [e] (is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest unexpected-mirror-file-read-error-rejects-page-mirror-test
(async done
(let [{:keys [platform writes]} (fake-platform)
read-error (ex-info "permission denied" {:code :eacces})
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/<mirror-page!
test-repo @conn (:db/id page)
{:platform (assoc-in platform [:storage :read-text!]
(fn [_path] (p/rejected read-error)))})
(p/then (fn [_]
(is false "Expected mirror write to reject when read fails unexpectedly")))
(p/catch (fn [error]
(is (= read-error error))
(is (empty? @writes))))
(p/finally done)))))
(deftest page-mirror-exports-property-values-test
(async done
(let [{:keys [platform files]} (fake-platform)