24 |
;;; Commentary: |
;;; Commentary: |
25 |
|
|
26 |
;;; Code: |
;;; Code: |
27 |
|
|
28 |
(provide 'ediff-ptch) |
(provide 'ediff-ptch) |
29 |
|
|
30 |
(defgroup ediff-ptch nil |
(defgroup ediff-ptch nil |
76 |
(defconst ediff-default-backup-extension |
(defconst ediff-default-backup-extension |
77 |
(if (memq system-type '(vax-vms axp-vms emx ms-dos)) |
(if (memq system-type '(vax-vms axp-vms emx ms-dos)) |
78 |
"_orig" ".orig")) |
"_orig" ".orig")) |
79 |
|
|
80 |
|
|
81 |
(defcustom ediff-backup-extension ediff-default-backup-extension |
(defcustom ediff-backup-extension ediff-default-backup-extension |
82 |
"Backup extension used by the patch program. |
"Backup extension used by the patch program. |
85 |
:group 'ediff-ptch) |
:group 'ediff-ptch) |
86 |
|
|
87 |
(defun ediff-test-patch-utility () |
(defun ediff-test-patch-utility () |
88 |
(cond ((zerop (call-process ediff-patch-program nil nil nil "-z." "-b")) |
(condition-case nil |
89 |
;; GNU `patch' v. >= 2.2 |
(cond ((zerop (call-process ediff-patch-program nil nil nil "-z." "-b")) |
90 |
'gnu) |
;; GNU `patch' v. >= 2.2 |
91 |
((zerop (call-process ediff-patch-program nil nil nil "-b")) |
'gnu) |
92 |
'posix) |
((zerop (call-process ediff-patch-program nil nil nil "-b")) |
93 |
(t 'traditional))) |
'posix) |
94 |
|
(t 'traditional)) |
95 |
|
(file-error nil))) |
96 |
|
|
97 |
(defcustom ediff-backup-specs |
(defcustom ediff-backup-specs |
98 |
(let ((type (ediff-test-patch-utility))) |
(let ((type (ediff-test-patch-utility))) |
99 |
(cond ((eq type 'gnu) |
(cond ((eq type 'gnu) |
100 |
;; GNU `patch' v. >= 2.2 |
;; GNU `patch' v. >= 2.2 |
184 |
(setq count (1+ count))))) |
(setq count (1+ count))))) |
185 |
count))) |
count))) |
186 |
|
|
187 |
;; Scan BUF (which is supposed to contain a patch) and make a list of the form |
;; Scan BUF (which is supposed to contain a patch) and make a list of the form |
188 |
;; ((nil nil filename-spec1 marker1 marker2) |
;; ((nil nil filename-spec1 marker1 marker2) |
189 |
;; (nil nil filename-spec2 marker1 marker2) ...) |
;; (nil nil filename-spec2 marker1 marker2) ...) |
190 |
;; where filename-spec[12] are files to which the `patch' program would |
;; where filename-spec[12] are files to which the `patch' program would |
191 |
;; have applied the patch. |
;; have applied the patch. |
192 |
;; nin, nil are placeholders. See ediff-make-new-meta-list-element in |
;; nin, nil are placeholders. See ediff-make-new-meta-list-element in |
193 |
;; ediff-meta.el for the explanations. |
;; ediff-meta.el for the explanations. |
240 |
(move-marker mark2 (match-beginning 0))) |
(move-marker mark2 (match-beginning 0))) |
241 |
|
|
242 |
(goto-char mark2-end) |
(goto-char mark2-end) |
243 |
|
|
244 |
(if filenames |
(if filenames |
245 |
(setq patch-map |
(setq patch-map |
246 |
(cons (ediff-make-new-meta-list-element |
(cons (ediff-make-new-meta-list-element |
274 |
;; directory part of filename |
;; directory part of filename |
275 |
(file-name-as-directory filename) |
(file-name-as-directory filename) |
276 |
(file-name-directory filename))) |
(file-name-directory filename))) |
277 |
;; Filename-spec is objA; at this point it is represented as |
;; Filename-spec is objA; at this point it is represented as |
278 |
;; (file1 . file2). We get it using ediff-get-session-objA |
;; (file1 . file2). We get it using ediff-get-session-objA |
279 |
;; directory part of the first file in the patch |
;; directory part of the first file in the patch |
280 |
(base-dir1 (file-name-directory |
(base-dir1 (file-name-directory |
349 |
(setcar (ediff-get-session-objA session-info) |
(setcar (ediff-get-session-objA session-info) |
350 |
(cons user-file user-file)))) |
(cons user-file user-file)))) |
351 |
(setcar proposed-file-names |
(setcar proposed-file-names |
352 |
(expand-file-name |
(expand-file-name |
353 |
(concat actual-dir (car proposed-file-names)))) |
(concat actual-dir (car proposed-file-names)))) |
354 |
(setcdr proposed-file-names |
(setcdr proposed-file-names |
355 |
(expand-file-name |
(expand-file-name |
356 |
(concat actual-dir (cdr proposed-file-names))))) |
(concat actual-dir (cdr proposed-file-names))))) |
357 |
)) |
)) |
358 |
ediff-patch-map) |
ediff-patch-map) |
418 |
(let ((directory t) |
(let ((directory t) |
419 |
target) |
target) |
420 |
(while directory |
(while directory |
421 |
(setq target (read-file-name |
(setq target (read-file-name |
422 |
"Please enter a patch target: " |
"Please enter a patch target: " |
423 |
actual-dir actual-dir t)) |
actual-dir actual-dir t)) |
424 |
(if (not (file-directory-p target)) |
(if (not (file-directory-p target)) |
502 |
(if (y-or-n-p "Is the patch already in a buffer? ") |
(if (y-or-n-p "Is the patch already in a buffer? ") |
503 |
(ediff-prompt-for-patch-buffer) |
(ediff-prompt-for-patch-buffer) |
504 |
(ediff-prompt-for-patch-file))))) |
(ediff-prompt-for-patch-file))))) |
505 |
|
|
506 |
(ediff-with-current-buffer patch-buf |
(ediff-with-current-buffer patch-buf |
507 |
(goto-char (point-min)) |
(goto-char (point-min)) |
508 |
(or (ediff-get-visible-buffer-window patch-buf) |
(or (ediff-get-visible-buffer-window patch-buf) |
529 |
"^/dev/null" |
"^/dev/null" |
530 |
;; this is the file to patch |
;; this is the file to patch |
531 |
(ediff-get-session-objA-name (car ediff-patch-map)))) |
(ediff-get-session-objA-name (car ediff-patch-map)))) |
532 |
(> (length |
(> (length |
533 |
(ediff-get-session-objA-name (car ediff-patch-map))) |
(ediff-get-session-objA-name (car ediff-patch-map))) |
534 |
1)) |
1)) |
535 |
(ediff-get-session-objA-name (car ediff-patch-map)) |
(ediff-get-session-objA-name (car ediff-patch-map)) |
571 |
(set-visited-file-modtime) ; sync buffer and temp file |
(set-visited-file-modtime) ; sync buffer and temp file |
572 |
(setq default-directory default-dir) |
(setq default-directory default-dir) |
573 |
) |
) |
574 |
|
|
575 |
;; dispatch a patch function |
;; dispatch a patch function |
576 |
(setq ctl-buf (ediff-dispatch-file-patching-job |
(setq ctl-buf (ediff-dispatch-file-patching-job |
577 |
patch-buf file-name startup-hooks)) |
patch-buf file-name startup-hooks)) |
578 |
|
|
579 |
(ediff-with-current-buffer ctl-buf |
(ediff-with-current-buffer ctl-buf |
580 |
(delete-file (buffer-file-name ediff-buffer-A)) |
(delete-file (buffer-file-name ediff-buffer-A)) |
581 |
(delete-file (buffer-file-name ediff-buffer-B)) |
(delete-file (buffer-file-name ediff-buffer-B)) |
588 |
(setq buffer-auto-save-file-name nil) ; don't create auto-save file |
(setq buffer-auto-save-file-name nil) ; don't create auto-save file |
589 |
(if default-dir (setq default-directory default-dir)) |
(if default-dir (setq default-directory default-dir)) |
590 |
(set-visited-file-name nil) |
(set-visited-file-name nil) |
591 |
(rename-buffer (ediff-unique-buffer-name |
(rename-buffer (ediff-unique-buffer-name |
592 |
(concat buf-to-patch-name "_patched") "")) |
(concat buf-to-patch-name "_patched") "")) |
593 |
(set-buffer-modified-p t))) |
(set-buffer-modified-p t))) |
594 |
)) |
)) |
607 |
(defun ediff-patch-file-internal (patch-buf source-filename |
(defun ediff-patch-file-internal (patch-buf source-filename |
608 |
&optional startup-hooks) |
&optional startup-hooks) |
609 |
(setq source-filename (expand-file-name source-filename)) |
(setq source-filename (expand-file-name source-filename)) |
610 |
|
|
611 |
(let* ((shell-file-name ediff-shell) |
(let* ((shell-file-name ediff-shell) |
612 |
(patch-diagnostics (get-buffer-create "*ediff patch diagnostics*")) |
(patch-diagnostics (get-buffer-create "*ediff patch diagnostics*")) |
613 |
;; ediff-find-file may use a temp file to do the patch |
;; ediff-find-file may use a temp file to do the patch |
618 |
(target-filename source-filename) |
(target-filename source-filename) |
619 |
;; this ensures that the patch process gets patch buffer in the |
;; this ensures that the patch process gets patch buffer in the |
620 |
;; encoding that Emacs thinks is right for that type of text |
;; encoding that Emacs thinks is right for that type of text |
621 |
(coding-system-for-write |
(coding-system-for-write |
622 |
(if (boundp 'buffer-file-coding-system) buffer-file-coding-system)) |
(if (boundp 'buffer-file-coding-system) buffer-file-coding-system)) |
623 |
target-buf buf-to-patch file-name-magic-p |
target-buf buf-to-patch file-name-magic-p |
624 |
patch-return-code ctl-buf backup-style aux-wind) |
patch-return-code ctl-buf backup-style aux-wind) |
625 |
|
|
626 |
(if (string-match "V" ediff-patch-options) |
(if (string-match "V" ediff-patch-options) |
627 |
(error |
(error |
628 |
"Ediff doesn't take the -V option in `ediff-patch-options'--sorry")) |
"Ediff doesn't take the -V option in `ediff-patch-options'--sorry")) |
629 |
|
|
630 |
;; Make a temp file, if source-filename has a magic file handler (or if |
;; Make a temp file, if source-filename has a magic file handler (or if |
631 |
;; it is handled via auto-mode-alist and similar magic). |
;; it is handled via auto-mode-alist and similar magic). |
632 |
;; Check if there is a buffer visiting source-filename and if they are in |
;; Check if there is a buffer visiting source-filename and if they are in |
640 |
;; temporary file where we put the after-product of the file handler. |
;; temporary file where we put the after-product of the file handler. |
641 |
(setq file-name-magic-p (not (equal (file-truename true-source-filename) |
(setq file-name-magic-p (not (equal (file-truename true-source-filename) |
642 |
(file-truename source-filename)))) |
(file-truename source-filename)))) |
643 |
|
|
644 |
;; Checkout orig file, if necessary, so that the patched file |
;; Checkout orig file, if necessary, so that the patched file |
645 |
;; could be checked back in. |
;; could be checked back in. |
646 |
(ediff-maybe-checkout buf-to-patch) |
(ediff-maybe-checkout buf-to-patch) |
647 |
|
|
674 |
|
|
675 |
(switch-to-buffer patch-diagnostics) |
(switch-to-buffer patch-diagnostics) |
676 |
(sit-for 0) ; synchronize - let the user see diagnostics |
(sit-for 0) ; synchronize - let the user see diagnostics |
677 |
|
|
678 |
(or (and (ediff-patch-return-code-ok patch-return-code) |
(or (and (ediff-patch-return-code-ok patch-return-code) |
679 |
(file-exists-p |
(file-exists-p |
680 |
(concat true-source-filename ediff-backup-extension))) |
(concat true-source-filename ediff-backup-extension))) |
682 |
(with-output-to-temp-buffer ediff-msg-buffer |
(with-output-to-temp-buffer ediff-msg-buffer |
683 |
(ediff-with-current-buffer standard-output |
(ediff-with-current-buffer standard-output |
684 |
(fundamental-mode)) |
(fundamental-mode)) |
685 |
(princ (format |
(princ (format |
686 |
"Patch program has failed due to a bad patch file, |
"Patch program has failed due to a bad patch file, |
687 |
it couldn't apply all hunks, OR |
it couldn't apply all hunks, OR |
688 |
it couldn't create the backup for the file being patched. |
it couldn't create the backup for the file being patched. |
695 |
ediff-backup-extension = %S ediff-backup-specs = %S |
ediff-backup-extension = %S ediff-backup-specs = %S |
696 |
|
|
697 |
See Ediff on-line manual for more details on these variables. |
See Ediff on-line manual for more details on these variables. |
698 |
In particular, check the documentation for `ediff-backup-specs'. |
In particular, check the documentation for `ediff-backup-specs'. |
699 |
|
|
700 |
In any of the above cases, Ediff doesn't compare files automatically. |
In any of the above cases, Ediff doesn't compare files automatically. |
701 |
However, if the patch was applied partially and the backup file was created, |
However, if the patch was applied partially and the backup file was created, |
713 |
(goto-char (point-max)))) |
(goto-char (point-max)))) |
714 |
(switch-to-buffer-other-window patch-diagnostics) |
(switch-to-buffer-other-window patch-diagnostics) |
715 |
(error "Patch appears to have failed"))) |
(error "Patch appears to have failed"))) |
716 |
|
|
717 |
;; If black magic is involved, apply patch to a temp copy of the |
;; If black magic is involved, apply patch to a temp copy of the |
718 |
;; file. Otherwise, apply patch to the orig copy. If patch is applied |
;; file. Otherwise, apply patch to the orig copy. If patch is applied |
719 |
;; to temp copy, we name the result old-name_patched for local files |
;; to temp copy, we name the result old-name_patched for local files |
727 |
(set-visited-file-name |
(set-visited-file-name |
728 |
(concat source-filename ediff-backup-extension)) |
(concat source-filename ediff-backup-extension)) |
729 |
(set-buffer-modified-p nil)) |
(set-buffer-modified-p nil)) |
730 |
|
|
731 |
;; Black magic in effect. |
;; Black magic in effect. |
732 |
;; If orig file was remote, put the patched file in the temp directory. |
;; If orig file was remote, put the patched file in the temp directory. |
733 |
;; If orig file is local, put the patched file in the directory of |
;; If orig file is local, put the patched file in the directory of |
738 |
true-source-filename |
true-source-filename |
739 |
source-filename) |
source-filename) |
740 |
"_patched")) |
"_patched")) |
741 |
|
|
742 |
(rename-file true-source-filename target-filename t) |
(rename-file true-source-filename target-filename t) |
743 |
|
|
744 |
;; arrange that the temp copy of orig will be deleted |
;; arrange that the temp copy of orig will be deleted |
745 |
(rename-file (concat true-source-filename ediff-backup-extension) |
(rename-file (concat true-source-filename ediff-backup-extension) |
746 |
true-source-filename t)) |
true-source-filename t)) |
747 |
|
|
748 |
;; make orig buffer read-only |
;; make orig buffer read-only |
749 |
(setq startup-hooks |
(setq startup-hooks |
750 |
(cons 'ediff-set-read-only-in-buf-A startup-hooks)) |
(cons 'ediff-set-read-only-in-buf-A startup-hooks)) |
751 |
|
|
752 |
;; set up a buf for the patched file |
;; set up a buf for the patched file |
753 |
(setq target-buf (find-file-noselect target-filename)) |
(setq target-buf (find-file-noselect target-filename)) |
754 |
|
|
755 |
(setq ctl-buf |
(setq ctl-buf |
756 |
(ediff-buffers-internal |
(ediff-buffers-internal |
757 |
buf-to-patch target-buf nil |
buf-to-patch target-buf nil |
759 |
(ediff-with-current-buffer ctl-buf |
(ediff-with-current-buffer ctl-buf |
760 |
(setq ediff-patchbufer patch-buf |
(setq ediff-patchbufer patch-buf |
761 |
ediff-patch-diagnostics patch-diagnostics)) |
ediff-patch-diagnostics patch-diagnostics)) |
762 |
|
|
763 |
(bury-buffer patch-diagnostics) |
(bury-buffer patch-diagnostics) |
764 |
(message "Type `P', if you need to see patch diagnostics") |
(message "Type `P', if you need to see patch diagnostics") |
765 |
ctl-buf)) |
ctl-buf)) |
775 |
'ediff-patch-file-form-meta |
'ediff-patch-file-form-meta |
776 |
ediff-meta-patchbufer patch-buf) ) |
ediff-meta-patchbufer patch-buf) ) |
777 |
startup-hooks)) |
startup-hooks)) |
778 |
(setq meta-buf (ediff-prepare-meta-buffer |
(setq meta-buf (ediff-prepare-meta-buffer |
779 |
'ediff-filegroup-action |
'ediff-filegroup-action |
780 |
(ediff-with-current-buffer patch-buf |
(ediff-with-current-buffer patch-buf |
781 |
(cons (ediff-make-new-meta-list-header |
(cons (ediff-make-new-meta-list-header |
793 |
(ediff-show-meta-buffer meta-buf) |
(ediff-show-meta-buffer meta-buf) |
794 |
)) |
)) |
795 |
|
|
796 |
|
|
797 |
|
|
798 |
|
|
799 |
;;; Local Variables: |
;;; Local Variables: |
800 |
;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) |
;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) |