repo.cljs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. (ns frontend.handler.repo
  2. (:refer-clojure :exclude [clone])
  3. (:require [frontend.util :as util :refer-macros [profile]]
  4. [frontend.fs :as fs]
  5. [frontend.fs.nfs :as nfs]
  6. [promesa.core :as p]
  7. [lambdaisland.glogi :as log]
  8. [frontend.state :as state]
  9. [frontend.db :as db]
  10. [frontend.idb :as idb]
  11. [frontend.git :as git]
  12. [cljs-bean.core :as bean]
  13. [frontend.date :as date]
  14. [frontend.config :as config]
  15. [frontend.format :as format]
  16. [frontend.search :as search]
  17. [frontend.handler.ui :as ui-handler]
  18. [frontend.handler.git :as git-handler]
  19. [frontend.handler.file :as file-handler]
  20. [frontend.handler.notification :as notification]
  21. [frontend.handler.route :as route-handler]
  22. [frontend.handler.common :as common-handler]
  23. [frontend.handler.extract :as extract-handler]
  24. [frontend.ui :as ui]
  25. [clojure.string :as string]
  26. [frontend.dicts :as dicts]
  27. [frontend.spec :as spec]
  28. [goog.dom :as gdom]
  29. [goog.object :as gobj]))
  30. ;; Project settings should be checked in two situations:
  31. ;; 1. User changes the config.edn directly in logseq.com (fn: alter-file)
  32. ;; 2. Git pulls the new change (fn: load-files)
  33. (defn show-install-error!
  34. [repo-url title]
  35. (spec/validate :repos/url repo-url)
  36. (notification/show!
  37. [:p.content
  38. title
  39. " "
  40. [:span.mr-2
  41. (util/format
  42. "Please make sure that you've installed the logseq app for the repo %s on GitHub. "
  43. repo-url)
  44. (ui/button
  45. "Install Logseq on GitHub"
  46. :href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
  47. :error
  48. false))
  49. (defn create-config-file-if-not-exists
  50. [repo-url]
  51. (spec/validate :repos/url repo-url)
  52. (let [repo-dir (config/get-repo-dir repo-url)
  53. app-dir config/app-name
  54. dir (str repo-dir "/" app-dir)]
  55. (p/let [_ (fs/mkdir-if-not-exists dir)]
  56. (let [default-content config/config-default-content]
  57. (p/let [file-exists? (fs/create-if-not-exists repo-url repo-dir (str app-dir "/" config/config-file) default-content)]
  58. (let [path (str app-dir "/" config/config-file)
  59. old-content (when file-exists?
  60. (db/get-file repo-url path))
  61. content (or old-content default-content)]
  62. (file-handler/reset-file! repo-url path content)
  63. (common-handler/reset-config! repo-url content)
  64. (when-not (= content old-content)
  65. (git-handler/git-add repo-url path))))))))
  66. (defn create-contents-file
  67. [repo-url]
  68. (spec/validate :repos/url repo-url)
  69. (let [repo-dir (config/get-repo-dir repo-url)
  70. format (state/get-preferred-format)
  71. path (str (state/get-pages-directory)
  72. "/contents."
  73. (config/get-file-extension format))
  74. file-path (str "/" path)
  75. default-content (util/default-content-with-title format "contents")]
  76. (p/let [_ (fs/mkdir-if-not-exists (str repo-dir "/" (state/get-pages-directory)))
  77. file-exists? (fs/create-if-not-exists repo-url repo-dir file-path default-content)]
  78. (when-not file-exists?
  79. (file-handler/reset-file! repo-url path default-content)
  80. (git-handler/git-add repo-url path)))))
  81. (defn create-custom-theme
  82. [repo-url]
  83. (spec/validate :repos/url repo-url)
  84. (let [repo-dir (config/get-repo-dir repo-url)
  85. path (str config/app-name "/" config/custom-css-file)
  86. file-path (str "/" path)
  87. default-content ""]
  88. (p/let [_ (fs/mkdir-if-not-exists (str repo-dir "/" config/app-name))
  89. file-exists? (fs/create-if-not-exists repo-url repo-dir file-path default-content)]
  90. (when-not file-exists?
  91. (file-handler/reset-file! repo-url path default-content)
  92. (git-handler/git-add repo-url path)))))
  93. (defn create-dummy-notes-page
  94. [repo-url content]
  95. (spec/validate :repos/url repo-url)
  96. (let [repo-dir (config/get-repo-dir repo-url)
  97. path (str (config/get-pages-directory) "/how_to_make_dummy_notes.md")
  98. file-path (str "/" path)]
  99. (p/let [_ (fs/mkdir-if-not-exists (str repo-dir "/" (config/get-pages-directory)))
  100. _file-exists? (fs/create-if-not-exists repo-url repo-dir file-path content)]
  101. (file-handler/reset-file! repo-url path content))))
  102. (defn create-today-journal-if-not-exists
  103. ([repo-url]
  104. (create-today-journal-if-not-exists repo-url nil))
  105. ([repo-url content]
  106. (spec/validate :repos/url repo-url)
  107. (when (state/enable-journals? repo-url)
  108. (let [repo-dir (config/get-repo-dir repo-url)
  109. format (state/get-preferred-format repo-url)
  110. title (date/today)
  111. file-name (date/journal-title->default title)
  112. default-content (util/default-content-with-title format title false)
  113. template (state/get-journal-template)
  114. template (if (and template
  115. (not (string/blank? template)))
  116. template)
  117. content (cond
  118. content
  119. content
  120. template
  121. (str default-content template)
  122. :else
  123. (util/default-content-with-title format title true))
  124. path (str config/default-journals-directory "/" file-name "."
  125. (config/get-file-extension format))
  126. file-path (str "/" path)
  127. page-exists? (db/entity repo-url [:page/name (string/lower-case title)])
  128. empty-blocks? (empty? (db/get-page-blocks-no-cache repo-url (string/lower-case title)))]
  129. (when (or empty-blocks?
  130. (not page-exists?))
  131. (p/let [_ (nfs/check-directory-permission! repo-url)
  132. _ (fs/mkdir-if-not-exists (str repo-dir "/" config/default-journals-directory))
  133. file-exists? (fs/file-exists? repo-dir file-path)]
  134. (when-not file-exists?
  135. (file-handler/reset-file! repo-url path content)
  136. (p/let [_ (fs/create-if-not-exists repo-url repo-dir file-path content)]
  137. (ui-handler/re-render-root!)
  138. (git-handler/git-add repo-url path)))))))))
  139. (defn create-today-journal!
  140. []
  141. (state/set-today! (date/today))
  142. (when-let [repo (state/get-current-repo)]
  143. (when (or (db/cloned? repo)
  144. (and (config/local-db? repo)
  145. ;; config file exists
  146. (let [path (config/get-config-path)]
  147. (db/get-file path))))
  148. (let [today-page (string/lower-case (date/today))]
  149. (when (empty? (db/get-page-blocks-no-cache repo today-page))
  150. (create-today-journal-if-not-exists repo))))))
  151. (defn create-default-files!
  152. [repo-url]
  153. (spec/validate :repos/url repo-url)
  154. (create-config-file-if-not-exists repo-url)
  155. (create-today-journal-if-not-exists repo-url)
  156. (create-contents-file repo-url)
  157. (create-custom-theme repo-url))
  158. (defn- reset-contents-and-blocks!
  159. [repo-url files blocks-pages delete-files delete-blocks]
  160. (db/transact-files-db! repo-url files)
  161. (let [files (map #(select-keys % [:file/path :file/last-modified-at]) files)
  162. all-data (-> (concat delete-files delete-blocks files blocks-pages)
  163. (util/remove-nils))]
  164. (db/transact! repo-url all-data)))
  165. (defn parse-files-and-load-to-db!
  166. [repo-url files {:keys [first-clone? delete-files delete-blocks re-render? re-render-opts] :as opts
  167. :or {re-render? true}}]
  168. (state/set-loading-files! false)
  169. (state/set-importing-to-db! true)
  170. (let [file-paths (map :file/path files)
  171. parsed-files (filter
  172. (fn [file]
  173. (let [format (format/get-format (:file/path file))]
  174. (contains? config/mldoc-support-formats format)))
  175. files)
  176. blocks-pages (if (seq parsed-files)
  177. (extract-handler/extract-all-blocks-pages repo-url parsed-files)
  178. [])]
  179. (reset-contents-and-blocks! repo-url files blocks-pages delete-files delete-blocks)
  180. (let [config-file (config/get-config-path)]
  181. (if (contains? (set file-paths) config-file)
  182. (when-let [content (some #(when (= (:file/path %) config-file)
  183. (:file/content %)) files)]
  184. (file-handler/restore-config! repo-url content true))))
  185. (when first-clone? (create-default-files! repo-url))
  186. (when re-render?
  187. (ui-handler/re-render-root! re-render-opts))
  188. (state/set-importing-to-db! false)))
  189. (defn load-repo-to-db!
  190. [repo-url {:keys [first-clone? diffs nfs-files]
  191. :as opts}]
  192. (spec/validate :repos/url repo-url)
  193. (let [load-contents (fn [files option]
  194. (file-handler/load-files-contents!
  195. repo-url
  196. files
  197. (fn [files-contents]
  198. (parse-files-and-load-to-db! repo-url files-contents option))))]
  199. (cond
  200. (and (not (seq diffs)) nfs-files)
  201. (parse-files-and-load-to-db! repo-url nfs-files {:first-clone? true})
  202. (and first-clone? (not nfs-files))
  203. (->
  204. (p/let [files (file-handler/load-files repo-url)]
  205. (load-contents files {:first-clone? first-clone?}))
  206. (p/catch (fn [error]
  207. (println "loading files failed: ")
  208. (js/console.dir error)
  209. ;; Empty repo
  210. (create-default-files! repo-url)
  211. (state/set-loading-files! false))))
  212. :else
  213. (when (seq diffs)
  214. (let [filter-diffs (fn [type] (->> (filter (fn [f] (= type (:type f))) diffs)
  215. (map :path)))
  216. remove-files (filter-diffs "remove")
  217. modify-files (filter-diffs "modify")
  218. add-files (filter-diffs "add")
  219. delete-files (if (seq remove-files)
  220. (db/delete-files remove-files))
  221. delete-blocks (db/delete-blocks repo-url (concat remove-files modify-files))
  222. delete-pages (if (seq remove-files)
  223. (db/delete-pages-by-files remove-files)
  224. [])
  225. add-or-modify-files (some->>
  226. (concat modify-files add-files)
  227. (util/remove-nils))
  228. options {:first-clone? first-clone?
  229. :delete-files (concat delete-files delete-pages)
  230. :delete-blocks delete-blocks
  231. :re-render? true}]
  232. (if (seq nfs-files)
  233. (parse-files-and-load-to-db! repo-url nfs-files
  234. (assoc options :re-render-opts {:clear-all-query-state? true}))
  235. (load-contents add-or-modify-files options)))))))
  236. (defn load-db-and-journals!
  237. [repo-url diffs first-clone?]
  238. (spec/validate :repos/url repo-url)
  239. (when (or diffs first-clone?)
  240. (load-repo-to-db! repo-url {:first-clone? first-clone?
  241. :diffs diffs})))
  242. (defn rebuild-page-blocks-children
  243. "For performance reason, we can update the :block/children value after every operation,
  244. but it's hard to make sure that it's correct, also it needs more time to implement it.
  245. We can improve it if the performance is really an issue."
  246. [repo page]
  247. (let [blocks (->>
  248. (db/get-page-blocks-no-cache repo page {:pull-keys '[:db/id :block/uuid :block/level :block/pre-block? :block/meta]})
  249. (remove :block/pre-block?)
  250. (map #(select-keys % [:db/id :block/uuid :block/level]))
  251. (reverse))
  252. original-blocks blocks]
  253. (loop [blocks blocks
  254. tx []
  255. children {}
  256. last-level 10000]
  257. (if (seq blocks)
  258. (let [[{:block/keys [uuid level] :as block} & others] blocks
  259. [tx children] (cond
  260. (< level last-level) ; parent
  261. (let [cur-children (get children last-level)
  262. tx (if (seq cur-children)
  263. (vec
  264. (concat
  265. tx
  266. (map
  267. (fn [child]
  268. [:db/add (:db/id block) :block/children [:block/uuid child]])
  269. cur-children)))
  270. tx)
  271. children (-> children
  272. (dissoc last-level)
  273. (update level conj uuid))]
  274. [tx children])
  275. (> level last-level) ; child of sibling
  276. (let [children (update children level conj uuid)]
  277. [tx children])
  278. :else ; sibling
  279. (let [children (update children last-level conj uuid)]
  280. [tx children]))]
  281. (recur others tx children level))
  282. ;; TODO: add top-level children to the "Page" block (we might remove the Page from db schema)
  283. (when (seq tx)
  284. (let [delete-tx (map (fn [block]
  285. [:db/retract (:db/id block) :block/children])
  286. original-blocks)]
  287. (->> (concat delete-tx tx)
  288. (remove nil?))))))))
  289. (defn transact-react-and-alter-file!
  290. ([repo tx transact-option files]
  291. (transact-react-and-alter-file! repo tx transact-option files {}))
  292. ([repo tx transact-option files opts]
  293. (spec/validate :repos/url repo)
  294. (let [files (remove nil? files)
  295. pages (->> (map db/get-file-page (map first files))
  296. (remove nil?))]
  297. (let [edit-block (state/get-edit-block)
  298. edit-input-id (state/get-edit-input-id)
  299. block-element (when edit-input-id (gdom/getElement (string/replace edit-input-id "edit-block" "ls-block")))
  300. {:keys [idx container]} (when block-element
  301. (util/get-block-idx-inside-container block-element))]
  302. (when (and idx container)
  303. (state/set-state! :editor/last-edit-block {:block edit-block
  304. :idx idx
  305. :container (gobj/get container "id")})))
  306. (when (seq files)
  307. (file-handler/alter-files repo files opts))
  308. (db/transact-react!
  309. repo
  310. tx
  311. transact-option)
  312. (when (seq pages)
  313. (let [children-tx (mapcat #(rebuild-page-blocks-children repo %) pages)]
  314. (when (seq children-tx)
  315. (db/transact! repo children-tx)))))))
  316. (declare push)
  317. (defn get-diff-result
  318. [repo-url]
  319. (p/let [remote-latest-commit (common-handler/get-remote-ref repo-url)
  320. local-latest-commit (common-handler/get-ref repo-url)]
  321. (git/get-diffs repo-url local-latest-commit remote-latest-commit)))
  322. (defn pull
  323. [repo-url {:keys [force-pull? show-diff? try-times]
  324. :or {force-pull? false
  325. show-diff? false
  326. try-times 2}
  327. :as opts}]
  328. (spec/validate :repos/url repo-url)
  329. (when (and
  330. (db/get-conn repo-url true)
  331. (db/cloned? repo-url))
  332. (p/let [remote-latest-commit (common-handler/get-remote-ref repo-url)
  333. local-latest-commit (common-handler/get-ref repo-url)
  334. descendent? (git/descendent? repo-url local-latest-commit remote-latest-commit)]
  335. (when (or (= local-latest-commit remote-latest-commit)
  336. (nil? local-latest-commit)
  337. (not descendent?)
  338. force-pull?)
  339. (p/let [files (js/window.workerThread.getChangedFiles (config/get-repo-dir repo-url))]
  340. (when (empty? files)
  341. (let [status (db/get-key-value repo-url :git/status)]
  342. (when (or
  343. force-pull?
  344. (and
  345. (not= status :pushing)
  346. (not (state/get-edit-input-id))
  347. (not (state/in-draw-mode?))
  348. ;; don't pull if git conflicts not resolved yet
  349. (or
  350. show-diff?
  351. (and (not show-diff?)
  352. (empty? @state/diffs)))))
  353. (git-handler/set-git-status! repo-url :pulling)
  354. (->
  355. (p/let [token (common-handler/get-github-token repo-url)
  356. result (git/fetch repo-url token)]
  357. (let [{:keys [fetchHead]} (bean/->clj result)]
  358. (-> (git/merge repo-url)
  359. (p/then (fn [result]
  360. (-> (git/checkout repo-url)
  361. (p/then (fn [result]
  362. (git-handler/set-git-status! repo-url nil)
  363. (git-handler/set-git-last-pulled-at! repo-url)
  364. (when (and local-latest-commit fetchHead
  365. (not= local-latest-commit fetchHead))
  366. (p/let [diffs (git/get-diffs repo-url local-latest-commit fetchHead)]
  367. (when (seq diffs)
  368. (load-db-and-journals! repo-url diffs false))))
  369. (common-handler/check-changed-files-status repo-url)))
  370. (p/catch (fn [error]
  371. (git-handler/set-git-status! repo-url :checkout-failed)
  372. (git-handler/set-git-error! repo-url error)
  373. (when force-pull?
  374. (notification/show!
  375. (str "Failed to checkout: " error)
  376. :error
  377. false)))))))
  378. (p/catch (fn [error]
  379. (println "Git pull error:")
  380. (js/console.error error)
  381. (git-handler/set-git-status! repo-url :merge-failed)
  382. (git-handler/set-git-error! repo-url error)
  383. (p/let [result (get-diff-result repo-url)]
  384. (if (seq result)
  385. (do
  386. (notification/show!
  387. [:p.content
  388. "Failed to merge, please "
  389. [:span.font-bold
  390. "resolve any diffs first."]]
  391. :error)
  392. (route-handler/redirect! {:to :diff}))
  393. (push repo-url {:merge-push-no-diff? true
  394. :custom-commit? force-pull?
  395. :commit-message "Merge push without diffed files"}))))))))
  396. (p/catch
  397. (fn [error]
  398. (cond
  399. (string/includes? (str error) "404")
  400. (do (log/error :git/pull-error error)
  401. (show-install-error! repo-url (util/format "Failed to fetch %s." repo-url)))
  402. (string/includes? (str error) "401")
  403. (let [remain-times (dec try-times)]
  404. (if (> remain-times 0)
  405. (let [new-opts (merge opts {:try-times remain-times})]
  406. (pull repo-url new-opts))
  407. (let [error-msg
  408. (util/format "Failed to fetch %s. It may be caused by token expiration or missing." repo-url)]
  409. (git-handler/set-git-status! repo-url :fetch-failed)
  410. (log/error :repo/pull-error error)
  411. (notification/show! error-msg :error false))))
  412. :else
  413. (log/error :git/pull-error error)))))))))))))
  414. (defn push
  415. [repo-url {:keys [commit-message merge-push-no-diff? custom-commit?]
  416. :or {custom-commit? false
  417. merge-push-no-diff? false}}]
  418. (spec/validate :repos/url repo-url)
  419. (let [status (db/get-key-value repo-url :git/status)
  420. commit-message (if (string/blank? commit-message)
  421. "Logseq auto save"
  422. commit-message)]
  423. (when (and
  424. (db/cloned? repo-url)
  425. (state/input-idle? repo-url)
  426. (or (not= status :pushing)
  427. custom-commit?))
  428. (->
  429. (p/let [files (git/add-all repo-url)
  430. changed-files? (some? (seq files))
  431. should-commit? (or changed-files? merge-push-no-diff?)
  432. _commit (when should-commit?
  433. (git/commit repo-url commit-message))
  434. token (common-handler/get-github-token repo-url)
  435. status (db/get-key-value repo-url :git/status)]
  436. (when (and token
  437. (or custom-commit?
  438. (and (not= status :pushing)
  439. changed-files?)))
  440. (git-handler/set-git-status! repo-url :pushing)
  441. (util/p-handle
  442. (git/push repo-url token merge-push-no-diff?)
  443. (fn [_result]
  444. (git-handler/set-git-status! repo-url nil)
  445. (git-handler/set-git-error! repo-url nil)
  446. (common-handler/check-changed-files-status repo-url))
  447. (fn [error]
  448. (log/error :git/push-error error)
  449. (js/console.error error)
  450. (common-handler/check-changed-files-status repo-url)
  451. (git-handler/set-git-status! repo-url :push-failed)
  452. (git-handler/set-git-error! repo-url error)
  453. (if (state/online?)
  454. (pull repo-url {:force-pull? true
  455. :show-diff? true})
  456. (when custom-commit?
  457. (p/rejected error)))))))
  458. (p/catch (fn [error]
  459. (log/error :repo/push-error error)
  460. (git-handler/set-git-status! repo-url :push-failed)
  461. (git-handler/set-git-error! repo-url error)
  462. (when custom-commit?
  463. (p/rejected error))))))))
  464. (defn push-if-auto-enabled!
  465. [repo]
  466. (spec/validate :repos/url repo)
  467. (when (state/get-git-auto-push? repo)
  468. (push repo nil)))
  469. (defn pull-current-repo
  470. []
  471. (when-let [repo (state/get-current-repo)]
  472. (-> (pull repo {:force-pull? true})
  473. (p/catch (fn [error]
  474. (notification/show! error :error false))))))
  475. (defn- clone
  476. [repo-url]
  477. (spec/validate :repos/url repo-url)
  478. (p/let [token (common-handler/get-github-token repo-url)]
  479. (when token
  480. (util/p-handle
  481. (do
  482. (state/set-cloning! true)
  483. (git/clone repo-url token))
  484. (fn [result]
  485. (state/set-current-repo! repo-url)
  486. (db/start-db-conn! (state/get-me) repo-url)
  487. (db/mark-repo-as-cloned! repo-url))
  488. (fn [e]
  489. (println "Clone failed, error: ")
  490. (js/console.error e)
  491. (state/set-cloning! false)
  492. (git-handler/set-git-status! repo-url :clone-failed)
  493. (git-handler/set-git-error! repo-url e)
  494. (show-install-error! repo-url (util/format "Failed to clone %s." repo-url)))))))
  495. (defn set-config-content!
  496. [repo path new-content]
  497. (file-handler/alter-file repo path new-content {:reset? false
  498. :re-render-root? false}))
  499. (defn remove-repo!
  500. [{:keys [id url] :as repo}]
  501. (spec/validate :repos/repo repo)
  502. (let [delete-db-f (fn []
  503. (db/remove-conn! url)
  504. (db/remove-db! url)
  505. (db/remove-files-db! url)
  506. (fs/rmdir! (config/get-repo-dir url))
  507. (state/delete-repo! repo))]
  508. (if (config/local-db? url)
  509. (p/let [_ (idb/clear-local-db! url)] ; clear file handles
  510. (delete-db-f))
  511. (util/delete (str config/api "repos/" id)
  512. delete-db-f
  513. (fn [error]
  514. (prn "Delete repo failed, error: " error))))))
  515. (defn start-repo-db-if-not-exists!
  516. [repo option]
  517. (state/set-current-repo! repo)
  518. (db/start-db-conn! nil repo option))
  519. (defn setup-local-repo-if-not-exists!
  520. []
  521. (if js/window.pfs
  522. (let [repo config/local-repo]
  523. (p/do! (fs/mkdir-if-not-exists (str "/" repo))
  524. (state/set-current-repo! repo)
  525. (db/start-db-conn! nil repo)
  526. (when-not config/publishing?
  527. (let [dummy-notes (get-in dicts/dicts [:en :tutorial/dummy-notes])]
  528. (create-dummy-notes-page repo dummy-notes)))
  529. (when-not config/publishing?
  530. (let [tutorial (get-in dicts/dicts [:en :tutorial/text])
  531. tutorial (string/replace-first tutorial "$today" (date/today))]
  532. (create-today-journal-if-not-exists repo tutorial)))
  533. (create-config-file-if-not-exists repo)
  534. (create-contents-file repo)
  535. (create-custom-theme repo)
  536. (state/set-db-restoring! false)))
  537. (js/setTimeout setup-local-repo-if-not-exists! 100)))
  538. (defn periodically-pull-current-repo
  539. []
  540. (js/setInterval
  541. (fn []
  542. (p/let [repo-url (state/get-current-repo)
  543. token (common-handler/get-github-token repo-url)]
  544. (when token
  545. (pull repo-url nil))))
  546. (* (config/git-pull-secs) 1000)))
  547. (defn periodically-push-current-repo
  548. []
  549. (js/setInterval #(push-if-auto-enabled! (state/get-current-repo))
  550. (* (config/git-push-secs) 1000)))
  551. (defn create-repo!
  552. [repo-url branch]
  553. (spec/validate :repos/url repo-url)
  554. (util/post (str config/api "repos")
  555. {:url repo-url
  556. :branch branch}
  557. (fn [result]
  558. (if (:installation_id result)
  559. (set! (.-href js/window.location) config/website)
  560. (set! (.-href js/window.location) (str "https://github.com/apps/" config/github-app-name "/installations/new"))))
  561. (fn [error]
  562. (println "Something wrong!")
  563. (js/console.dir error))))
  564. (defn- clone-and-load-db
  565. [repo-url]
  566. (spec/validate :repos/url repo-url)
  567. (->
  568. (p/let [_ (clone repo-url)
  569. _ (git-handler/git-set-username-email! repo-url (state/get-me))]
  570. (load-db-and-journals! repo-url nil true))
  571. (p/catch (fn [error]
  572. (js/console.error error)))))
  573. (defn clone-and-pull-repos
  574. [me]
  575. (spec/validate :state/me me)
  576. (if (and js/window.git js/window.pfs)
  577. (do
  578. (doseq [{:keys [id url]} (:repos me)]
  579. (let [repo url]
  580. (if (db/cloned? repo)
  581. (p/do!
  582. (git-handler/git-set-username-email! repo me)
  583. (pull repo nil))
  584. (p/do!
  585. (clone-and-load-db repo)))))
  586. (periodically-pull-current-repo)
  587. (periodically-push-current-repo))
  588. (js/setTimeout (fn []
  589. (clone-and-pull-repos me))
  590. 500)))
  591. (defn rebuild-index!
  592. [url]
  593. (when url
  594. (search/reset-indice! url)
  595. (db/remove-conn! url)
  596. (db/clear-query-state!)
  597. (-> (p/do! (db/remove-db! url)
  598. (db/remove-files-db! url)
  599. (fs/rmdir! (config/get-repo-dir url))
  600. (clone-and-load-db url))
  601. (p/catch (fn [error]
  602. (prn "Delete repo failed, error: " error))))))
  603. (defn git-commit-and-push!
  604. [commit-message]
  605. (when-let [repo (state/get-current-repo)]
  606. (push repo {:commit-message commit-message
  607. :custom-commit? true})))
  608. (defn get-repo-name
  609. [url]
  610. (last (string/split url #"/")))
  611. (defn auto-push!
  612. []
  613. (git-commit-and-push! "Logseq auto save"))