]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix vc-dir when "remote" Git branch is local
authorKévin Le Gouguec <kevin.legouguec@gmail.com>
Mon, 12 Feb 2024 07:29:19 +0000 (08:29 +0100)
committerEshel Yaron <me@eshelyaron.com>
Mon, 18 Mar 2024 15:44:11 +0000 (16:44 +0100)
While in there, add that "tracking" branch to the vc-dir
buffer.  For bug#68183.

* lisp/vc/vc-git.el (vc-git-dir-extra-headers): Reduce
boilerplate with new function 'vc-git--out-ok'; stop calling
vc-git-repository-url when REMOTE is "." to avoid throwing an
error; display tracking branch; prefer "none (<details...>)" to
"not (<details...>)" since that reads more grammatically
correct.
(vc-git--out-ok): Add documentation.
(vc-git--out-str): New function to easily get the output from a
Git command.
* test/lisp/vc/vc-git-tests.el (vc-git-test--with-repo)
(vc-git-test--run): New helpers, defined to steer clear of
vc-git-- internal functions.
(vc-git-test-dir-track-local-branch): Check that vc-dir does
not crash.

(cherry picked from commit 21828f288ef57422d12860d71e3d4cd8b8cc97b4)

lisp/vc/vc-git.el
test/lisp/vc/vc-git-tests.el

index 18b4a8691e942c73232687663e8b39ee80cc6618..0d54e2346599d0f291ec8aa7d7678953351f8195 100644 (file)
@@ -817,27 +817,31 @@ or an empty string if none."
     cmds))
 
 (defun vc-git-dir-extra-headers (dir)
-  (let ((str (with-output-to-string
-               (with-current-buffer standard-output
-                 (vc-git--out-ok "symbolic-ref" "HEAD"))))
+  (let ((str (vc-git--out-str "symbolic-ref" "HEAD"))
        (stash-list (vc-git-stash-list))
         (default-directory dir)
         (in-progress (vc-git--cmds-in-progress))
 
-       branch remote remote-url stash-button stash-string)
+       branch remote-url stash-button stash-string tracking-branch)
     (if (string-match "^\\(refs/heads/\\)?\\(.+\\)$" str)
        (progn
          (setq branch (match-string 2 str))
-         (setq remote
-               (with-output-to-string
-                 (with-current-buffer standard-output
-                   (vc-git--out-ok "config"
-                                    (concat "branch." branch ".remote")))))
-         (when (string-match "\\([^\n]+\\)" remote)
-           (setq remote (match-string 1 remote)))
-          (when (> (length remote) 0)
-           (setq remote-url (vc-git-repository-url dir remote))))
-      (setq branch "not (detached HEAD)"))
+          (let ((remote (vc-git--out-str
+                         "config" (concat "branch." branch ".remote")))
+                (merge (vc-git--out-str
+                        "config" (concat "branch." branch ".merge"))))
+            (when (string-match "\\([^\n]+\\)" remote)
+             (setq remote (match-string 1 remote)))
+            (when (string-match "^\\(refs/heads/\\)?\\(.+\\)$" merge)
+              (setq tracking-branch (match-string 2 merge)))
+            (pcase remote
+              ("."
+               (setq remote-url "none (tracking local branch)"))
+              ((pred (not string-empty-p))
+               (setq
+                remote-url (vc-git-repository-url dir remote)
+                tracking-branch (concat remote "/" tracking-branch))))))
+      (setq branch "none (detached HEAD)"))
     (when stash-list
       (let* ((len (length stash-list))
              (limit
@@ -890,6 +894,11 @@ or an empty string if none."
      (propertize "Branch     : " 'face 'vc-dir-header)
      (propertize branch
                 'face 'vc-dir-header-value)
+     (when tracking-branch
+       (concat
+        "\n"
+        (propertize "Tracking   : " 'face 'vc-dir-header)
+        (propertize tracking-branch 'face 'vc-dir-header-value)))
      (when remote-url
        (concat
        "\n"
@@ -2226,8 +2235,17 @@ The difference to vc-do-command is that this function always invokes
     (apply #'process-file vc-git-program nil buffer nil "--no-pager" command args)))
 
 (defun vc-git--out-ok (command &rest args)
+  "Run `git COMMAND ARGS...' and insert standard output in current buffer.
+Return whether the process exited with status zero."
   (zerop (apply #'vc-git--call '(t nil) command args)))
 
+(defun vc-git--out-str (command &rest args)
+  "Run `git COMMAND ARGS...' and return standard output.
+The exit status is ignored."
+  (with-output-to-string
+    (with-current-buffer standard-output
+      (apply #'vc-git--out-ok command args))))
+
 (defun vc-git--run-command-string (file &rest args)
   "Run a git command on FILE and return its output as string.
 FILE can be nil."
index c52cd9c5875371070634a68e21f92a6d954ac05f..fd3e8ccd6022842edba1dad0aa8cdb2d4318f16d 100644 (file)
@@ -24,6 +24,8 @@
 
 ;;; Code:
 
+(require 'ert-x)
+(require 'vc)
 (require 'vc-git)
 
 (ert-deftest vc-git-test-program-version-general ()
     (should-not (vc-git-annotate-time))
     (should-not (vc-git-annotate-time))))
 
+(defmacro vc-git-test--with-repo (name &rest body)
+  "Initialize a repository in a temporary directory and evaluate BODY.
+
+The current directory will be set to the top of that repository; NAME
+will be bound to that directory's file name.  Once BODY exits, the
+directory will be deleted."
+  (declare (indent 1))
+  `(ert-with-temp-directory ,name
+     (let ((default-directory ,name))
+       (vc-create-repo 'Git)
+       ,@body)))
+
+(defun vc-git-test--run (&rest args)
+  "Run git ARGS…, check for non-zero status, and return output."
+  (with-temp-buffer
+    (apply 'vc-git-command t 0 nil args)
+    (buffer-string)))
+
+(ert-deftest vc-git-test-dir-track-local-branch ()
+  "Test that `vc-dir' works when tracking local branches.  Bug#68183."
+  (skip-unless (executable-find vc-git-program))
+  (vc-git-test--with-repo repo
+    ;; Create an initial commit to get a branch started.
+    (write-region "hello" nil "README")
+    (vc-git-test--run "add" "README")
+    (vc-git-test--run "commit" "-mFirst")
+    ;; Get current branch name lazily, to remain agnostic of
+    ;; init.defaultbranch.
+    (let ((upstream-branch
+           (string-trim (vc-git-test--run "branch" "--show-current"))))
+      (vc-git-test--run "checkout" "--track" "-b" "hack" upstream-branch)
+      (vc-dir default-directory)
+      (pcase-dolist (`(,header ,value)
+                     `(("Branch" "hack")
+                       ("Tracking" ,upstream-branch)))
+        (goto-char (point-min))
+        (re-search-forward (format "^%s *: %s$" header value))))))
+
 ;;; vc-git-tests.el ends here