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"
		     ediff-patch-program
		     ediff-patch-options
		     ediff-backup-specs
		     (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))