From: Juri Linkov <juri@linkov.net>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 33319@debbugs.gnu.org
Subject: bug#33319: Support revisions in diff-goto-source
Date: Sat, 10 Nov 2018 23:12:51 +0200 [thread overview]
Message-ID: <87in14ra6c.fsf@mail.linkov.net> (raw)
In-Reply-To: <83pnvebscp.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 09 Nov 2018 09:52:22 +0200")
[-- Attachment #1: Type: text/plain, Size: 1616 bytes --]
>> +*** In the diff buffer created by a version control system, the prefix
>> +arg of diff-goto-source means it jumps to the old revision of the file
> ^^^^^^^^^^^^^^^^^
> "... means jump to ..." is a better wording, I think.
>
> Also, it is best to provide a header for the description of the
> change, so that it could be meaningfully folded by Outline mode.
Fixed in a new patch.
> And I think we want to update the manual as well.
Updated.
>> +(defvar diff-vc-revisions nil
>> + "The VC revisions compared in the current Diff buffer, if any.")
>> +
>> (defvar diff-outline-regexp
>> "\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)")
>
> Which VCSes does this support? I'm not sure all of them produce such
> markers. If this supports only some, we should document that and make
> sure the code does something reasonable when the revision is not
> found.
It should work in all VCSes that support the VC interface function
'find-revision' defined in the comments of vc.el:
;; * find-revision (file rev buffer)
;;
;; Fetch revision REV of file FILE and put it into BUFFER.
;; If REV is the empty string, fetch the head of the trunk.
;; The implementation should pass the value of vc-checkout-switches
;; to the backend command.
BTW, its implementation in vc-find-revision currently has
a major shortcoming: it always saves the retrieved revision
to the file. I spend too much time cleaning after this command
all old files that it creates. Thus I propose a new option
`vc-find-revision-no-save' to not save the buffer it creates
to the file.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: diff-goto-source.2.patch --]
[-- Type: text/x-diff, Size: 6699 bytes --]
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 6c68075ae4..523734ec1f 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1507,7 +1507,11 @@ Diff Mode
@item C-c C-c
@findex diff-goto-source
Go to the source file and line corresponding to this hunk
-(@code{diff-goto-source}).
+(@code{diff-goto-source}). With a prefix argument of @kbd{C-u},
+go to the old source file. If the source file is under version
+control (@pxref{Version Control}), with a prefix argument of
+@kbd{C-u}, go to the old revision of the file (@pxref{Old Revisions})
+when point is on old line, or otherwise to the new revision.
@item C-c C-e
@findex diff-ediff-patch
diff --git a/etc/NEWS b/etc/NEWS
index 29bbde9395..cea600c430 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -334,6 +334,9 @@ still be used if it exists.) Set the variable to nil to get the
previous behavior of always creating a buffer that visits a ChangeLog
file.
+*** New customizable variable 'vc-find-revision-no-save'.
+With non-nil, 'vc-find-revision' doesn't write the created buffer to file.
+
*** New customizable variable 'vc-git-grep-template'.
This new variable allows customizing the default arguments passed to
git-grep when 'vc-git-grep' is used.
@@ -358,6 +361,10 @@ To disable it, set the new defcustom 'diff-font-lock-refine' to nil.
*** File headers can be shortened, mimicking Magit's diff format.
To enable it, set the new defcustom 'diff-font-lock-prettify to t.
+*** Prefix arg of 'diff-goto-source' means jump to the old revision
+of the file under version control if point is on an old changed line,
+or to the new revision of the file otherwise.
+
** Browse-url
*** The function 'browse-url-emacs' can now visit a URL in selected window.
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index cf52368508..aef16e2e67 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -104,6 +105,9 @@ diff-font-lock-prettify
(defvar diff-vc-backend nil
"The VC backend that created the current Diff buffer, if any.")
+(defvar diff-vc-revisions nil
+ "The VC revisions compared in the current Diff buffer, if any.")
+
(defvar diff-outline-regexp
"\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)")
@@ -1736,7 +1740,12 @@ diff-find-source-location
(match-string 1)))))
(file (or (diff-find-file-name other noprompt)
(error "Can't find the file")))
- (buf (find-file-noselect file)))
+ (revision (and other diff-vc-backend
+ (nth (if reverse 1 0) diff-vc-revisions)))
+ (buf (if revision
+ (let ((vc-find-revision-no-save t))
+ (vc-find-revision file revision diff-vc-backend))
+ (find-file-noselect file))))
;; Update the user preference if he so wished.
(when (> (prefix-numeric-value other-file) 8)
(setq diff-jump-to-old-file other))
@@ -1862,7 +1871,11 @@ diff-goto-source
`diff-jump-to-old-file' (or its opposite if the OTHER-FILE prefix arg
is given) determines whether to jump to the old or the new file.
If the prefix arg is bigger than 8 (for example with \\[universal-argument] \\[universal-argument])
-then `diff-jump-to-old-file' is also set, for the next invocations."
+then `diff-jump-to-old-file' is also set, for the next invocations.
+
+Under version control, the OTHER-FILE prefix arg means jump to the old
+revision of the file if point is on an old changed line, or to the new
+revision of the file otherwise."
(interactive (list current-prefix-arg last-input-event))
;; When pointing at a removal line, we probably want to jump to
;; the old location, and else to the new (i.e. as if reverting).
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index dcfbf26e86..7c4c288b66 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -871,6 +871,12 @@ vc-comment-alist
(string :tag "Comment End")))
:group 'vc)
+(defcustom vc-find-revision-no-save nil
+ "If non-nil, `vc-find-revision' doesn't write the created buffer to file."
+ :type 'boolean
+ :group 'vc
+ :version "27.1")
+
\f
;; File property caching
@@ -1728,6 +1735,7 @@ vc-diff-internal
(set-buffer buffer)
(diff-mode)
(set (make-local-variable 'diff-vc-backend) (car vc-fileset))
+ (set (make-local-variable 'diff-vc-revisions) (list rev1 rev2))
(set (make-local-variable 'revert-buffer-function)
(lambda (_ignore-auto _noconfirm)
(vc-diff-internal async vc-fileset rev1 rev2 verbose)))
@@ -1951,6 +1959,8 @@ vc-revision-other-window
(defun vc-find-revision (file revision &optional backend)
"Read REVISION of FILE into a buffer and return the buffer.
Use BACKEND as the VC backend if specified."
+ (if vc-find-revision-no-save
+ (vc-find-revision-no-save file revision backend)
(let ((automatic-backup (vc-version-backup-file-name file revision))
(filebuf (or (get-file-buffer file) (current-buffer)))
(filename (vc-version-backup-file-name file revision 'manual)))
@@ -1981,6 +1991,38 @@ vc-find-revision
;; Set the parent buffer so that things like
;; C-x v g, C-x v l, ... etc work.
(set (make-local-variable 'vc-parent-buffer) filebuf))
+ result-buf))))
+
+(defun vc-find-revision-no-save (file revision &optional backend)
+ "Read REVISION of FILE into a buffer and return the buffer.
+Unlike `vc-find-revision', doesn't save the created buffer to file."
+ (let ((filebuf (or (get-file-buffer file) (current-buffer)))
+ (filename (vc-version-backup-file-name file revision 'manual)))
+ (unless (or (get-file-buffer filename)
+ (file-exists-p filename))
+ (with-current-buffer filebuf
+ (let ((failed t))
+ (unwind-protect
+ (let ((coding-system-for-read 'no-conversion)
+ (coding-system-for-write 'no-conversion))
+ (with-current-buffer (create-file-buffer filename)
+ (setq buffer-file-name filename)
+ (let ((outbuf (current-buffer)))
+ (with-current-buffer filebuf
+ (if backend
+ (vc-call-backend backend 'find-revision file revision outbuf)
+ (vc-call find-revision file revision outbuf))))
+ (goto-char (point-min))
+ (normal-mode)
+ (set-buffer-modified-p nil)
+ (setq buffer-read-only t))
+ (setq failed nil))
+ (when (and failed (get-file-buffer filename))
+ (kill-buffer (get-file-buffer filename)))))))
+ (let ((result-buf (or (get-file-buffer filename)
+ (find-file-noselect filename))))
+ (with-current-buffer result-buf
+ (set (make-local-variable 'vc-parent-buffer) filebuf))
result-buf)))
;; Header-insertion code
next prev parent reply other threads:[~2018-11-10 21:12 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-08 21:05 bug#33319: Support revisions in diff-goto-source Juri Linkov
2018-11-09 7:52 ` Eli Zaretskii
2018-11-10 21:12 ` Juri Linkov [this message]
2018-11-11 15:40 ` Eli Zaretskii
2018-11-14 0:24 ` Juri Linkov
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=87in14ra6c.fsf@mail.linkov.net \
--to=juri@linkov.net \
--cc=33319@debbugs.gnu.org \
--cc=eliz@gnu.org \
/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.