[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/diff-hl 4b860c5 1/2: Add new option: diff-hl-show-stage
From: |
ELPA Syncer |
Subject: |
[elpa] externals/diff-hl 4b860c5 1/2: Add new option: diff-hl-show-staged-changes |
Date: |
Mon, 5 Apr 2021 09:57:07 -0400 (EDT) |
branch: externals/diff-hl
commit 4b860c5ee571429dd0e3210fd50058a29988b98d
Author: Dmitry Gutov <dgutov@yandex.ru>
Commit: Dmitry Gutov <dgutov@yandex.ru>
Add new option: diff-hl-show-staged-changes
Resolves #161
---
diff-hl.el | 131 ++++++++++++++++++++++++++++++++++++---------------
test/diff-hl-test.el | 44 ++++++++++++++++-
2 files changed, 134 insertions(+), 41 deletions(-)
diff --git a/diff-hl.el b/diff-hl.el
index d643482..aa528bc 100644
--- a/diff-hl.el
+++ b/diff-hl.el
@@ -167,6 +167,11 @@ performance when viewing such files in certain conditions."
(repeat :inline t (symbol :tag "mode"))))
:group 'diff-hl)
+(defcustom diff-hl-show-staged-changes t
+ "Whether to include staged changes in the indicators.
+Only affects Git, it's the only backend that has staging area."
+ :type 'boolean)
+
(defvar diff-hl-reference-revision nil
"Revision to diff against. nil means the most recent one.")
@@ -279,22 +284,31 @@ performance when viewing such files in certain
conditions."
;; Diffing against an older revision.
diff-hl-reference-revision))))
+(declare-function vc-git-command "vc-git")
+
(defun diff-hl-changes-buffer (file backend)
- ;; FIXME: To diff against the staging area, call 'git diff-files -p'.
(let ((buf-name " *diff-hl* "))
- (condition-case err
+ (if (and (eq backend 'Git)
+ (not diff-hl-reference-revision)
+ (not diff-hl-show-staged-changes))
(diff-hl-with-diff-switches
- (vc-call-backend backend 'diff (list file)
- diff-hl-reference-revision nil
- buf-name))
- (error
- ;; https://github.com/dgutov/diff-hl/issues/117
- (when (string-match-p "\\`Failed (status 128)" (error-message-string
err))
- (diff-hl-with-diff-switches
- (vc-call-backend backend 'diff (list file)
- "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
- nil
- buf-name)))))
+ (apply #'vc-git-command buf-name 1
+ (list file)
+ "diff-files"
+ (cons "-p" (vc-switches 'git 'diff))))
+ (condition-case err
+ (diff-hl-with-diff-switches
+ (vc-call-backend backend 'diff (list file)
+ diff-hl-reference-revision nil
+ buf-name))
+ (error
+ ;; https://github.com/dgutov/diff-hl/issues/117
+ (when (string-match-p "\\`Failed (status 128)" (error-message-string
err))
+ (diff-hl-with-diff-switches
+ (vc-call-backend backend 'diff (list file)
+ "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
+ nil
+ buf-name))))))
buf-name))
(defun diff-hl-changes ()
@@ -304,33 +318,37 @@ performance when viewing such files in certain
conditions."
(let ((state (vc-state file backend)))
(cond
((diff-hl-modified-p state)
- (let* (diff-auto-refine-mode res)
- (with-current-buffer (diff-hl-changes-buffer file backend)
- (goto-char (point-min))
- (unless (eobp)
- (ignore-errors
- (diff-beginning-of-hunk t))
- (while (looking-at diff-hunk-header-re-unified)
- (let ((line (string-to-number (match-string 3)))
- (len (let ((m (match-string 4)))
- (if m (string-to-number m) 1)))
- (beg (point)))
- (diff-end-of-hunk)
- (let* ((inserts (diff-count-matches "^\\+" beg (point)))
- (deletes (diff-count-matches "^-" beg (point)))
- (type (cond ((zerop deletes) 'insert)
- ((zerop inserts) 'delete)
- (t 'change))))
- (when (eq type 'delete)
- (setq len 1)
- (cl-incf line))
- (push (list line len type) res))))))
- (nreverse res)))
+ (diff-hl-changes-from-buffer
+ (diff-hl-changes-buffer file backend)))
((eq state 'added)
`((1 ,(line-number-at-pos (point-max)) insert)))
((eq state 'removed)
`((1 ,(line-number-at-pos (point-max)) delete))))))))
+(defun diff-hl-changes-from-buffer (buf)
+ (with-current-buffer buf
+ (let* (diff-auto-refine-mode res)
+ (goto-char (point-min))
+ (unless (eobp)
+ (ignore-errors
+ (diff-beginning-of-hunk t))
+ (while (looking-at diff-hunk-header-re-unified)
+ (let ((line (string-to-number (match-string 3)))
+ (len (let ((m (match-string 4)))
+ (if m (string-to-number m) 1)))
+ (beg (point)))
+ (diff-end-of-hunk)
+ (let* ((inserts (diff-count-matches "^\\+" beg (point)))
+ (deletes (diff-count-matches "^-" beg (point)))
+ (type (cond ((zerop deletes) 'insert)
+ ((zerop inserts) 'delete)
+ (t 'change))))
+ (when (eq type 'delete)
+ (setq len 1)
+ (cl-incf line))
+ (push (list line len type) res)))))
+ (nreverse res))))
+
(defun diff-hl-update ()
(let ((changes (diff-hl-changes))
(current-line 1))
@@ -788,11 +806,17 @@ the `diff-program' to be in your `exec-path'."
(if (file-directory-p "/dev/shm/")
"/dev/shm/"
temporary-file-directory))
- (rev (diff-hl-create-revision
+ (rev
+ (if (and (eq backend 'Git)
+ (not diff-hl-reference-revision)
+ (not diff-hl-show-staged-changes))
+ (diff-hl-git-index-revision
file
- (or diff-hl-reference-revision
- (diff-hl-working-revision file backend)))))
- ;; FIXME: When against staging, do it differently!
+ (diff-hl-git-index-object-name file))
+ (diff-hl-create-revision
+ file
+ (or diff-hl-reference-revision
+ (diff-hl-working-revision file backend))))))
(diff-no-select rev (current-buffer) "-U 0 --strip-trailing-cr" 'noasync
(get-buffer-create dest-buffer))
(with-current-buffer dest-buffer
@@ -801,6 +825,35 @@ the `diff-program' to be in your `exec-path'."
(delete-matching-lines "^Diff finished.*")))
(get-buffer-create dest-buffer))))
+(defun diff-hl-git-index-object-name (file)
+ (with-temp-buffer
+ (vc-git-command (current-buffer) 0 file "ls-files" "-s")
+ (and
+ (goto-char (point-min))
+ (re-search-forward "^[0-9]+ \\([0-9a-f]+\\)")
+ (match-string-no-properties 1))))
+
+(defun diff-hl-git-index-revision (file object-name)
+ (let ((filename (diff-hl-make-temp-file-name file
+ (concat ":" object-name)
+ 'manual))
+ (filebuf (get-file-buffer file)))
+ (unless (file-exists-p filename)
+ (with-current-buffer filebuf
+ (let ((coding-system-for-read 'no-conversion)
+ (coding-system-for-write 'no-conversion))
+ (condition-case nil
+ (with-temp-file filename
+ (let ((outbuf (current-buffer)))
+ ;; Change buffer to be inside the repo.
+ (with-current-buffer filebuf
+ (vc-git-command outbuf 0 nil
+ "cat-file" "blob" object-name))))
+ (error
+ (when (file-exists-p filename)
+ (delete-file filename)))))))
+ filename))
+
;;;###autoload
(defun turn-on-diff-hl-mode ()
"Turn on `diff-hl-mode' or `diff-hl-dir-mode' in a buffer if appropriate."
diff --git a/test/diff-hl-test.el b/test/diff-hl-test.el
index b94c316..4b8563b 100644
--- a/test/diff-hl-test.el
+++ b/test/diff-hl-test.el
@@ -1,6 +1,6 @@
;;; diff-hl-test.el --- tests for diff-hl -*- lexical-binding: t -*-
-;; Copyright (C) 2020 Free Software Foundation, Inc.
+;; Copyright (C) 2020, 2021 Free Software Foundation, Inc.
;; Author: Nathan Moreau <nathan.moreau@m4x.org>
@@ -48,7 +48,8 @@
(diff-hl-test-in-source
(erase-buffer)
(insert diff-hl-test-initial-content)
- (save-buffer)))
+ (save-buffer)
+ (vc-git-command nil 0 buffer-file-name "reset")))
(defun diff-hl-test-compute-diff-lines ()
(diff-hl-test-in-source
@@ -120,6 +121,45 @@
(should (looking-at "added"))
(should-error (diff-hl-next-hunk) :type 'user-error)))
+(diff-hl-deftest diff-hl-can-ignore-staged-changes ()
+ (diff-hl-test-in-source
+ (goto-char (point-min))
+ (insert "new line 1\n")
+ (save-buffer)
+ (vc-git-command nil 0 buffer-file-name "add")
+ (goto-char (point-max))
+ (insert "new line 2\n")
+ (save-buffer)
+ (let ((diff-hl-show-staged-changes t))
+ (should
+ (equal (diff-hl-changes)
+ '((1 1 insert)
+ (12 1 insert)))))
+ (let ((diff-hl-show-staged-changes nil))
+ (should
+ (equal (diff-hl-changes)
+ '((12 1 insert)))))))
+
+(diff-hl-deftest diff-hl-flydiff-can-ignore-staged-changes ()
+ (diff-hl-test-in-source
+ (goto-char (point-min))
+ (insert "new line 1\n")
+ (save-buffer)
+ (vc-git-command nil 0 buffer-file-name "add")
+ (goto-char (point-max))
+ (insert "new line 2\n")
+ (let ((diff-hl-show-staged-changes t))
+ (should
+ (equal (diff-hl-changes-from-buffer
+ (diff-hl-diff-buffer-with-head buffer-file-name nil 'Git))
+ '((1 1 insert)
+ (12 1 insert)))))
+ (let ((diff-hl-show-staged-changes nil))
+ (should
+ (equal (diff-hl-changes-from-buffer
+ (diff-hl-diff-buffer-with-head buffer-file-name nil 'Git))
+ '((12 1 insert)))))))
+
(defun diff-hl-run-tests ()
(ert-run-tests-batch))