Skip to content

Commit fcf504f

Browse files
committed
use diff-no-select
1 parent 36aa80b commit fcf504f

File tree

1 file changed

+64
-104
lines changed

1 file changed

+64
-104
lines changed

clang/tools/clang-format/clang-format.el

Lines changed: 64 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -160,55 +160,31 @@ is a zero-based file offset, assuming ‘utf-8-unix’ coding."
160160
(string-to-number (match-string 3 line)))))
161161
(concat (match-string 1 line) ":" (match-string 1 line)))))
162162

163-
(defun clang-format--vc-diff-get-diff-lines (file-orig file-new)
163+
(defun clang-format--vc-diff-compute-diff-and-get-lines (buf-orig buf-cur)
164164
"Return all line regions that contain diffs between FILE-ORIG and
165165
FILE-NEW. If there is no diff ‘nil’ is returned. Otherwise the
166166
return is a ‘list’ of lines in the format ‘--lines=<start>:<end>’
167167
which can be passed directly to ‘clang-format’."
168168
;; Use temporary buffer for output of diff.
169169
(with-temp-buffer
170-
(let ((status (call-process
171-
"diff"
172-
nil
173-
(current-buffer)
174-
nil
175-
;; Binary diff has different behaviors that we
176-
;; aren't interested in.
177-
"-a"
178-
;; Get minimal diff (copy diff config for git-clang-format).
179-
"-U0"
180-
file-orig
181-
file-new))
182-
(stderr (concat (if (zerop (buffer-size)) "" ": ")
170+
(diff-no-select buf-orig buf-cur "-a -U0" t (current-buffer))
171+
(let ((diff-lines '()))
172+
;; Iterate through all lines in diff buffer and collect all
173+
;; lines in current buffer that have a diff.
174+
(goto-char (point-min))
175+
(while (not (eobp))
176+
(let ((diff-line (clang-format--vc-diff-match-diff-line
183177
(buffer-substring-no-properties
184-
(point-min) (line-end-position))))
185-
(diff-lines '()))
186-
(cond
187-
((stringp status)
188-
(error "(diff killed by signal %s%s)" status stderr))
189-
;; Return of 0 indicates no diff.
190-
((= status 0) nil)
191-
;; Return of 1 indicates found diffs and no error.
192-
((= status 1)
193-
;; Iterate through all lines in diff buffer and collect all
194-
;; lines in current buffer that have a diff.
195-
(goto-char (point-min))
196-
(while (not (eobp))
197-
(let ((diff-line (clang-format--vc-diff-match-diff-line
198-
(buffer-substring-no-properties
199-
(line-beginning-position)
200-
(line-end-position)))))
201-
(when diff-line
202-
;; Create list line regions with diffs to pass to
203-
;; clang-format.
204-
(push (concat "--lines=" diff-line) diff-lines)))
205-
(forward-line 1))
206-
(reverse diff-lines))
207-
;; Any return != 0 && != 1 indicates some level of error.
208-
(t
209-
(error "(diff returned unsuccessfully %s%s)" status stderr))))))
210-
211-
(defun clang-format--vc-diff-get-vc-head-file (tmpfile-vc-head)
178+
(line-beginning-position)
179+
(line-end-position)))))
180+
(when diff-line
181+
;; Create list line regions with diffs to pass to
182+
;; clang-format.
183+
(push (concat "--lines=" diff-line) diff-lines)))
184+
(forward-line 1))
185+
(reverse diff-lines))))
186+
187+
(defun clang-format--vc-diff-get-diff-lines ()
212188
"Stores the contents of ‘buffer-file-name’ at vc revision HEAD into
213189
‘tmpfile-vc-head’. If the current buffer is either not a file or not
214190
in a vc repo, this results in an error. Currently git is the only
@@ -217,39 +193,44 @@ supported vc."
217193
(unless (buffer-file-name)
218194
(error "Buffer is not visiting a file"))
219195

220-
(let ((base-dir (vc-root-dir))
196+
(let ((inp-buf (current-buffer))
197+
(base-dir (vc-root-dir))
221198
(backend (vc-backend (buffer-file-name))))
222-
;; We need to be able to find version control (git) root.
223-
(unless base-dir
224-
(error "File not known to git"))
225-
(cond
226-
((string-equal backend "Git")
227-
;; Get the filename relative to git root.
228-
(let ((vc-file-name (substring
229-
(expand-file-name (buffer-file-name))
230-
(string-width (expand-file-name base-dir))
231-
nil)))
232-
(let ((status (call-process
233-
"git"
234-
nil
235-
`(:file, tmpfile-vc-head)
236-
nil
237-
"show" (concat "HEAD:" vc-file-name)))
238-
(stderr (with-temp-buffer
239-
(unless (zerop (cadr (insert-file-contents tmpfile-vc-head)))
240-
(insert ": "))
241-
(buffer-substring-no-properties
242-
(point-min) (line-end-position)))))
243-
(when (stringp status)
244-
(error "(git show HEAD:%s killed by signal %s%s)"
245-
vc-file-name status stderr))
246-
(unless (zerop status)
247-
(error "(git show HEAD:%s returned unsuccessfully %s%s)"
248-
vc-file-name status stderr)))))
249-
(t
250-
(error
251-
"Version control %s isn't supported, currently supported backends: git"
252-
backend)))))
199+
(with-temp-buffer
200+
;; We need to be able to find version control (git) root.
201+
(unless base-dir
202+
(error "File not known to version control system"))
203+
(cond
204+
((string-equal backend "Git")
205+
;; Get the filename relative to git root.
206+
(let ((vc-file-name (substring
207+
(expand-file-name (buffer-file-name inp-buf))
208+
(string-width (expand-file-name base-dir))
209+
nil)))
210+
(let ((status (call-process
211+
"git"
212+
nil
213+
(current-buffer)
214+
nil
215+
"show" (concat "HEAD:" vc-file-name)))
216+
(stderr (concat (if (zerop (buffer-size)) "" ": ")
217+
(buffer-substring-no-properties
218+
(point-min) (line-end-position)))))
219+
(when (stringp status)
220+
(error "(git show HEAD:%s killed by signal %s%s)"
221+
vc-file-name status stderr))
222+
(unless (zerop status)
223+
(error "(git show HEAD:%s returned unsuccessfully %s%s)"
224+
vc-file-name status stderr)))))
225+
(t
226+
(error
227+
"Version control %s isn't supported, currently supported backends: git"
228+
backend)))
229+
;; Collect all lines where inp-buf (buffer we call
230+
;; clang-format-vc-diff on) differs from latest version of the
231+
;; backing file in the version control system.
232+
(clang-format--vc-diff-compute-diff-and-get-lines
233+
(current-buffer) inp-buf))))
253234

254235

255236
(defun clang-format--region-impl (start end &optional style assume-file-name lines)
@@ -323,7 +304,6 @@ specific locations for reformatting (i.e diff locations)."
323304
(delete-file temp-file)
324305
(when (buffer-name temp-buffer) (kill-buffer temp-buffer)))))
325306

326-
327307
;;;###autoload
328308
(defun clang-format-vc-diff (&optional style assume-file-name)
329309
"The same as ‘clang-format-buffer’ but only operates on the vc
@@ -332,35 +312,15 @@ diffs from HEAD in the buffer. If no STYLE is given uses
332312
file. If no ASSUME-FILE-NAME is given uses the function
333313
‘buffer-file-name’."
334314
(interactive)
335-
(let ((tmpfile-vc-head nil)
336-
(tmpfile-curbuf nil))
337-
(unwind-protect
338-
(progn
339-
(setq tmpfile-vc-head
340-
(make-temp-file "clang-format-vc-tmp-head-content"))
341-
(clang-format--vc-diff-get-vc-head-file tmpfile-vc-head)
342-
;; Move the current buffer to a temporary file to take a
343-
;; diff. Even if current-buffer is backed by a file, we
344-
;; want to diff the buffer contents which might not be
345-
;; saved.
346-
(setq tmpfile-curbuf (make-temp-file "clang-format-vc-tmp"))
347-
(write-region nil nil tmpfile-curbuf nil 'nomessage)
348-
;; Get a list of lines with a diff.
349-
(let ((diff-lines
350-
(clang-format--vc-diff-get-diff-lines
351-
tmpfile-vc-head tmpfile-curbuf)))
352-
;; If we have any diffs, format them.
353-
(when diff-lines
354-
(clang-format--region-impl
355-
(point-min)
356-
(point-max)
357-
style
358-
assume-file-name
359-
diff-lines))))
360-
(progn
361-
;; Cleanup temporary files we created.
362-
(when tmpfile-vc-head (delete-file tmpfile-vc-head))
363-
(when tmpfile-curbuf (delete-file tmpfile-curbuf))))))
315+
(let ((diff-lines (clang-format--vc-diff-get-diff-lines)))
316+
;; If we have any diffs, format them.
317+
(when diff-lines
318+
(clang-format--region-impl
319+
(point-min)
320+
(point-max)
321+
style
322+
assume-file-name
323+
diff-lines))))
364324

365325

366326
;;;###autoload

0 commit comments

Comments
 (0)