Subject: bug#38044: 27.0.50; There should be an easier way to look at a specific vc commit

From: Stephen Berman <[email-masked]>
Date: Sun, 03 Nov 2019 16:43:08 +0100

On Sun, 03 Nov 2019 16:17:05 +0100 Lars Ingebrigtsen <[email-masked]> wrote:

> Often when discussing code changes, people will send an email saying
> something like "this was fixed by <id>", but Emacs doesn't have a
> convenient way to display that.
>
> For that case, Emacs should have a command that prompts for an ID
> (defaulting to the ID under point), and then (unless default-directory
> is already in a vc-controlled directory), prompts for the directory to
> look for that ID, and then display the commit.

I wrote such a command (appended below) for my own use, but it's
git-specific and I don't know the innards of VC well enough to adapt it,
which is why I haven't proposed it for inclusion in Emacs.  Maybe some
of it could be used for a VC command.

Steve Berman

(defun srb-git-log (&optional repo commit)
  "Check REPO for COMMIT and if it exists, display its commit message.
Interactively, prompt for REPO, defaulting to emacs-master, and
for COMMIT, defaulting to the commit hash at point.  If called
with a prefix argument `C-u', show the commit diff in addition to
the commit message."
  (interactive "P")
  (let* ((show (equal current-prefix-arg '(4)))
	 (git-dir (if repo
		      (read-directory-name "Repo: " "~/src/emacs/"
					   nil t "emacs-master")
		    "~/src/emacs/emacs-master"))
	 (commit0 (substring-no-properties
		   (or commit
		       (read-string "Commit: " nil nil (word-at-point)))))
	 (default-directory git-dir)
	 (output-buffer (get-buffer-create "*git log*"))
	 (args (split-string (mapconcat #'concat
					(if show
					    `("show" ,commit0)
					  `("log" "-1" ,commit0)) " ")))
	 ;; FIXME: output of `git branch --contains' can be ambiguous (even
	 ;; when `git log isn't, because one hash is for a commit, one for a
	 ;; tree?).  Can use `git rev-parse --disambiguate=' to find matching
	 ;; full hashes.
	 (proc (progn
		 (with-current-buffer output-buffer (erase-buffer))
		 (call-process "git" nil output-buffer nil
			       "branch" "--contains" commit0))))
    (when proc
      (with-current-buffer output-buffer
	(goto-char (point-min))
	(unless (looking-at "[ *]")
	  (user-error "%s is not on branch %s" commit0
		      (file-name-base git-dir)))
	(insert "Branches:\n")
	(goto-char (point-max))
	(apply #'call-process "git" nil output-buffer nil args)
	(when show
	  (with-current-buffer output-buffer
	    (diff-mode)))
	(pop-to-buffer output-buffer)))))