Skip to content

Commit 5446a69

Browse files
committed
New command: diff-hl-root-diff-reference-goto-hunk
Behavior similar to vc-root-diff (C-x v D), but uses the reference revision as the comparison.
1 parent 9ef720e commit 5446a69

1 file changed

Lines changed: 57 additions & 6 deletions

File tree

diff-hl.el

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,36 @@ reference revision."
778778
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
779779
(diff-hl-diff-goto-hunk-1 nil diff-hl-reference-revision)))
780780

781+
(defun diff-hl-root-diff-reference-goto-hunk ()
782+
"Run VC diff command against the reference for the whole tree.
783+
And if the current buffer is visiting a file, and it has changes, the diff
784+
buffer will show the position corresponding to its current line."
785+
(interactive)
786+
(defvar vc-sentinel-movepoint)
787+
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
788+
(let ((backend (vc-deduce-backend))
789+
(default-directory default-directory)
790+
rootdir fileset
791+
relname)
792+
(if backend
793+
(setq rootdir (vc-call-backend backend 'root default-directory)
794+
default-directory rootdir
795+
fileset `(,backend (,rootdir))
796+
relname (if buffer-file-name (file-relative-name buffer-file-name
797+
rootdir)))
798+
(error "Directory is not version controlled"))
799+
(setq fileset (or fileset (vc-deduce-fileset)))
800+
(vc-buffer-sync-fileset fileset t)
801+
(let* ((line (line-number-at-pos)))
802+
(vc-diff-internal
803+
(if (boundp 'vc-allow-async-diff)
804+
vc-allow-async-diff
805+
t)
806+
fileset diff-hl-reference-revision nil t)
807+
(vc-run-delayed (when relname
808+
(diff-hl-diff-skip-to line relname)
809+
(setq vc-sentinel-movepoint (point))))))))
810+
781811
(defun diff-hl-diff-read-revisions (rev1-default)
782812
(let* ((file buffer-file-name)
783813
(files (list file))
@@ -807,13 +837,31 @@ reference revision."
807837
(when (string= rev2 "") (setq rev2 nil))
808838
(cons rev1 rev2))))
809839

810-
(defun diff-hl-diff-skip-to (line)
840+
(defun diff-hl-diff-skip-to (line &optional filename)
811841
"In `diff-mode', skip to the hunk and line corresponding to LINE
812-
in the source file, or the last line of the hunk above it."
842+
in the source file, or the last line of the hunk above it.
843+
844+
When passed FILENAME, ensure that the line is in the section belonging to
845+
that file, if it's present."
813846
(goto-char (point-min)) ; Counteract any similar behavior in diff-mode.
814-
(diff-hunk-next)
815-
(let (found)
816-
(while (and (looking-at diff-hunk-header-re-unified) (not found))
847+
(let (found
848+
(end-pos (point-max)))
849+
(diff-hunk-next)
850+
(when filename
851+
(while (and (not (equal (diff-find-file-name nil t)
852+
filename))
853+
(not (eobp)))
854+
(diff-file-next))
855+
(if (not (eobp))
856+
;; Found our file in the changed set. Ensure that we don't go past.
857+
(setq end-pos (save-excursion
858+
(diff-end-of-file)
859+
(point)))
860+
(goto-char (point-min))
861+
(setq line 0)))
862+
(while (and (looking-at diff-hunk-header-re-unified)
863+
(not found)
864+
(< (point) end-pos))
817865
(let ((hunk-line (string-to-number (match-string 3)))
818866
(len (let ((m (match-string 4)))
819867
(if m (string-to-number m) 1))))
@@ -827,7 +875,10 @@ in the source file, or the last line of the hunk above it."
827875
(while (cl-plusp to-go)
828876
(forward-line 1)
829877
(unless (looking-at "^[-\\]")
830-
(cl-decf to-go))))))))))
878+
(cl-decf to-go))))))))
879+
(when (> (point) end-pos)
880+
(diff-hunk-prev)
881+
(diff-end-of-hunk))))
831882

832883
(defface diff-hl-reverted-hunk-highlight
833884
'((default :inverse-video t))

0 commit comments

Comments
 (0)