@@ -314,6 +314,15 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
314314 (lambda (value )
315315 (or (null value) (stringp value))))
316316
317+ (defun diff-hl--target-buffer (buf )
318+ " Return the correct buffer for the situation, preferring the base buffer."
319+ (or (buffer-base-buffer buf) buf))
320+
321+ (defun diff-hl--buffer-file-name (&optional buffer )
322+ " Return the file name of the BUFFER or its base buffer.
323+ BUFFER defaults to the current buffer."
324+ (buffer-file-name (diff-hl--target-buffer (or buffer (current-buffer )))))
325+
317326(defun diff-hl-define-bitmaps ()
318327 (let* ((scale (if (and (boundp 'text-scale-mode-amount )
319328 (numberp text-scale-mode-amount))
@@ -485,7 +494,7 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
485494 buffer)
486495
487496(defun diff-hl-changes ()
488- (let* ((file buffer-file-name)
497+ (let* ((file (diff-hl-- buffer-file-name) )
489498 (backend (vc-backend file))
490499 (hide-staged (and (eq backend 'Git ) (not diff-hl-show-staged-changes))))
491500 (when backend
@@ -530,7 +539,7 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
530539 (or (assoc-default backend diff-hl-head-revision-alist)
531540 ; ; It's usually cached already (e.g. for mode-line).
532541 ; ; So this is basically an optimization for rare cases.
533- (vc-working-revision buffer-file-name backend)))
542+ (vc-working-revision (diff-hl-- buffer-file-name) backend)))
534543
535544(defun diff-hl-adjust-changes (old new )
536545 " Adjust changesets in OLD using changes in NEW.
@@ -732,17 +741,22 @@ Return a list of line overlays used."
732741 (lambda (ref-changes )
733742 (when (buffer-live-p orig)
734743 (let ((ref-changes (diff-hl-adjust-changes ref-changes changes))
735- reuse)
736- (with-current-buffer orig
737- (diff-hl-remove-overlays)
738- (let ((diff-hl-highlight-function
739- diff-hl-highlight-reference-function)
740- (diff-hl-fringe-face-function
741- diff-hl-fringe-reference-face-function))
742- (setq reuse (diff-hl--update-overlays ref-changes nil )))
743- (diff-hl--update-overlays changes reuse)
744- (when (not (or changes ref-changes))
745- (diff-hl--autohide-margin)))))))))))
744+ (base (diff-hl--target-buffer orig)))
745+ (dolist (buf (buffer-list ))
746+ (when (and (buffer-live-p buf)
747+ (eq (diff-hl--target-buffer buf) base)
748+ (buffer-local-value 'diff-hl-mode buf))
749+ (with-current-buffer buf
750+ (let (reuse)
751+ (diff-hl-remove-overlays)
752+ (let ((diff-hl-highlight-function
753+ diff-hl-highlight-reference-function)
754+ (diff-hl-fringe-face-function
755+ diff-hl-fringe-reference-face-function))
756+ (setq reuse (diff-hl--update-overlays ref-changes nil )))
757+ (diff-hl--update-overlays changes reuse)
758+ (when (not (or changes ref-changes))
759+ (diff-hl--autohide-margin))))))))))))))
746760
747761(defun diff-hl--resolve (value-or-buffer cb )
748762 (if (listp value-or-buffer)
@@ -869,15 +883,15 @@ Return a list of line overlays used."
869883With double prefix argument (C-u C-u), the diff is made against the
870884reference revision."
871885 (interactive (list current-prefix-arg))
872- (with-current-buffer (or ( buffer-base-buffer ) ( current-buffer ) )
886+ (with-current-buffer (current-buffer )
873887 (if (equal historic '(16 ))
874888 (diff-hl-diff-reference-goto-hunk)
875889 (diff-hl-diff-goto-hunk-1 historic nil ))))
876890
877891(defun diff-hl-diff-reference-goto-hunk ()
878892 " Run VC diff command against the reference and go to the corresponding line."
879893 (interactive )
880- (with-current-buffer (or ( buffer-base-buffer ) ( current-buffer ) )
894+ (with-current-buffer (current-buffer )
881895 (diff-hl-diff-goto-hunk-1 nil diff-hl-reference-revision)))
882896
883897(defun diff-hl-root-diff-reference-goto-hunk ()
@@ -886,7 +900,7 @@ And if the current buffer is visiting a file, and it has changes, the diff
886900buffer will show the position corresponding to its current line."
887901 (interactive )
888902 (defvar vc-sentinel-movepoint )
889- (with-current-buffer (or ( buffer-base-buffer ) ( current-buffer ) )
903+ (with-current-buffer (current-buffer )
890904 (let ((backend (vc-deduce-backend ))
891905 (default-directory default-directory)
892906 rootdir fileset
@@ -895,8 +909,9 @@ buffer will show the position corresponding to its current line."
895909 (setq rootdir (vc-call-backend backend 'root default-directory)
896910 default-directory rootdir
897911 fileset `(,backend (,rootdir ))
898- relname (if buffer-file-name (file-relative-name buffer-file-name
899- rootdir)))
912+ relname (let ((file (diff-hl--buffer-file-name)))
913+ (when file
914+ (file-relative-name file rootdir))))
900915 (error " Directory is not version controlled " ))
901916 (setq fileset (or fileset (vc-deduce-fileset )))
902917 (vc-buffer-sync-fileset fileset t )
@@ -911,7 +926,7 @@ buffer will show the position corresponding to its current line."
911926 (setq vc-sentinel-movepoint (point ))))))))
912927
913928(defun diff-hl-diff-read-revisions (rev1-default )
914- (let* ((file buffer-file-name)
929+ (let* ((file (diff-hl-- buffer-file-name) )
915930 (files (list file))
916931 (backend (vc-backend file))
917932 (rev2-default nil ))
@@ -1011,7 +1026,7 @@ that file, if it's present."
10111026 (line (save-excursion
10121027 (diff-hl-find-current-hunk)
10131028 (line-number-at-pos )))
1014- (file buffer-file-name)
1029+ (file (diff-hl-- buffer-file-name) )
10151030 (backend (vc-backend file)))
10161031 (unwind-protect
10171032 (progn
@@ -1091,7 +1106,7 @@ its end position."
10911106(defun diff-hl-revert-hunk ()
10921107 " Revert the diff hunk with changes at or above the point."
10931108 (interactive )
1094- (with-current-buffer (or ( buffer-base-buffer ) ( current-buffer ) )
1109+ (with-current-buffer (current-buffer )
10951110 (diff-hl-revert-hunk-1)))
10961111
10971112(defun diff-hl-hunk-overlay-at (pos )
@@ -1147,7 +1162,7 @@ its end position."
11471162 (push-mark (overlay-end hunk) nil t )))
11481163
11491164(defun diff-hl--ensure-staging-supported ()
1150- (let ((backend (vc-backend buffer-file-name)))
1165+ (let ((backend (vc-backend (diff-hl-- buffer-file-name) )))
11511166 (unless (eq backend 'Git )
11521167 (user-error " Only Git supports staging; this file is controlled by %s" backend))))
11531168
@@ -1174,7 +1189,7 @@ Only supported with Git."
11741189 (diff-hl--ensure-staging-supported)
11751190 (diff-hl-find-current-hunk)
11761191 (let* ((line (line-number-at-pos ))
1177- (file buffer-file-name)
1192+ (file (diff-hl-- buffer-file-name) )
11781193 (dest-buffer (get-buffer-create " *diff-hl-stage*" ))
11791194 (orig-buffer (current-buffer ))
11801195 ; ; FIXME: If the file name has double quotes, these need to be quoted.
@@ -1215,13 +1230,14 @@ Only supported with Git."
12151230
12161231Only supported with Git."
12171232 (interactive )
1218- (unless buffer-file-name
1219- (user-error " No current file" ))
1220- (diff-hl--ensure-staging-supported)
1221- (vc-git-command nil 0 buffer-file-name " reset" )
1222- (message " Unstaged all " )
1223- (unless diff-hl-show-staged-changes
1224- (diff-hl-update)))
1233+ (let ((file (diff-hl--buffer-file-name)))
1234+ (unless file
1235+ (user-error " No current file" ))
1236+ (diff-hl--ensure-staging-supported)
1237+ (vc-git-command nil 0 file " reset" )
1238+ (message " Unstaged all " )
1239+ (unless diff-hl-show-staged-changes
1240+ (diff-hl-update))))
12251241
12261242(defun diff-hl-stage-dwim (&optional with-edit )
12271243 " Stage the current hunk or choose the hunks to stage.
@@ -1248,7 +1264,7 @@ Pops up a diff buffer that can be edited to choose the changes to stage."
12481264 (diff-hl--ensure-staging-supported)
12491265 (let* ((line-beg (and beg (line-number-at-pos beg t )))
12501266 (line-end (and end (line-number-at-pos end t )))
1251- (file buffer-file-name)
1267+ (file (diff-hl-- buffer-file-name) )
12521268 (dest-buffer (get-buffer-create " *diff-hl-stage-some*" ))
12531269 (orig-buffer (current-buffer ))
12541270 (diff-hl-update-async nil )
@@ -1392,14 +1408,14 @@ The value of this variable is a mode line template as in
13921408 (declare-function smartrep-define-key 'smartrep )
13931409 (let (smart-keys)
13941410 (cl-labels ((scan (map )
1395- (map-keymap
1396- (lambda (event binding )
1397- (if (consp binding)
1398- (scan binding)
1399- (when (and (characterp event)
1400- (not (memq binding diff-hl-repeat-exceptions)))
1401- (push (cons (string event) binding) smart-keys))))
1402- map)))
1411+ (map-keymap
1412+ (lambda (event binding )
1413+ (if (consp binding)
1414+ (scan binding)
1415+ (when (and (characterp event)
1416+ (not (memq binding diff-hl-repeat-exceptions)))
1417+ (push (cons (string event) binding) smart-keys))))
1418+ map)))
14031419 (scan diff-hl-command-map)
14041420 (smartrep-define-key diff-hl-mode-map diff-hl-command-prefix smart-keys))))
14051421
@@ -1424,19 +1440,21 @@ The value of this variable is a mode line template as in
14241440 (let* ((topdir (magit-toplevel))
14251441 (modified-files
14261442 (magit-git-items " diff-tree" " -z" " --name-only" " -r" " HEAD~" " HEAD" ))
1427- (unmodified-states '(up-to-date ignored unregistered)))
1443+ (unmodified-states '(up-to-date ignored unregistered))
1444+ file)
14281445 (dolist (buf (buffer-list ))
1429- (when (and (buffer-local-value 'diff-hl-mode buf)
1430- (not (buffer-modified-p buf))
1431- ; ; Solve the "cloned indirect buffer" problem
1432- ; ; (diff-hl-mode could be non-nil there, even if
1433- ; ; buffer-file-name is nil):
1434- (buffer-file-name buf)
1435- (file-in-directory-p (buffer-file-name buf) topdir)
1436- (file-exists-p (buffer-file-name buf)))
1446+ (setq file (diff-hl--buffer-file-name buf))
1447+ (when (and
1448+ (buffer-local-value 'diff-hl-mode buf)
1449+ (not (buffer-modified-p buf))
1450+ ; ; Solve the "cloned indirect buffer" problem
1451+ ; ; (diff-hl-mode could be non-nil there, even if
1452+ ; ; buffer-file-name is nil):
1453+ file
1454+ (file-in-directory-p file topdir)
1455+ (file-exists-p file))
14371456 (with-current-buffer buf
1438- (let* ((file buffer-file-name)
1439- (backend (vc-backend file)))
1457+ (let* ((backend (vc-backend file)))
14401458 (when backend
14411459 (cond
14421460 ((member file modified-files)
@@ -1538,7 +1556,7 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0."
15381556 backend
15391557 (or diff-hl-reference-revision
15401558 (assoc-default backend diff-hl-head-revision-alist)))
1541- (diff-hl-working-revision buffer-file-name backend)))))
1559+ (diff-hl-working-revision (diff-hl-- buffer-file-name) backend)))))
15421560 (switches (format " -U %d --strip-trailing-cr " (or context-lines 0 ))))
15431561 (diff-no-select rev (current-buffer ) switches (not (diff-hl--use-async-p))
15441562 (get-buffer-create dest-buffer))
@@ -1606,13 +1624,14 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0."
16061624;;;### autoload
16071625(defun turn-on-diff-hl-mode ()
16081626 " Turn on `diff-hl-mode' or `diff-hl-dir-mode' in a buffer if appropriate."
1609- (cond
1610- (buffer-file-name
1611- (unless (and diff-hl-disable-on-remote
1612- (file-remote-p buffer-file-name))
1613- (diff-hl-mode 1 )))
1614- ((eq major-mode 'vc-dir-mode )
1615- (diff-hl-dir-mode 1 ))))
1627+ (let ((file (diff-hl--buffer-file-name)))
1628+ (cond
1629+ (file
1630+ (unless (and diff-hl-disable-on-remote
1631+ (file-remote-p file))
1632+ (diff-hl-mode 1 )))
1633+ ((eq major-mode 'vc-dir-mode )
1634+ (diff-hl-dir-mode 1 )))))
16161635
16171636;;;### autoload
16181637(defun diff-hl--global-turn-on ()
0 commit comments