Merge pull request #216 from logseq/refactor/sync

Simplify git state
pull/645/head
Tienson Qin 2020-11-11 02:35:18 -06:00 committed by GitHub
commit 55a75ae332
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 175 additions and 189 deletions

View File

@ -5,6 +5,7 @@
[frontend.handler.git :as git-handler]
[frontend.handler.file :as file]
[frontend.handler.notification :as notification]
[frontend.handler.common :as common-handler]
[frontend.state :as state]
[clojure.string :as string]
[frontend.db :as db]
@ -138,38 +139,34 @@
{:will-mount
(fn [state]
(when-let [repo (state/get-current-repo)]
(git-handler/get-latest-commit
repo
(fn [commit]
(let [local-oid (gobj/get commit "oid")
remote-oid (db/get-key-value repo
:git/remote-latest-commit)]
(p/let [result (git/get-local-diffs repo local-oid remote-oid)]
(reset! diffs result)
(reset! remote-hash-id remote-oid)
(doseq [{:keys [type path]} result]
(when (contains? #{"added" "modify"}
type)
(github/get-content
(state/get-github-token repo)
repo
path
remote-oid
(fn [{:keys [repo-url path ref content]}]
(swap! state/state
assoc-in [:github/contents repo-url remote-oid path] content))
(fn [response]
(when (= (gobj/get response "status") 401)
(notification/show!
[:span.text-gray-700.mr-2
(util/format
"Please make sure that you've installed the logseq app for the repo %s on GitHub. "
repo)
(ui/button
"Install Logseq on GitHub"
:href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]
:error
false)))))))))))
(p/let [remote-latest-commit (common-handler/get-remote-ref repo)
local-latest-commit (common-handler/get-ref repo)
result (git/get-local-diffs repo local-latest-commit remote-latest-commit)]
(reset! diffs result)
(reset! remote-hash-id remote-latest-commit)
(doseq [{:keys [type path]} result]
(when (contains? #{"added" "modify"}
type)
(github/get-content
(state/get-github-token repo)
repo
path
remote-latest-commit
(fn [{:keys [repo-url path ref content]}]
(swap! state/state
assoc-in [:github/contents repo-url remote-latest-commit path] content))
(fn [response]
(when (= (gobj/get response "status") 401)
(notification/show!
[:span.text-gray-700.mr-2
(util/format
"Please make sure that you've installed the logseq app for the repo %s on GitHub. "
repo)
(ui/button
"Install Logseq on GitHub"
:href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]
:error
false))))))))
state)
:will-unmount
(fn [state]
@ -206,13 +203,13 @@
(if pushing?
[:span (ui/loading "Pushing")]
(ui/button "Commit and push"
:on-click
(fn []
(let [commit-message (if (string/blank? @commit-message)
"Merge"
@commit-message)]
(reset! *pushing? true)
(git-handler/commit-and-force-push! commit-message *pushing?)))))]]
:on-click
(fn []
(let [commit-message (if (string/blank? @commit-message)
"Merge"
@commit-message)]
(reset! *pushing? true)
(git-handler/commit-and-force-push! commit-message *pushing?)))))]]
:else
[:div "No diffs"])]))

View File

@ -2499,6 +2499,5 @@
:repo repo
:git/cloned? (cloned? repo)
:git/status (get-key-value repo :git/status)
:git/latest-commit (get-key-value repo :git/latest-commit)
:git/error (get-key-value repo :git/error)})
repos))))

View File

@ -24,10 +24,6 @@
;; Git
:repo/url {:db/unique :db.unique/identity}
:repo/cloned? {}
;; local
:git/latest-commit {}
;; remote
:git/remote-latest-commit {}
:git/status {}
:git/last-pulled-at {}
;; last error, better we should record all the errors

View File

@ -4,21 +4,55 @@
[cljs-bean.core :as bean]
[promesa.core :as p]
[frontend.util :as util]
[frontend.text :as text]))
[frontend.text :as text]
[frontend.git :as git]
[frontend.db :as db]))
(defn get-ref
[repo-url]
(git/resolve-ref repo-url "HEAD"))
(defn get-remote-ref
[repo-url]
(let [branch (state/get-repo-branch repo-url)]
;; TODO: what if the remote is not named "origin", check the api from isomorphic-git
(git/resolve-ref repo-url (str "refs/remotes/origin/" branch))))
;; Should include un-pushed committed files too
(defn check-changed-files-status
[]
(when-let [repo (state/get-current-repo)]
(when (and
(gobj/get js/window "workerThread")
(gobj/get js/window.workerThread "getChangedFiles"))
(->
(p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo))]
(let [files (bean/->clj files)]
(state/set-changed-files! repo files)))
(p/catch (fn [error]
(js/console.dir error)))))))
([]
(check-changed-files-status (state/get-current-repo)))
([repo]
(when (and
repo
(gobj/get js/window "workerThread")
(gobj/get js/window.workerThread "getChangedFiles"))
(->
(p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo))]
(let [files (bean/->clj files)]
(p/let [remote-latest-commit (get-remote-ref repo)
local-latest-commit (get-ref repo)
descendent? (git/descendent? repo local-latest-commit remote-latest-commit)
diffs (git/get-diffs repo local-latest-commit remote-latest-commit)]
(let [files (if descendent?
(->> (concat (map :path diffs) files)
distinct)
files)]
(state/set-changed-files! repo files)))))
(p/catch (fn [error]
(js/console.dir error)))))))
(defn copy-to-clipboard-without-id-property!
[content]
(util/copy-to-clipboard! (text/remove-id-property content)))
(comment
(let [repo (state/get-current-repo)]
(p/let [remote-oid (get-remote-ref repo)
local-oid (get-ref repo)
diffs (git/get-diffs repo local-oid remote-oid)]
(println {:local-oid local-oid
:remote-oid remote-oid
:diffs diffs})))
)

View File

@ -12,14 +12,6 @@
[frontend.handler.common :as common-handler]
[cljs-time.local :as tl]))
(defn- set-latest-commit!
[repo-url hash]
(db/set-key-value repo-url :git/latest-commit hash))
(defn- set-remote-latest-commit!
[repo-url hash]
(db/set-key-value repo-url :git/remote-latest-commit hash))
(defn- set-git-status!
[repo-url value]
(db/set-key-value repo-url :git/status value)
@ -44,47 +36,19 @@
(p/catch (fn [error]
(println "git add '" file "' failed: " error)
(js/console.error error))))))
(defn get-latest-commit
([repo-url handler]
(get-latest-commit repo-url handler 1))
([repo-url handler length]
(-> (p/let [commits (git/log repo-url length)]
(handler (if (= length 1)
(first commits)
commits)))
(p/catch (fn [error]
(println "get latest commit failed: " error)
(js/console.log (.-stack error))
;; TODO: safe check
(println "It might be an empty repo"))))))
(defn set-latest-commit-if-exists! [repo-url]
(get-latest-commit
repo-url
(fn [commit]
(when-let [hash (gobj/get commit "oid")]
(set-latest-commit! repo-url hash)))))
(defn set-remote-latest-commit-if-exists! [repo-url]
(get-latest-commit
repo-url
(fn [commit]
(when-let [hash (gobj/get commit "oid")]
(set-remote-latest-commit! repo-url hash)))))
(defn commit-and-force-push!
[commit-message pushing?]
(when-let [repo (frontend.state/get-current-repo)]
(let [remote-oid (db/get-key-value repo
:git/remote-latest-commit)]
(p/let [commit-oid (git/commit repo commit-message (array remote-oid))
result (git/write-ref! repo commit-oid)
push-result (git/push repo
(state/get-github-token repo)
true)]
(reset! pushing? false)
(notification/clear! nil)
(route-handler/redirect! {:to :home})))))
(p/let [remote-oid (common-handler/get-remote-ref repo)
commit-oid (git/commit repo commit-message (array remote-oid))
result (git/write-ref! repo commit-oid)
push-result (git/push repo
(state/get-github-token repo)
true)]
(reset! pushing? false)
(notification/clear! nil)
(route-handler/redirect! {:to :home}))))
(defn git-set-username-email!
[repo-url {:keys [name email]}]

View File

@ -303,90 +303,81 @@
(db/get-conn repo-url true)
(db/cloned? repo-url)
token)
(let [remote-latest-commit (db/get-key-value repo-url :git/remote-latest-commit)
local-latest-commit (db/get-key-value repo-url :git/latest-commit)]
(p/let [descendent? (git/descendent? repo-url local-latest-commit remote-latest-commit)]
(when (or (= local-latest-commit remote-latest-commit)
(nil? local-latest-commit)
(not descendent?)
force-pull?)
(p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo-url))]
(when (empty? files)
(let [status (db/get-key-value repo-url :git/status)]
(when (or
force-pull?
(and
;; (not= status :push-failed)
(not= status :pushing)
(not (state/get-edit-input-id))
(not (state/in-draw-mode?))))
(git-handler/set-git-status! repo-url :pulling)
(let [latest-commit (db/get-key-value repo-url :git/latest-commit)]
(->
(p/let [result (git/fetch repo-url token)]
(let [{:keys [fetchHead]} (bean/->clj result)]
(when fetchHead
(git-handler/set-remote-latest-commit! repo-url fetchHead))
(-> (git/merge repo-url)
(p/then (fn [result]
(-> (git/checkout repo-url)
(p/then (fn [result]
(git-handler/set-git-status! repo-url nil)
(git-handler/set-git-last-pulled-at! repo-url)
(when (and latest-commit fetchHead
(not= latest-commit fetchHead))
(p/let [diffs (git/get-diffs repo-url latest-commit fetchHead)]
(when (seq diffs)
(load-db-and-journals! repo-url diffs false)
(git-handler/set-latest-commit! repo-url fetchHead))))))
(p/catch (fn [error]
(git-handler/set-git-status! repo-url :checkout-failed)
(git-handler/set-git-error! repo-url error))))
(state/set-changed-files! repo-url nil)))
(p/catch (fn [error]
(println "Git pull error:")
(js/console.error error)
(git-handler/set-git-status! repo-url :merge-failed)
(git-handler/set-git-error! repo-url error)
(git-handler/get-latest-commit
repo-url
(fn [commit]
(let [local-oid (gobj/get commit "oid")
remote-oid (db/get-key-value repo-url
:git/remote-latest-commit)]
(p/let [result (git/get-local-diffs repo-url local-oid remote-oid)]
(if (seq result)
(do
(notification/show!
[:p.content
"Failed to merge, please "
[:span.text-gray-700.font-bold
"resolve any diffs first."]]
:error)
(route-handler/redirect! {:to :diff}))
(push repo-url {:commit-push? true
:force? true
:commit-message "Merge push without diffed files"})))))))))))
(p/catch (fn [error]
(println "Pull error:" (str error))
(js/console.error error)
;; token might be expired, request new token
(p/let [remote-latest-commit (common-handler/get-remote-ref repo-url)
local-latest-commit (common-handler/get-ref repo-url)
descendent? (git/descendent? repo-url local-latest-commit remote-latest-commit)]
(when (or (= local-latest-commit remote-latest-commit)
(nil? local-latest-commit)
(not descendent?)
force-pull?)
(p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo-url))]
(when (empty? files)
(let [status (db/get-key-value repo-url :git/status)]
(when (or
force-pull?
(and
(not= status :pushing)
(not (state/get-edit-input-id))
(not (state/in-draw-mode?))))
(git-handler/set-git-status! repo-url :pulling)
(->
(p/let [result (git/fetch repo-url token)]
(let [{:keys [fetchHead]} (bean/->clj result)]
(-> (git/merge repo-url)
(p/then (fn [result]
(-> (git/checkout repo-url)
(p/then (fn [result]
(git-handler/set-git-status! repo-url nil)
(git-handler/set-git-last-pulled-at! repo-url)
(when (and local-latest-commit fetchHead
(not= local-latest-commit fetchHead))
(p/let [diffs (git/get-diffs repo-url local-latest-commit fetchHead)]
(when (seq diffs)
(load-db-and-journals! repo-url diffs false))))
(common-handler/check-changed-files-status repo-url)))
(p/catch (fn [error]
(git-handler/set-git-status! repo-url :checkout-failed)
(git-handler/set-git-error! repo-url error))))))
(p/catch (fn [error]
(println "Git pull error:")
(js/console.error error)
(git-handler/set-git-status! repo-url :merge-failed)
(git-handler/set-git-error! repo-url error)
(p/let [remote-latest-commit (common-handler/get-remote-ref repo-url)
local-latest-commit (common-handler/get-ref repo-url)
result (git/get-local-diffs repo-url local-latest-commit remote-latest-commit)]
(if (seq result)
(do
(notification/show!
[:p.content
"Failed to merge, please "
[:span.text-gray-700.font-bold
"resolve any diffs first."]]
:error)
(route-handler/redirect! {:to :diff}))
(push repo-url {:commit-push? true
:force? true
:commit-message "Merge push without diffed files"}))))))))
(p/catch (fn [error]
(println "Pull error:" (str error))
(js/console.error error)
;; token might be expired, request new token
(cond
(and (or (string/includes? (str error) "401")
(string/includes? (str error) "404"))
(not fallback?))
(request-app-tokens!
(fn []
(pull repo-url (state/get-github-token repo-url) {:fallback? true}))
nil)
(cond
(and (or (string/includes? (str error) "401")
(string/includes? (str error) "404"))
(not fallback?))
(request-app-tokens!
(fn []
(pull repo-url (state/get-github-token repo-url) {:fallback? true}))
nil)
(or (string/includes? (str error) "401")
(string/includes? (str error) "404"))
(show-install-error! repo-url (util/format "Failed to fetch %s." repo-url))
(or (string/includes? (str error) "401")
(string/includes? (str error) "404"))
(show-install-error! repo-url (util/format "Failed to fetch %s." repo-url))
:else
nil))))))))))))))
:else
nil))))))))))))
(defn push
[repo-url {:keys [commit-message fallback? diff-push? commit-push? force?]
@ -410,7 +401,6 @@
"Logseq auto save"
commit-message)]
(p/let [commit-oid (git/commit repo-url commit-message)]
(git-handler/set-latest-commit-if-exists! repo-url)
(git-handler/set-git-status! repo-url :pushing)
(when-let [token (state/get-github-token repo-url)]
(util/p-handle
@ -418,12 +408,11 @@
(fn [result]
(git-handler/set-git-status! repo-url nil)
(git-handler/set-git-error! repo-url nil)
(state/set-changed-files! repo-url nil)
(git-handler/set-remote-latest-commit! repo-url commit-oid))
(common-handler/check-changed-files-status repo-url))
(fn [error]
(println "Git push error: ")
(js/console.error error)
(common-handler/check-changed-files-status)
(common-handler/check-changed-files-status repo-url)
(let [permission? (or (string/includes? (str error) "401")
(string/includes? (str error) "404"))]
(cond
@ -476,9 +465,7 @@
(state/set-git-clone-repo! "")
(state/set-current-repo! repo-url)
(db/start-db-conn! (:me @state/state) repo-url)
(db/mark-repo-as-cloned repo-url)
(git-handler/set-latest-commit-if-exists! repo-url)
(git-handler/set-remote-latest-commit-if-exists! repo-url))
(db/mark-repo-as-cloned repo-url))
(fn [e]
(if (and (not fallback?)
(or (string/includes? (str e) "401")

View File

@ -210,6 +210,15 @@
[]
(get-in @state [:me :repos]))
(defn get-repo-branch
[repo-url]
(or
(->> (get-repos)
(filter (fn [repo] (= (:url repo) repo-url)))
first
:branch)
"master"))
(defn set-current-repo!
[repo]
(swap! state assoc :git/current-repo repo)