Browse Source

refactor: simplify git state

Retreive both local and remote oids using resolveRef.
Tienson Qin 5 years ago
parent
commit
b5e3f7de6e

+ 36 - 39
src/main/frontend/components/diff.cljs

@@ -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"])]))

+ 0 - 1
src/main/frontend/db.cljs

@@ -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))))

+ 0 - 4
src/main/frontend/db_schema.cljs

@@ -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

+ 34 - 2
src/main/frontend/handler/common.cljs

@@ -4,8 +4,22 @@
             [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)]
@@ -15,10 +29,28 @@
       (->
        (p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo))]
          (let [files (bean/->clj files)]
-           (state/set-changed-files! repo 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})))
+  )

+ 9 - 45
src/main/frontend/handler/git.cljs

@@ -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]}]

+ 77 - 90
src/main/frontend/handler/repo.cljs

@@ -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
-
-                                (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))
-
-                                  :else
-                                  nil))))))))))))))
+    (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))))))
+                                       (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)
+                                    (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)
+
+                              (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))))))))))))
 
 (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,8 +408,7 @@
                      (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))
+                       (state/set-changed-files! repo-url nil))
                      (fn [error]
                        (println "Git push error: ")
                        (js/console.error error)
@@ -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")

+ 9 - 0
src/main/frontend/state.cljs

@@ -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)