Function: ediff-patch-file-internal
ediff-patch-file-internal is an autoloaded and byte-compiled function
defined in ediff-ptch.el.gz.
Signature
(ediff-patch-file-internal PATCH-BUF SOURCE-FILENAME &optional STARTUP-HOOKS)
Source Code
;; Defined in /usr/src/emacs/lisp/vc/ediff-ptch.el.gz
(defun ediff-patch-file-internal (patch-buf source-filename
&optional startup-hooks)
(setq source-filename (expand-file-name source-filename))
(let* ((shell-file-name ediff-shell)
(patch-diagnostics (get-buffer-create "*ediff patch diagnostics*"))
;; ediff-find-file may use a temp file to do the patch
;; so, we save source-filename and true-source-filename as a var
;; that initially is source-filename but may be changed to a temp
;; file for the purpose of patching.
(true-source-filename source-filename)
(target-filename source-filename)
;; this ensures that the patch process gets patch buffer in the
;; encoding that Emacs thinks is right for that type of text
(coding-system-for-write
(if (boundp 'buffer-file-coding-system) buffer-file-coding-system))
(ediff--startup-hook startup-hooks)
target-buf buf-to-patch magic-file-name
patch-return-code ctl-buf backup-style aux-wind)
(if (string-match-p "V" ediff-patch-options)
(error
"Ediff doesn't take the -V option in `ediff-patch-options'--sorry"))
;; Make a temp file, if source-filename has a magic file name handler (or if
;; it is handled via auto-mode-alist and similar magic).
;; Check if there is a buffer visiting source-filename and if they are in
;; sync; arrange for the deletion of temp file.
(setq buf-to-patch (ediff-find-file true-source-filename
'ediff-last-dir-patch))
(setq startup-hooks ediff--startup-hook)
;; Check if source file name has triggered black magic, such as file name
;; handlers or auto mode alist, and make a note of it.
(setq magic-file-name
(with-current-buffer buf-to-patch ediff--magic-file-name))
;; Checkout orig file, if necessary, so that the patched file
;; could be checked back in.
(ediff-maybe-checkout buf-to-patch)
(ediff-with-current-buffer patch-diagnostics
(insert-buffer-substring patch-buf)
(message "Applying patch ... ")
;; fix environment for gnu patch, so it won't make numbered extensions
(setq backup-style (getenv "VERSION_CONTROL"))
(setenv "VERSION_CONTROL" nil)
(setq patch-return-code
(call-process-region
(point-min) (point-max)
shell-file-name
t ; delete region (which contains the patch
t ; insert output (patch diagnostics) in current buffer
nil ; don't redisplay
shell-command-switch ; usually -c
(format "%s %s %s %s"
(shell-quote-argument ediff-patch-program)
ediff-patch-options
ediff-backup-specs
(shell-quote-argument
(ediff--buffer-file-name buf-to-patch)))
))
;; restore environment for gnu patch
(setenv "VERSION_CONTROL" backup-style))
(message "Applying patch ... done")
(message "")
(switch-to-buffer patch-diagnostics)
(sit-for 0) ; synchronize - let the user see diagnostics
(or (and (ediff-patch-return-code-ok patch-return-code)
(file-exists-p
(concat (ediff--buffer-file-name buf-to-patch)
ediff-backup-extension)))
(progn
(with-output-to-temp-buffer ediff-msg-buffer
(ediff-with-current-buffer standard-output
(fundamental-mode))
(princ (format-message
"Patch program has failed due to a bad patch file,
it couldn't apply all hunks, OR
it couldn't create the backup for the file being patched.
The former could be caused by a corrupt patch file or because the %S
program doesn't understand the format of the patch file in use.
The second problem might be due to an incompatibility among these settings:
ediff-patch-program = %S ediff-patch-options = %S
ediff-backup-extension = %S ediff-backup-specs = %S
See Ediff manual for more details on these variables.
In particular, check the documentation for `ediff-backup-specs'.
In any of the above cases, Ediff doesn't compare files automatically.
However, if the patch was applied partially and the backup file was created,
you can still examine the changes via M-x ediff-files"
ediff-patch-program
ediff-patch-program
ediff-patch-options
ediff-backup-extension
ediff-backup-specs
)))
(beep 1)
(if (setq aux-wind (get-buffer-window ediff-msg-buffer))
(progn
(select-window aux-wind)
(goto-char (point-max))))
(switch-to-buffer-other-window patch-diagnostics)
(user-error "Patch appears to have failed")))
;; If black magic is involved, apply patch to a temp copy of the
;; file. Otherwise, apply patch to the orig copy. If patch is applied
;; to temp copy, we name the result old-name_patched for local files
;; and temp-copy_patched for remote files. The orig file name isn't
;; changed, and the temp copy of the original is later deleted.
;; Without magic, the original file is renamed (usually into
;; old-name_orig) and the result of patching will have the same name as
;; the original.
(if (not magic-file-name)
(ediff-with-current-buffer buf-to-patch
(set-visited-file-name
(concat source-filename ediff-backup-extension))
(set-buffer-modified-p nil))
;; Black magic in effect.
;; If orig file was remote, put the patched file in the temp directory.
;; If orig file is local, put the patched file in the directory of
;; the orig file.
(setq target-filename
(concat
(if (file-remote-p (file-truename source-filename))
magic-file-name
source-filename)
"_patched"))
(rename-file magic-file-name target-filename t)
;; arrange that the temp copy of orig will be deleted
(rename-file (concat magic-file-name
ediff-backup-extension)
magic-file-name t))
;; make orig buffer read-only
(push #'ediff-set-read-only-in-buf-A startup-hooks)
;; set up a buf for the patched file
(setq target-buf (find-file-noselect target-filename))
(setq ctl-buf
(ediff-buffers-internal
buf-to-patch target-buf nil
startup-hooks 'epatch))
(ediff-with-current-buffer ctl-buf
(setq ediff-patchbufer patch-buf
ediff-patch-diagnostics patch-diagnostics))
(bury-buffer patch-diagnostics)
(message (substitute-command-keys
"Type \\`P', if you need to see patch diagnostics"))
ctl-buf))