Просмотр исходного кода

fix: don't store broken config in DB (#8578)

* fix: don't store broken config in DB

Also, all configs should be clojure maps.

* fix: editor should show the corresponding file's content from disk
Tienson Qin 3 лет назад
Родитель
Сommit
dcf9559094

+ 40 - 18
src/main/frontend/components/file.cljs

@@ -11,11 +11,15 @@
             [frontend.handler.export :as export-handler]
             [frontend.state :as state]
             [frontend.util :as util]
+            [frontend.fs :as fs]
+            [frontend.config :as config]
+            [frontend.ui :as ui]
             [logseq.graph-parser.config :as gp-config]
             [logseq.graph-parser.util :as gp-util]
             [goog.object :as gobj]
             [reitit.frontend.easy :as rfe]
-            [rum.core :as rum]))
+            [rum.core :as rum]
+            [promesa.core :as p]))
 
 (defn- get-path
   [state]
@@ -66,18 +70,25 @@
    (files-all)
    ])
 
-(rum/defcs file < rum/reactive
-  {:did-mount (fn [state]
+(rum/defcs file-inner < rum/reactive
+  {:will-mount (fn [state]
+                 (let [*content (atom nil)
+                       [path format] (:rum/args state)]
+                   (when (and format (contains? (gp-config/text-formats) format))
+                     (p/let [content (fs/read-file
+                                      (config/get-repo-dir (state/get-current-repo)) path)]
+                       (reset! *content content)))
+                   (assoc state ::file-content *content)))
+   :did-mount (fn [state]
                 (state/set-file-component! (:rum/react-component state))
                 state)
    :will-unmount (fn [state]
                    (state/clear-file-component!)
                    state)}
-  [state]
-  (let [path (get-path state)
-        format (gp-util/get-format path)
-        original-name (db/get-file-page path)
-        random-id (str (d/squuid))]
+  [state path format]
+  (let [original-name (db/get-file-page path)
+        random-id (str (d/squuid))
+        content (rum/react (::file-content state))]
     [:div.file {:id (str "file-edit-wrapper-" random-id)
                 :key path}
      [:h1.title
@@ -107,16 +118,27 @@
        (and format (contains? (gp-config/img-formats) format))
        [:img {:src (util/node-path.join "file://" path)}]
 
-       (and format (contains? (gp-config/text-formats) format))
-       (when-let [file-content (or (db/get-file path) "")]
-         (let [content (string/trim file-content)
-               mode (util/get-file-ext path)]
-            (lazy-editor/editor {:file?     true
-                                 :file-path path}
-                                (str "file-edit-" random-id)
-                                {:data-lang mode}
-                                content
-                               {})))
+       (and format
+            (contains? (gp-config/text-formats) format)
+            content)
+       (let [content' (string/trim content)
+             mode (util/get-file-ext path)]
+         (lazy-editor/editor {:file?     true
+                              :file-path path}
+                             (str "file-edit-" random-id)
+                             {:data-lang mode}
+                             content'
+                             {}))
+
+       (and format
+            (contains? (gp-config/text-formats) format))
+       (ui/loading "Loading ...")
 
        :else
        [:div (t :file/format-not-supported (name format))])]))
+
+(rum/defcs file
+  [state]
+  (let [path (get-path state)
+        format (gp-util/get-format path)]
+    (rum/with-key (file-inner path format) path)))

+ 55 - 60
src/main/frontend/handler/file.cljs

@@ -21,6 +21,7 @@
             [promesa.core :as p]
             [frontend.mobile.util :as mobile-util]
             [logseq.graph-parser.config :as gp-config]
+            [clojure.string :as string]
             ["path" :as path]))
 
 ;; TODO: extract all git ops using a channel
@@ -104,8 +105,7 @@
     :else
     true))
 
-(defn- validate-and-write-file
-  "Validates and if valid writes file. Returns boolean indicating if file content was valid"
+(defn- write-file-aux!
   [repo path content write-file-options]
   (let [original-content (db/get-file repo path)
         path-dir (if (and
@@ -117,12 +117,7 @@
                    (config/get-repo-dir repo))
         write-file-options' (merge write-file-options
                                    (when original-content {:old-content original-content}))]
-    (p/do!
-     (if (validate-file repo path content)
-       (do
-         (fs/write-file! repo path-dir path content write-file-options')
-         true)
-       false))))
+    (fs/write-file! repo path-dir path content write-file-options')))
 
 ;; TODO: Remove this function in favor of `alter-files`
 (defn alter-file
@@ -133,58 +128,58 @@
                            from-disk? false
                            skip-compare? false}}]
   (let [path (gp-util/path-normalize path)
-        write-file! (if from-disk?
-                      #(p/promise (validate-file repo path content))
-                      #(validate-and-write-file repo path content {:skip-compare? skip-compare?}))
-        opts {:new-graph? new-graph?
-              :from-disk? from-disk?
-              :skip-db-transact? skip-db-transact?}
-        result (if reset?
-                 (do
-                   (when-not skip-db-transact?
-                     (when-let [page-id (db/get-file-page-id path)]
-                       (db/transact! repo
-                                     [[:db/retract page-id :block/alias]
-                                      [:db/retract page-id :block/tags]]
-                                     opts)))
-                   (file-common-handler/reset-file! repo path content (merge opts
-                                                                             (when (some? verbose) {:verbose verbose}))))
-                 (db/set-file-content! repo path content opts))]
-    (util/p-handle (write-file!)
-                   (fn [valid-result?]
-                     (when re-render-root? (ui-handler/re-render-root!))
-
-                     (cond
-                       (= path (config/get-custom-css-path repo))
-                       (ui-handler/add-style-if-exists!)
-
-                       (and (= path (config/get-repo-config-path repo))
-                            valid-result?)
-                       (p/let [_ (repo-config-handler/restore-repo-config! repo content)]
-                              (state/pub-event! [:shortcut/refresh]))
-
-                       (and (config/global-config-enabled?)
-                            (= path (global-config-handler/global-config-path))
-                            valid-result?)
-                       (p/let [_ (global-config-handler/restore-global-config!)]
-                              (state/pub-event! [:shortcut/refresh]))))
-                   (fn [error]
-                     (when (and (config/global-config-enabled?)
-                                ;; Global-config not started correctly but don't
-                                ;; know root cause yet
-                                ;; https://sentry.io/organizations/logseq/issues/3587411237/events/4b5da8b8e58b4f929bd9e43562213d32/events/?cursor=0%3A0%3A1&project=5311485&statsPeriod=14d
-                                (global-config-handler/global-config-dir-exists?)
-                                (= path (global-config-handler/global-config-path)))
-                       (state/pub-event! [:notification/show
-                                          {:content (str "Failed to write to file " path)
-                                           :status :error}]))
-
-                     (println "Write file failed, path: " path ", content: " content)
-                     (log/error :write/failed error)
-                     (state/pub-event! [:capture-error
-                                        {:error error
-                                         :payload {:type :write-file/failed-for-alter-file}}])))
-    result))
+        config-file? (string/ends-with? path config/config-file)
+        config-valid? (and config-file? (validate-file repo path content))]
+    (when-not (and config-file? (not config-valid?)) ; non-config file or valid config
+      (let [opts {:new-graph? new-graph?
+                  :from-disk? from-disk?
+                  :skip-db-transact? skip-db-transact?}
+            result (if reset?
+                     (do
+                       (when-not skip-db-transact?
+                         (when-let [page-id (db/get-file-page-id path)]
+                           (db/transact! repo
+                             [[:db/retract page-id :block/alias]
+                              [:db/retract page-id :block/tags]]
+                             opts)))
+                       (file-common-handler/reset-file!
+                        repo path content (merge opts
+                                                 (when (some? verbose) {:verbose verbose}))))
+                     (db/set-file-content! repo path content opts))]
+        (-> (p/let [_ (when-not from-disk?
+                        (write-file-aux! repo path content {:skip-compare? skip-compare?}))]
+              (when re-render-root? (ui-handler/re-render-root!))
+
+              (cond
+                (= path (config/get-custom-css-path repo))
+                (ui-handler/add-style-if-exists!)
+
+                (= path (config/get-repo-config-path repo))
+                (p/let [_ (repo-config-handler/restore-repo-config! repo content)]
+                  (state/pub-event! [:shortcut/refresh]))
+
+                (and (config/global-config-enabled?)
+                     (= path (global-config-handler/global-config-path)))
+                (p/let [_ (global-config-handler/restore-global-config!)]
+                  (state/pub-event! [:shortcut/refresh]))))
+            (p/catch
+                (fn [error]
+                  (when (and (config/global-config-enabled?)
+                             ;; Global-config not started correctly but don't
+                             ;; know root cause yet
+                             ;; https://sentry.io/organizations/logseq/issues/3587411237/events/4b5da8b8e58b4f929bd9e43562213d32/events/?cursor=0%3A0%3A1&project=5311485&statsPeriod=14d
+                             (global-config-handler/global-config-dir-exists?)
+                             (= path (global-config-handler/global-config-path)))
+                    (state/pub-event! [:notification/show
+                                       {:content (str "Failed to write to file " path)
+                                        :status :error}]))
+
+                  (println "Write file failed, path: " path ", content: " content)
+                  (log/error :write/failed error)
+                  (state/pub-event! [:capture-error
+                                     {:error error
+                                      :payload {:type :write-file/failed-for-alter-file}}]))))
+        result))))
 
 (defn set-file-content!
   [repo path new-content]

+ 4 - 3
src/main/frontend/state.cljs

@@ -324,12 +324,13 @@
   "Merges user configs in given orders. All values are overridden except for maps
   which are merged."
   [& configs]
-  (apply merge-with
+  (->> configs
+       (filter map?)
+       (apply merge-with
          (fn merge-config [current new]
            (if (and (map? current) (map? new))
              (merge current new)
-             new))
-         configs))
+             new)))))
 
 (defn get-config
   "User config for the given repo or current repo if none given. All config fetching