("c" . stgit-diff-combined)
("m" . stgit-find-file-merge)
("o" . stgit-diff-ours)
+ ("r" . stgit-diff-range)
("t" . stgit-diff-theirs)))
(suppress-keymap toggle-map)
(mapc (lambda (arg) (define-key toggle-map (car arg) (cdr arg)))
"-"
["Show diff" stgit-diff
:active (get-text-property (point) 'entry-type)]
+ ["Show diff for range of applied patches" stgit-diff-range
+ :active (= (length stgit-marked-patches) 1)]
("Merge"
:active (stgit-git-index-unmerged-p)
["Combined diff" stgit-diff-combined
Commands for diffs:
\\[stgit-diff] Show diff of patch or file
+\\[stgit-diff-range] Show diff for range of patches
\\[stgit-diff-base] Show diff against the merge base
\\[stgit-diff-ours] Show diff against our branch
\\[stgit-diff-theirs] Show diff against their branch
(error "Cannot find commit id for %s" patchsym))
(match-string 1 result))))
+(defun stgit-whitespace-diff-arg (arg)
+ (when (numberp arg)
+ (cond ((> arg 4) "--ignore-all-space")
+ ((> arg 1) "--ignore-space-change"))))
+
(defun stgit-show-patch (unmerged-stage ignore-whitespace)
"Show the patch on the current line.
UNMERGED-STAGE is the argument to `git-diff' that that selects
which stage to diff against in the case of unmerged files."
- (let ((space-arg (when (numberp ignore-whitespace)
- (cond ((> ignore-whitespace 4)
- "--ignore-all-space")
- ((> ignore-whitespace 1)
- "--ignore-space-change"))))
+ (let ((space-arg (stgit-whitespace-diff-arg ignore-whitespace))
(patch-name (stgit-patch-name-at-point t)))
(stgit-capture-output "*StGit patch*"
(case (get-text-property (point) 'entry-type)
"--cc"
"show a combined diff")
+(defun stgit-diff-range (&optional ignore-whitespace)
+ "Show diff for the range of patches between point and the marked patch.
+
+With a prefix argument, ignore whitespace. With a prefix argument
+greater than four (e.g., \\[universal-argument] \
+\\[universal-argument] \\[stgit-diff-range]), ignore all whitespace."
+ (interactive "p")
+ (stgit-assert-mode)
+ (unless (= (length stgit-marked-patches) 1)
+ (error "Need exactly one patch marked"))
+ (let* ((patches (stgit-sort-patches (cons (stgit-patch-name-at-point t t)
+ stgit-marked-patches)
+ t))
+ (first-patch (car patches))
+ (second-patch (if (cdr patches) (cadr patches) first-patch))
+ (whitespace-arg (stgit-whitespace-diff-arg ignore-whitespace))
+ (applied (stgit-applied-patchsyms t)))
+ (unless (and (memq first-patch applied) (memq second-patch applied))
+ (error "Can only show diff range for applied patches"))
+ (stgit-capture-output (format "*StGit diff %s..%s*"
+ first-patch second-patch)
+ (apply 'stgit-run-git (append '("diff" "--patch-with-stat")
+ (and whitespace-arg (list whitespace-arg))
+ (list (format "%s^" (stgit-id first-patch))
+ (stgit-id second-patch))))
+ (with-current-buffer standard-output
+ (goto-char (point-min))
+ (diff-mode)))))
+
(defun stgit-move-change-to-index (file &optional force)
"Copies the work tree state of FILE to index, using git add or git rm.
(t (setq result :bottom)))))
result)))
-(defun stgit-sort-patches (patchsyms)
+(defun stgit-sort-patches (patchsyms &optional allow-duplicates)
"Returns the list of patches in PATCHSYMS sorted according to
their position in the patch series, bottommost first.
-PATCHSYMS must not contain duplicate entries."
+PATCHSYMS must not contain duplicate entries, unless
+ALLOW-DUPLICATES is not nil."
(let (sorted-patchsyms
(series (with-output-to-string
(with-current-buffer standard-output
(setq start (match-end 0)))
(setq sorted-patchsyms (nreverse sorted-patchsyms))
- (unless (= (length patchsyms) (length sorted-patchsyms))
- (error "Internal error"))
+ (unless allow-duplicates
+ (unless (= (length patchsyms) (length sorted-patchsyms))
+ (error "Internal error")))
sorted-patchsyms))