mirror of https://github.com/logseq/logseq
commit
55a75ae332
|
@ -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"])]))
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})))
|
||||
)
|
||||
|
|
|
@ -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]}]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue