mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
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.
This commit is contained in:
parent
9904376c79
commit
2d139141a6
2 changed files with 31 additions and 8 deletions
2
etc/NEWS
2
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
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue