Skip to content

Commit 6915bc4

Browse files
committed
Support indirect buffers by resolving base buffer file names
- Add diff-hl--buffer-file-name helper to retrieve the file name of the current buffer or its base buffer. - Replace direct accesses of the buffer-file-name variable with the new helper changes to all live buffers sharing the same base buffer.
1 parent b965e19 commit 6915bc4

5 files changed

Lines changed: 75 additions & 61 deletions

File tree

diff-hl-amend.el

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Currently only supports Git, Mercurial and Bazaar."
4444
(diff-hl-update)))
4545

4646
(defun diff-hl-amend-setup ()
47-
(let ((backend (vc-backend buffer-file-name)))
47+
(let ((backend (vc-backend (diff-hl--buffer-file-name))))
4848
(when backend
4949
(setq-local diff-hl-reference-revision
5050
(cl-case backend
@@ -62,7 +62,7 @@ Currently only supports Git, Mercurial and Bazaar."
6262

6363
(defun turn-on-diff-hl-amend-mode ()
6464
"Turn on `diff-hl-amend-mode' in a buffer if appropriate."
65-
(and buffer-file-name (diff-hl-amend-mode 1)))
65+
(and (diff-hl--buffer-file-name) (diff-hl-amend-mode 1)))
6666

6767
(provide 'diff-hl-amend)
6868

diff-hl-flydiff.el

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@
5252
(unless (or
5353
(not diff-hl-mode)
5454
(eq diff-hl-flydiff-modified-tick (buffer-chars-modified-tick))
55-
(not buffer-file-name)
56-
(file-remote-p default-directory)
57-
(not (file-exists-p buffer-file-name)))
55+
(let ((file (diff-hl--buffer-file-name)))
56+
(or (not file)
57+
(file-remote-p default-directory)
58+
(not (file-exists-p file)))))
5859
(diff-hl-update)))
5960

6061
(defun diff-hl-flydiff/modified-p (_state)

diff-hl-show-hunk.el

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,11 @@ buffer."
134134
(line (line-number-at-pos))
135135
(dest-buffer diff-hl-show-hunk-diff-buffer-name))
136136
(with-current-buffer buffer
137-
(if (buffer-modified-p)
138-
(diff-hl-diff-buffer-with-reference buffer-file-name dest-buffer)
139-
(diff-hl-changes-buffer buffer-file-name (vc-backend buffer-file-name)
140-
nil dest-buffer))
137+
(let ((file (diff-hl--buffer-file-name)))
138+
(if (buffer-modified-p)
139+
(diff-hl-diff-buffer-with-reference file dest-buffer)
140+
(diff-hl-changes-buffer file (vc-backend file)
141+
nil dest-buffer)))
141142
(switch-to-buffer dest-buffer)
142143
(diff-hl-diff-skip-to line)
143144
(setq vc-sentinel-movepoint (point)))

diff-hl.el

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -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--buffer-file-name (&optional buffer)
318+
"Return the file name of the BUFFER or its base buffer.
319+
BUFFER defaults to the current buffer."
320+
(let* ((buffer (or buffer (current-buffer)))
321+
(base-buffer (buffer-base-buffer buffer)))
322+
(if base-buffer
323+
(buffer-file-name base-buffer)
324+
(buffer-file-name 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.
@@ -893,8 +902,9 @@ buffer will show the position corresponding to its current line."
893902
(setq rootdir (vc-call-backend backend 'root default-directory)
894903
default-directory rootdir
895904
fileset `(,backend (,rootdir))
896-
relname (if buffer-file-name (file-relative-name buffer-file-name
897-
rootdir)))
905+
relname (let ((file (diff-hl--buffer-file-name)))
906+
(when file
907+
(file-relative-name file rootdir))))
898908
(error "Directory is not version controlled"))
899909
(setq fileset (or fileset (vc-deduce-fileset)))
900910
(vc-buffer-sync-fileset fileset t)
@@ -909,7 +919,7 @@ buffer will show the position corresponding to its current line."
909919
(setq vc-sentinel-movepoint (point))))))))
910920

911921
(defun diff-hl-diff-read-revisions (rev1-default)
912-
(let* ((file buffer-file-name)
922+
(let* ((file (diff-hl--buffer-file-name))
913923
(files (list file))
914924
(backend (vc-backend file))
915925
(rev2-default nil))
@@ -1009,7 +1019,7 @@ that file, if it's present."
10091019
(line (save-excursion
10101020
(diff-hl-find-current-hunk)
10111021
(line-number-at-pos)))
1012-
(file buffer-file-name)
1022+
(file (diff-hl--buffer-file-name))
10131023
(backend (vc-backend file)))
10141024
(unwind-protect
10151025
(progn
@@ -1145,7 +1155,7 @@ its end position."
11451155
(push-mark (overlay-end hunk) nil t)))
11461156

11471157
(defun diff-hl--ensure-staging-supported ()
1148-
(let ((backend (vc-backend buffer-file-name)))
1158+
(let ((backend (vc-backend (diff-hl--buffer-file-name))))
11491159
(unless (eq backend 'Git)
11501160
(user-error "Only Git supports staging; this file is controlled by %s" backend))))
11511161

@@ -1172,7 +1182,7 @@ Only supported with Git."
11721182
(diff-hl--ensure-staging-supported)
11731183
(diff-hl-find-current-hunk)
11741184
(let* ((line (line-number-at-pos))
1175-
(file buffer-file-name)
1185+
(file (diff-hl--buffer-file-name))
11761186
(dest-buffer (get-buffer-create " *diff-hl-stage*"))
11771187
(orig-buffer (current-buffer))
11781188
;; FIXME: If the file name has double quotes, these need to be quoted.
@@ -1213,13 +1223,14 @@ Only supported with Git."
12131223
12141224
Only supported with Git."
12151225
(interactive)
1216-
(unless buffer-file-name
1217-
(user-error "No current file"))
1218-
(diff-hl--ensure-staging-supported)
1219-
(vc-git-command nil 0 buffer-file-name "reset")
1220-
(message "Unstaged all")
1221-
(unless diff-hl-show-staged-changes
1222-
(diff-hl-update)))
1226+
(let ((file (diff-hl--buffer-file-name)))
1227+
(unless file
1228+
(user-error "No current file"))
1229+
(diff-hl--ensure-staging-supported)
1230+
(vc-git-command nil 0 file "reset")
1231+
(message "Unstaged all")
1232+
(unless diff-hl-show-staged-changes
1233+
(diff-hl-update))))
12231234

12241235
(defun diff-hl-stage-dwim (&optional with-edit)
12251236
"Stage the current hunk or choose the hunks to stage.
@@ -1246,7 +1257,7 @@ Pops up a diff buffer that can be edited to choose the changes to stage."
12461257
(diff-hl--ensure-staging-supported)
12471258
(let* ((line-beg (and beg (line-number-at-pos beg t)))
12481259
(line-end (and end (line-number-at-pos end t)))
1249-
(file buffer-file-name)
1260+
(file (diff-hl--buffer-file-name))
12501261
(dest-buffer (get-buffer-create "*diff-hl-stage-some*"))
12511262
(orig-buffer (current-buffer))
12521263
(diff-hl-update-async nil)
@@ -1424,26 +1435,26 @@ The value of this variable is a mode line template as in
14241435
(magit-git-items "diff-tree" "-z" "--name-only" "-r" "HEAD~" "HEAD"))
14251436
(unmodified-states '(up-to-date ignored unregistered)))
14261437
(dolist (buf (buffer-list))
1427-
(when (and (buffer-local-value 'diff-hl-mode buf)
1428-
(not (buffer-modified-p buf))
1429-
;; Solve the "cloned indirect buffer" problem
1430-
;; (diff-hl-mode could be non-nil there, even if
1431-
;; buffer-file-name is nil):
1432-
(buffer-file-name buf)
1433-
(file-in-directory-p (buffer-file-name buf) topdir)
1434-
(file-exists-p (buffer-file-name buf)))
1435-
(with-current-buffer buf
1436-
(let* ((file buffer-file-name)
1437-
(backend (vc-backend file)))
1438-
(when backend
1439-
(cond
1440-
((member file modified-files)
1441-
(when (memq (vc-state file) unmodified-states)
1442-
(vc-state-refresh file backend))
1443-
(diff-hl-update))
1444-
((not (memq (vc-state file backend) unmodified-states))
1445-
(vc-state-refresh file backend)
1446-
(diff-hl-update)))))))))))
1438+
(let ((file (diff-hl--buffer-file-name buf)))
1439+
(when (and (buffer-local-value 'diff-hl-mode buf)
1440+
(not (buffer-modified-p buf))
1441+
;; Solve the "cloned indirect buffer" problem
1442+
;; (diff-hl-mode could be non-nil there, even if
1443+
;; buffer-file-name is nil):
1444+
file
1445+
(file-in-directory-p file topdir)
1446+
(file-exists-p file))
1447+
(with-current-buffer buf
1448+
(let* ((backend (vc-backend file)))
1449+
(when backend
1450+
(cond
1451+
((member file modified-files)
1452+
(when (memq (vc-state file) unmodified-states)
1453+
(vc-state-refresh file backend))
1454+
(diff-hl-update))
1455+
((not (memq (vc-state file backend) unmodified-states))
1456+
(vc-state-refresh file backend)
1457+
(diff-hl-update))))))))))))
14471458

14481459
(defun diff-hl-dir-update ()
14491460
(dolist (pair (if (vc-dir-marked-files)
@@ -1536,7 +1547,7 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0."
15361547
backend
15371548
(or diff-hl-reference-revision
15381549
(assoc-default backend diff-hl-head-revision-alist)))
1539-
(diff-hl-working-revision buffer-file-name backend)))))
1550+
(diff-hl-working-revision (diff-hl--buffer-file-name) backend)))))
15401551
(switches (format "-U %d --strip-trailing-cr" (or context-lines 0))))
15411552
(diff-no-select rev (current-buffer) switches (not (diff-hl--use-async-p))
15421553
(get-buffer-create dest-buffer))
@@ -1604,13 +1615,14 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0."
16041615
;;;###autoload
16051616
(defun turn-on-diff-hl-mode ()
16061617
"Turn on `diff-hl-mode' or `diff-hl-dir-mode' in a buffer if appropriate."
1607-
(cond
1608-
(buffer-file-name
1609-
(unless (and diff-hl-disable-on-remote
1610-
(file-remote-p buffer-file-name))
1611-
(diff-hl-mode 1)))
1612-
((eq major-mode 'vc-dir-mode)
1613-
(diff-hl-dir-mode 1))))
1618+
(let ((file (diff-hl--buffer-file-name)))
1619+
(cond
1620+
(file
1621+
(unless (and diff-hl-disable-on-remote
1622+
(file-remote-p file))
1623+
(diff-hl-mode 1)))
1624+
((eq major-mode 'vc-dir-mode)
1625+
(diff-hl-dir-mode 1)))))
16141626

16151627
;;;###autoload
16161628
(defun diff-hl--global-turn-on ()

test/diff-hl-test.el

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@
5050
(erase-buffer)
5151
(insert diff-hl-test-initial-content)
5252
(save-buffer)
53-
(pcase (vc-backend buffer-file-name)
53+
(pcase (vc-backend (diff-hl--buffer-file-name))
5454
(`Git
55-
(vc-git-command nil 0 buffer-file-name "reset"))
55+
(vc-git-command nil 0 (diff-hl--buffer-file-name) "reset"))
5656
(`Hg
57-
(vc-hg-command nil 0 buffer-file-name "revert")))))
57+
(vc-hg-command nil 0 (diff-hl--buffer-file-name) "revert")))))
5858

5959
(defun diff-hl-test-compute-diff-lines ()
6060
(diff-hl-test-in-source
@@ -160,7 +160,7 @@
160160
(goto-char (point-min))
161161
(insert "new line 1\n")
162162
(save-buffer)
163-
(vc-git-command nil 0 buffer-file-name "add")
163+
(vc-git-command nil 0 (diff-hl--buffer-file-name) "add")
164164
(goto-char (point-max))
165165
(insert "new line 2\n")
166166
(save-buffer)
@@ -180,19 +180,19 @@
180180
(goto-char (point-min))
181181
(insert "new line 1\n")
182182
(save-buffer)
183-
(vc-git-command nil 0 buffer-file-name "add")
183+
(vc-git-command nil 0 (diff-hl--buffer-file-name) "add")
184184
(goto-char (point-max))
185185
(insert "new line 2\n")
186186
(let ((diff-hl-show-staged-changes t))
187187
(should
188188
(equal (diff-hl-changes-from-buffer
189-
(diff-hl-diff-buffer-with-reference buffer-file-name))
189+
(diff-hl-diff-buffer-with-reference (diff-hl--buffer-file-name)))
190190
'((1 1 0 insert)
191191
(12 1 0 insert)))))
192192
(let ((diff-hl-show-staged-changes nil))
193193
(should
194194
(equal (diff-hl-changes-from-buffer
195-
(diff-hl-diff-buffer-with-reference buffer-file-name))
195+
(diff-hl-diff-buffer-with-reference (diff-hl--buffer-file-name)))
196196
'((12 1 0 insert)))))))
197197

198198
(diff-hl-deftest diff-hl-can-split-away-no-trailing-newline ()
@@ -202,7 +202,7 @@
202202
(search-backward "}")
203203
(insert " ")
204204
(save-buffer)
205-
(let ((file buffer-file-name)
205+
(let ((file (diff-hl--buffer-file-name))
206206
(dest-buffer (get-buffer-create " *diff-hl-test*")))
207207
(diff-hl-diff-buffer-with-reference file dest-buffer nil 3)
208208
(with-current-buffer dest-buffer

0 commit comments

Comments
 (0)