emacs-elpa-diffs
[Top][All Lists]
Advanced

[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))
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]