[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 2d139141a6c: Support file creation and deletion in diff-apply-hun
From: |
Dmitry Gutov |
Subject: |
master 2d139141a6c: Support file creation and deletion in diff-apply-hunk |
Date: |
Mon, 7 Oct 2024 19:26:05 -0400 (EDT) |
branch: master
commit 2d139141a6c249691a50ade9c8d08dc35fcdf456
Author: Dmitry Gutov <dmitry@gutov.dev>
Commit: Dmitry Gutov <dmitry@gutov.dev>
Support file creation and deletion in diff-apply-hunk
* lisp/vc/diff-mode.el (diff-find-file-name): Allow entering
non-existing file name when the corresponding hunk is of type
"create file" (bug#62731). Default to file name with deleted
prefix if diff-buffer-type is Git or Hg. Make sure not to add
such input to diff-remembered-files-alist, it would be hard to
change otherwise in case of typo.
(diff-setup-buffer-type):
Match against the diff header common to 'hg diff' output.
(diff-find-source-location): Look at the other source when the
buffer is applied in reverse.
(diff-apply-hunk): Delect file deletion and pass a different
argument to 'diff-find-source-location' in such case. Bind
diff-vc-backend to nil to avoid older revision buffer being
returned. In the end, offer to delete the file if the hunk was of
corresponding type and matched the existing contents.
* etc/NEWS: Mention the new capability.
---
etc/NEWS | 2 ++
lisp/vc/diff-mode.el | 37 +++++++++++++++++++++++++++++--------
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index b5104145878..d5f48ae4391 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -424,6 +424,8 @@ useful to prepare a *vc-diff* buffer for committing a
single hunk.
When the region is active, it deletes all hunks that the region does not
overlap.
+*** 'diff-apply-hunk' now supports creating and deleting files.
+
** php-ts-mode
---
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index d085c721bc8..cfa90d380ad 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1091,13 +1091,24 @@ PREFIX is only used internally: don't use it."
(diff-find-file-name old noprompt (match-string 1)))
;; if all else fails, ask the user
(unless noprompt
- (let ((file (expand-file-name (or (car fs) ""))))
+ (let ((file (or (car fs) ""))
+ (creation (equal null-device
+ (car (diff-hunk-file-names (not old))))))
+ (when (and (memq diff-buffer-type '(git hg))
+ (string-match "/" file))
+ ;; Strip the dst prefix (like b/) if diff is from Git/Hg.
+ (setq file (substring file (match-end 0))))
+ (setq file (expand-file-name file))
(setq file
(read-file-name (format "Use file %s: " file)
- (file-name-directory file) file t
+ (file-name-directory file) file
+ ;; Allow non-matching for creation.
+ (not creation)
(file-name-nondirectory file)))
- (setq-local diff-remembered-files-alist
- (cons (cons fs file) diff-remembered-files-alist))
+ (when (or (not creation) (file-exists-p file))
+ ;; Only remember files that exist. User might have mistyped.
+ (setq-local diff-remembered-files-alist
+ (cons (cons fs file) diff-remembered-files-alist)))
file)))))))
@@ -1647,7 +1658,9 @@ modified lines of the diff."
(setq-local diff-buffer-type
(if (re-search-forward "^diff --git" nil t)
'git
- nil)))
+ (if (re-search-forward "^diff -r.*-r" nil t)
+ 'hg
+ nil))))
(when (eq diff-buffer-type 'git)
(setq diff-outline-regexp
(concat "\\(^diff --git.*\\|" diff-hunk-header-re "\\)")))
@@ -1957,7 +1970,7 @@ SWITCHED is non-nil if the patch is already applied."
diff-context-mid-hunk-header-re nil t)
(error "Can't find the hunk separator"))
(match-string 1)))))
- (file (or (diff-find-file-name other noprompt)
+ (file (or (diff-find-file-name (xor other reverse) noprompt)
(error "Can't find the file")))
(revision (and other diff-vc-backend
(if reverse (nth 1 diff-vc-revisions)
@@ -2020,7 +2033,11 @@ the value of this variable when given an appropriate
prefix argument).
With a prefix argument, REVERSE the hunk."
(interactive "P")
(diff-beginning-of-hunk t)
- (pcase-let ((`(,buf ,line-offset ,pos ,old ,new ,switched)
+ (pcase-let* (;; Do not accept BUFFER.REV buffers as source location.
+ (diff-vc-backend nil)
+ ;; When we detect deletion, we will use the old file name.
+ (deletion (equal null-device (car (diff-hunk-file-names
reverse))))
+ (`(,buf ,line-offset ,pos ,old ,new ,switched)
;; Sometimes we'd like to have the following behavior: if
;; REVERSE go to the new file, otherwise go to the old.
;; But that means that by default we use the old file, which is
@@ -2030,7 +2047,7 @@ With a prefix argument, REVERSE the hunk."
;; TODO: make it possible to ask explicitly for this behavior.
;;
;; This is duplicated in diff-test-hunk.
- (diff-find-source-location nil reverse)))
+ (diff-find-source-location deletion reverse)))
(cond
((null line-offset)
(user-error "Can't find the text to patch"))
@@ -2056,6 +2073,10 @@ With a prefix argument, REVERSE the hunk."
"Hunk hasn't been applied yet; apply it now? "
"Hunk has already been applied; undo it? ")))))
(message "(Nothing done)"))
+ ((and deletion (not switched))
+ (when (y-or-n-p (format-message "Delete file `%s'?" (buffer-file-name
buf)))
+ (delete-file (buffer-file-name buf) delete-by-moving-to-trash)
+ (kill-buffer buf)))
(t
;; Apply the hunk
(with-current-buffer buf
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 2d139141a6c: Support file creation and deletion in diff-apply-hunk,
Dmitry Gutov <=