Fix vc-dir when "remote" Git branch is local
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.
This commit is contained in:
parent
7a0f4de3c1
commit
21828f288e
2 changed files with 72 additions and 14 deletions
|
@ -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."
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert-x)
|
||||
(require 'vc)
|
||||
(require 'vc-git)
|
||||
|
||||
(ert-deftest vc-git-test-program-version-general ()
|
||||
|
@ -81,4 +83,42 @@
|
|||
(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
|
||||
|
|
Loading…
Add table
Reference in a new issue