From: "Kévin Le Gouguec" <kevin.legouguec@gmail.com>
To: Tom Tromey <tom@tromey.com>
Cc: Dmitry Gutov <dmitry@gutov.dev>, Eli Zaretskii <eliz@gnu.org>,
68183@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
Subject: bug#68183: 28.3; vc-dir fails when I have a certain branch checked out
Date: Wed, 14 Feb 2024 20:56:28 +0100 [thread overview]
Message-ID: <877cj6izv7.fsf@gmail.com> (raw)
In-Reply-To: <878r3q2jfx.fsf@gmail.com> ("Kévin Le Gouguec"'s message of "Mon, 12 Feb 2024 09:08:50 +0100")
[-- Attachment #1: Type: text/plain, Size: 2196 bytes --]
Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:
> Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:
>
>> Tom Tromey <tom@tromey.com> writes:
>>
>>> Eli> Thanks, but I think we'd appreciate a reproducible recipe for this:
>>> Eli> how can one create a Git repository which can be used to reproduce
>>> Eli> this issue?
>>>
>>> This worked for me:
>>>
>>> $ cd ~/Emacs/trunk
>>> # This is my Emacs git repository
>>> $ git checkout --track -b vc-dir-bug master
>>> branch 'vc-dir-bug' set up to track 'master'.
>>> Switched to a new branch 'vc-dir-bug'
>>>
>>>
>>> Now invoke vc-dir on that directory.
>>
[…]
> Here's a patch. […]
And here's another revision, addressing most of the points below.
WDY'allT?
> * the test should probably have a (skip-unless (have-git-or-something)),
Done.
> * maybe "none (tracking local branch)" is not informative and we should
> ditch it,
> * maybe we should fall back to "origin", like vc-git-repository-url
> does,
FWIW, the current patch will show
Branch : vc-dir-tracking-branch
Tracking : origin/master
Remote : https://git.savannah.gnu.org/git/emacs.git
for my checkout of this work-in-progress patch, and
Branch : vc-dir-bug
Tracking : master
Remote : none (tracking local branch)
for a checkout made following Tom's recipe, and
Branch : trunk
for a fresh 'git init' with just a default branch.
OT1H "none (tracking local branch)" is redundant with "Tracking" not
being prefixed with "origin"; OTOH
* stripping "Remote" altogether might confuse users - at least "tracking
local branch" hints at what's going on,
* Falling back to origin's URL might also cause confusion: users might
then expect 'vc-pull' to fetch changes from that URL, which is not the
case.
So all in all I think the above is reasonably useful.
> * rushed the ChangeLog entry; vc-git-test--run should also be declared
> as a "new helper" (and maybe I should spell out that I used it to not
> have to depend on vc-git-- internal functions),
Done.
> * maybe the new header deserves a NEWS entry.
Maybe?
[-- Attachment #2: 0001-Fix-vc-dir-when-remote-Git-branch-is-local.patch --]
[-- Type: text/x-diff, Size: 6732 bytes --]
From ccca29fe2cce9b8c3477fcd31c8b37b1d8a57e94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= <kevin.legouguec@gmail.com>
Date: Mon, 12 Feb 2024 08:29:19 +0100
Subject: [PATCH] Fix vc-dir when "remote" Git branch is local
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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.
---
lisp/vc/vc-git.el | 46 +++++++++++++++++++++++++-----------
test/lisp/vc/vc-git-tests.el | 40 +++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 14 deletions(-)
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 456417e566e..b1d3dd533c6 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -817,27 +817,31 @@ vc-git--cmds-in-progress
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 @@ vc-git-dir-extra-headers
(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"
@@ -2219,8 +2228,17 @@ vc-git--call
(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."
diff --git a/test/lisp/vc/vc-git-tests.el b/test/lisp/vc/vc-git-tests.el
index c52cd9c5875..fd3e8ccd602 100644
--- a/test/lisp/vc/vc-git-tests.el
+++ b/test/lisp/vc/vc-git-tests.el
@@ -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 @@ vc-git-test-annotate-time
(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
--
2.39.2
next prev parent reply other threads:[~2024-02-14 19:56 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-31 18:59 bug#68183: 28.3; vc-dir fails when I have a certain branch checked out Tom Tromey
2023-12-31 19:34 ` Eli Zaretskii
2023-12-31 20:14 ` Tom Tromey
2024-01-03 9:46 ` Kévin Le Gouguec
2024-02-12 8:08 ` Kévin Le Gouguec
2024-02-14 19:56 ` Kévin Le Gouguec [this message]
2024-03-13 20:03 ` Kévin Le Gouguec
2024-03-15 2:57 ` Dmitry Gutov
2024-03-16 17:56 ` Kévin Le Gouguec
2024-03-17 1:06 ` Dmitry Gutov
2024-03-17 18:09 ` Kévin Le Gouguec
2024-03-18 15:26 ` Dmitry Gutov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=877cj6izv7.fsf@gmail.com \
--to=kevin.legouguec@gmail.com \
--cc=68183@debbugs.gnu.org \
--cc=dmitry@gutov.dev \
--cc=eliz@gnu.org \
--cc=juri@linkov.net \
--cc=tom@tromey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.