db_and_file_graphs.clj 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. (ns logseq.tasks.dev.db-and-file-graphs
  2. (:require [babashka.process :refer [shell]]
  3. [clojure.set :as set]
  4. [clojure.string :as string]))
  5. (defn- escape-shell-regex
  6. [s]
  7. (reduce (fn [acc escape-char]
  8. (string/replace acc escape-char (str "\\" escape-char)))
  9. s
  10. ["." "?"]))
  11. (def db-graph-ns
  12. "Namespaces or parent namespaces _only_ for DB graphs. Use a '.' at end of a namespace for parent namespaces"
  13. (mapv escape-shell-regex
  14. ["logseq.db.sqlite." "logseq.db.frontend."
  15. "electron.db"
  16. "frontend.handler.db-based."
  17. "frontend.worker.handler.page.db-based"
  18. "frontend.components.property" "frontend.components.class"
  19. "frontend.components.db-based" "frontend.components.objects" "frontend.components.query.view"]))
  20. (def file-graph-ns
  21. "Namespaces or parent namespaces _only_ for file graphs"
  22. (mapv escape-shell-regex
  23. ["frontend.handler.file-based" "frontend.handler.file-sync"
  24. "frontend.db.file-based"
  25. "frontend.util.file-based"
  26. "frontend.common.file-based"
  27. "frontend.worker.handler.page.file-based"
  28. ;; Want to only specify this ns and not the ones under it but don't have a way yet
  29. "frontend.worker.file"
  30. "frontend.fs"
  31. "frontend.components.file-sync"
  32. "frontend.components.file-based"
  33. "frontend.util.fs"]))
  34. (def block-name-db-graph-paths
  35. "DB graph paths with :block/name"
  36. ["deps/db/src/logseq/db/frontend"
  37. "deps/db/src/logseq/db/sqlite"
  38. "src/main/frontend/worker/handler/page/db_based"])
  39. (def db-graph-paths
  40. "Paths _only_ for DB graphs"
  41. (into block-name-db-graph-paths
  42. ["src/main/frontend/handler/db_based"
  43. "src/main/frontend/components/class.cljs"
  44. "src/main/frontend/components/property.cljs"
  45. "src/main/frontend/components/property"
  46. "src/main/frontend/components/objects.cljs"
  47. "src/main/frontend/components/db_based"
  48. "src/main/frontend/components/query/view.cljs"
  49. "src/electron/electron/db.cljs"]))
  50. (def file-graph-paths
  51. "Paths _only_ for file graphs"
  52. ["src/main/frontend/handler/file_based" "src/main/frontend/handler/file_sync.cljs" "src/main/frontend/db/file_based"
  53. "src/main/frontend/util/file_based" "src/main/frontend/worker/handler/page/file_based" "src/main/frontend/worker/file.cljs"
  54. "src/main/frontend/common/file_based"
  55. "src/main/frontend/fs"
  56. "src/main/frontend/components/file_sync.cljs"
  57. "src/main/frontend/components/file_based"
  58. "src/main/frontend/util/fs.cljs"])
  59. (defn- grep-many
  60. "Git greps a coll of patterns for given paths. Returns result from process/shell"
  61. [patterns paths]
  62. (apply shell {:out :string :continue true}
  63. "git grep -E" (str "(" (string/join "|" patterns) ")")
  64. paths))
  65. (defn- validate-db-ns-not-in-file
  66. []
  67. (let [res (grep-many db-graph-ns file-graph-paths)]
  68. (when-not (and (= 1 (:exit res)) (= "" (:out res)))
  69. (println "The following db graph namespaces should not be in file graph files:")
  70. (println (:out res))
  71. (System/exit 1))))
  72. (defn- validate-file-ns-not-in-db
  73. []
  74. (let [res (grep-many file-graph-ns db-graph-paths)]
  75. (when-not (and (= 1 (:exit res)) (= "" (:out res)))
  76. (println "The following file graph namespaces should not be in db graph files:")
  77. (println (:out res))
  78. (System/exit 1))))
  79. (defn- validate-multi-graph-fns-not-in-file-or-db
  80. []
  81. ;; TODO: Lint `(db-based-graph?` when db.frontend.entity-plus is split into separate graph contexts
  82. (let [multi-graph-fns ["/db-based-graph\\?"
  83. ;; Use file-entity-util and entity-util when in a single graph context
  84. "ldb/whiteboard\\?" "ldb/journal\\?" "ldb/page\\?"]
  85. res (grep-many multi-graph-fns (into file-graph-paths db-graph-paths))]
  86. (when-not (and (= 1 (:exit res)) (= "" (:out res)))
  87. (println "The following files should not have fns meant to be used in multi-graph contexts:")
  88. (println (:out res))
  89. (System/exit 1))))
  90. (defn- validate-file-concepts-not-in-db
  91. []
  92. (let [file-concepts (->>
  93. ;; from logseq.db.file-based.schema
  94. [:block/namespace :block/properties-text-values :block/pre-block :recent/pages :block/file :block/properties-order
  95. :block/repeated :block/deadline :block/scheduled :block/priority :block/marker :block/macros
  96. :block/type :block/format]
  97. (map str)
  98. (into [;; e.g. block/properties :title
  99. "block/properties :"
  100. ;; anything org mode except for org.babashka
  101. "org[^\\.]"
  102. "#+BEGIN_"
  103. "#+END_"
  104. "pre-block"]))
  105. ;; For now use the whole code line. If this is too brittle can make this smaller
  106. allowed-exceptions #{":block/pre-block? :block/scheduled :block/deadline :block/type :block/name :block/marker"
  107. "(dissoc :block/format))]"
  108. ;; The next 3 are from components.property.value
  109. "{:block/name page-title})"
  110. "(when-not (db/get-page journal)"
  111. "(let [value (if datetime? (tc/to-long d) (db/get-page journal))]"}
  112. res (grep-many file-concepts db-graph-paths)
  113. invalid-lines (when (= 0 (:exit res))
  114. (remove #(some->> (string/split % #":\s+") second string/trim (contains? allowed-exceptions))
  115. (string/split-lines (:out res))))
  116. _ (when (> (:exit res) 1) (System/exit 1))
  117. _ (when (and (= 0 (:exit res)) (seq invalid-lines))
  118. (println "The following files should not have contained file specific concepts:")
  119. (println (string/join "\n" invalid-lines))
  120. (System/exit 1))
  121. ;; :block/name isn't used in db graphs except for fns with journal or internal-page
  122. block-name-file-concepts #{"block/name" "/page-name-sanity-lc" "db/get-page"}
  123. no-block-name-db-graph-paths (set/difference (set db-graph-paths) (set block-name-db-graph-paths))
  124. block-name-res (grep-many block-name-file-concepts no-block-name-db-graph-paths)
  125. block-name-invalid-lines (when (= 0 (:exit block-name-res))
  126. (remove #(some->> (string/split % #":\s+") second string/trim (contains? allowed-exceptions))
  127. (string/split-lines (:out block-name-res))))]
  128. (when (> (:exit block-name-res) 1) (System/exit 1))
  129. (when (and (= 0 (:exit block-name-res)) (seq block-name-invalid-lines))
  130. (println "The following files should not have contained file specific concepts:")
  131. (println (string/join "\n" block-name-invalid-lines))
  132. (System/exit 1))))
  133. (defn- validate-db-concepts-not-in-file
  134. []
  135. (let [db-concepts
  136. ;; from logseq.db.frontend.schema
  137. ["closed-value" "class/properties" "classes" "property/parent"
  138. "logseq.property" "logseq.class"]
  139. res (grep-many db-concepts file-graph-paths)]
  140. (when-not (and (= 1 (:exit res)) (= "" (:out res)))
  141. (println "The following files should not have contained db specific concepts:")
  142. (println (:out res))
  143. (System/exit 1))))
  144. (defn -main
  145. "Check that file and db graph specific namespaces and concepts are separate"
  146. []
  147. (validate-db-ns-not-in-file)
  148. (validate-file-ns-not-in-db)
  149. (validate-file-concepts-not-in-db)
  150. (validate-db-concepts-not-in-file)
  151. (validate-multi-graph-fns-not-in-file-or-db)
  152. (println "✅ All checks passed!"))