Mercurial > hg > xemacs-beta
comparison lisp/ediff/ediff-ptch.el @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | 0293115a14e9 |
children | c7528f8e288d |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 ;;; ediff-ptch.el --- Ediff's patch support | 1 ;;; ediff-ptch.el --- Ediff's patch support |
2 | 2 |
3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1996 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Michael Kifer <kifer@cs.sunysb.edu> | 5 ;; Author: Michael Kifer <kifer@cs.sunysb.edu> |
6 | 6 |
7 ;; This file is part of GNU Emacs. | 7 ;; This file is part of GNU Emacs. |
8 | 8 |
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
22 ;; Boston, MA 02111-1307, USA. | 22 ;; Boston, MA 02111-1307, USA. |
23 | 23 |
24 | 24 |
25 ;;; Code: | 25 ;;; Code: |
26 | |
27 (provide 'ediff-ptch) | |
28 | |
29 ;; compiler pacifier | |
30 (defvar ediff-window-A) | |
31 (defvar ediff-window-B) | |
32 (defvar ediff-window-C) | |
33 (defvar ediff-use-last-dir) | |
34 (defvar ediff-shell) | |
35 | |
36 (eval-when-compile | |
37 (let ((load-path (cons (expand-file-name ".") load-path))) | |
38 (or (featurep 'ediff-init) | |
39 (load "ediff-init.el" nil nil 'nosuffix)) | |
40 (or (featurep 'ediff) | |
41 (load "ediff.el" nil nil 'nosuffix)) | |
42 )) | |
43 ;; end pacifier | |
44 | |
45 (require 'ediff-init) | |
46 | 26 |
47 (defvar ediff-last-dir-patch nil | 27 (defvar ediff-last-dir-patch nil |
48 "Last directory used by an Ediff command for file to patch.") | 28 "Last directory used by an Ediff command for file to patch.") |
49 | 29 |
50 (defvar ediff-backup-extension | 30 (defvar ediff-backup-extension |
51 (if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95)) | 31 (if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95)) |
52 "_orig" ".orig") | 32 "_orig" ".orig") |
53 "Backup extension used by the patch program. | 33 "Default backup extension for the patch program.") |
54 See also `ediff-backup-specs'.") | |
55 | |
56 (defvar ediff-backup-specs (format "-b %s" ediff-backup-extension) | |
57 "*Backup directives to pass to the patch program. | |
58 Ediff requires that the old version of the file \(before applying the patch\) | |
59 is saved in a file named `the-patch-file.extension'. Usually `extension' is | |
60 `.orig', but this can be changed by the user and may depend on the system. | |
61 Therefore, Ediff needs to know the backup extension used by the patch program. | |
62 | |
63 Some versions of the patch program let you specify `-b backup-extension'. | |
64 Other versions only permit `-b', which assumes some canned extension | |
65 \(usually `.orig'\). | |
66 | |
67 Note that both `ediff-backup-extension' and `ediff-backup-specs' | |
68 must be properly set. If your patch program takes the option `-b', | |
69 but not `-b extension', the variable `ediff-backup-extension' must | |
70 still be set so Ediff will know which extension to use.") | |
71 | |
72 | 34 |
73 (defvar ediff-patch-default-directory nil | 35 (defvar ediff-patch-default-directory nil |
74 "*Default directory to look for patches.") | 36 "*Default directory to look for patches.") |
75 | 37 |
76 (defvar ediff-context-diff-label-regexp | 38 (defvar ediff-context-diff-label-regexp |
77 (concat "\\(" ; context diff 2-liner | 39 (concat "\\(" ; context diff 2-liner |
78 "^\\*\\*\\* \\([^ \t]+\\)[^*]+[\t ]*\n--- \\([^ \t]+\\)" | 40 "^\\*\\*\\* \\([^ \t]+\\)[^*]+[\t ]*\n--- \\([^ \t]+\\)" |
79 "\\|" ; GNU unified format diff 2-liner | 41 "\\|" ; GNU unified format diff 2-liner |
80 "^--- \\([^ \t]+\\)[\t ]+.*\n\\+\\+\\+ \\([^ \t]+\\)" | 42 "^--- \\([^ \t]+\\)[^-]+[\t ]*\n\\+\\+\\+ \\([^ \t]+\\)" |
81 "\\)") | 43 "\\)") |
82 "*Regexp matching filename 2-liners at the start of each context diff.") | 44 "*Regexp matching filename 2-liners at the start of each context diff.") |
83 | 45 |
84 (defvar ediff-patch-program "patch" | 46 (defvar ediff-patch-program "patch" |
85 "*Name of the program that applies patches. | 47 "*Name of the program that applies patches.") |
86 It is recommended to use GNU-compatible versions.") | 48 (defvar ediff-patch-options "" |
87 (defvar ediff-patch-options "-f" | 49 "*Options to pass to ediff-patch-program.") |
88 "*Options to pass to ediff-patch-program. | |
89 | |
90 Note: the `-b' option should be specified in `ediff-backup-specs'. | |
91 | |
92 It is recommended to pass the `-f' option to the patch program, so it won't ask | |
93 questions. However, some implementations don't accept this option, in which | |
94 case the default value for this variable should be changed.") | |
95 | 50 |
96 ;; The buffer of the patch file. Local to control buffer. | 51 ;; The buffer of the patch file. Local to control buffer. |
97 (ediff-defvar-local ediff-patchbufer nil "") | 52 (ediff-defvar-local ediff-patchbufer nil "") |
98 | 53 |
99 ;; The buffer where patch displays its diagnostics. | 54 ;; The buffer where patch displays its diagnostics. |
153 (re-search-forward ediff-context-diff-label-regexp nil t)) | 108 (re-search-forward ediff-context-diff-label-regexp nil t)) |
154 (if (= opoint (point)) | 109 (if (= opoint (point)) |
155 (forward-char 1) ; ensure progress towards the end | 110 (forward-char 1) ; ensure progress towards the end |
156 (setq mark2 (move-marker (make-marker) (match-beginning 0)) | 111 (setq mark2 (move-marker (make-marker) (match-beginning 0)) |
157 mark2-end (match-end 0) | 112 mark2-end (match-end 0) |
158 beg1 (or (match-beginning 2) (match-beginning 4)) | 113 beg1 (match-beginning 2) |
159 end1 (or (match-end 2) (match-end 4)) | 114 end1 (match-end 2) |
160 beg2 (or (match-beginning 3) (match-beginning 5)) | 115 beg2 (match-beginning 3) |
161 end2 (or (match-end 3) (match-end 5))) | 116 end2 (match-end 3)) |
162 ;; possible-file-names is holding the new file names until we | 117 ;; possible-file-names is holding the new file names until we |
163 ;; insert the old file name in the patch map | 118 ;; insert the old file name in the patch map |
164 ;; It is a pair (filename from 1st header line . fn from 2nd line) | 119 ;; It is a pair (filename from 1st header line . fn from 2nd line) |
165 (setq possible-file-names | 120 (setq possible-file-names |
166 (cons (if (and beg1 end1) | 121 (cons (if (and beg1 end1) |
240 (progn | 195 (progn |
241 (with-output-to-temp-buffer ediff-msg-buffer | 196 (with-output-to-temp-buffer ediff-msg-buffer |
242 (princ | 197 (princ |
243 (format " | 198 (format " |
244 The patch file contains a context diff for | 199 The patch file contains a context diff for |
245 | |
246 %s | 200 %s |
247 %s | 201 %s |
248 | 202 |
249 However, Ediff cannot infer the name of the actual file | 203 However, Ediff cannot infer the name of the actual file |
250 to be patched on your system. If you know the correct file name, | 204 to be patched on your system. If you know the correct file name, |
362 (read-buffer | 316 (read-buffer |
363 "Which buffer contains the patch? " | 317 "Which buffer contains the patch? " |
364 (current-buffer) 'must-match))) | 318 (current-buffer) 'must-match))) |
365 (setq patch-buf | 319 (setq patch-buf |
366 (find-file-noselect | 320 (find-file-noselect |
367 (read-file-name "Which file contains the patch? " | 321 (read-file-name "Which file contains the patch? " dir)))) |
368 dir nil 'must-match)))) | |
369 | 322 |
370 (ediff-eval-in-buffer patch-buf | 323 (ediff-eval-in-buffer patch-buf |
371 (goto-char (point-min)) | 324 (goto-char (point-min)) |
372 (or (ediff-get-visible-buffer-window patch-buf) | 325 (or (ediff-get-visible-buffer-window patch-buf) |
373 (progn | 326 (progn |
449 | 402 |
450 (defun ediff-patch-file-internal (patch-buf source-filename | 403 (defun ediff-patch-file-internal (patch-buf source-filename |
451 &optional startup-hooks) | 404 &optional startup-hooks) |
452 (setq source-filename (expand-file-name source-filename)) | 405 (setq source-filename (expand-file-name source-filename)) |
453 | 406 |
454 (let* ((shell-file-name ediff-shell) | 407 (let* ((backup-extension |
408 ;; if the user specified a -b option, extract the backup | |
409 ;; extension from there; else use ediff-backup-extension | |
410 (substring ediff-patch-options | |
411 (if (string-match "-b[ \t]+" ediff-patch-options) | |
412 (match-end 0) 0) | |
413 (if (string-match "-b[ \t]+[^ \t]+" ediff-patch-options) | |
414 (match-end 0) 0))) | |
415 (shell-file-name ediff-shell) | |
455 (patch-diagnostics (get-buffer-create "*ediff patch diagnostics*")) | 416 (patch-diagnostics (get-buffer-create "*ediff patch diagnostics*")) |
456 ;; ediff-find-file may use a temp file to do the patch | 417 ;; ediff-find-file may use a temp file to do the patch |
457 ;; so, we save source-filename and true-source-filename as a var | 418 ;; so, we save source-filename and true-source-filename as a var |
458 ;; that initially is source-filename but may be changed to a temp | 419 ;; that initially is source-filename but may be changed to a temp |
459 ;; file for the purpose of patching. | 420 ;; file for the purpose of patching. |
460 (true-source-filename source-filename) | 421 (true-source-filename source-filename) |
461 (target-filename source-filename) | 422 (target-filename source-filename) |
462 target-buf buf-to-patch file-name-magic-p | 423 target-buf buf-to-patch file-name-magic-p ctl-buf backup-style) |
463 patch-return-code ctl-buf backup-style aux-wind) | |
464 | 424 |
425 ;; if the user didn't specify a backup extension, use | |
426 ;; ediff-backup-extension | |
427 (if (string= backup-extension "") | |
428 (setq backup-extension ediff-backup-extension)) | |
465 (if (string-match "-V" ediff-patch-options) | 429 (if (string-match "-V" ediff-patch-options) |
466 (error | 430 (error |
467 "Ediff doesn't take the -V option in `ediff-patch-options'--sorry")) | 431 "Ediff doesn't take the -V option in `ediff-patch-options'--sorry")) |
468 | 432 |
469 ;; Make a temp file, if source-filename has a magic file handler (or if | 433 ;; Make a temp file, if source-filename has a magic file handler (or if |
478 ;; true-source-filename should be either the original name or a | 442 ;; true-source-filename should be either the original name or a |
479 ;; temporary file where we put the after-product of the file handler. | 443 ;; temporary file where we put the after-product of the file handler. |
480 (setq file-name-magic-p (not (equal (file-truename true-source-filename) | 444 (setq file-name-magic-p (not (equal (file-truename true-source-filename) |
481 (file-truename source-filename)))) | 445 (file-truename source-filename)))) |
482 | 446 |
483 ;; Checkout orig file, if necessary, so that the patched file | 447 ;; Checkout orig file, if necessary, so that the patched file could be |
484 ;; could be checked back in. | 448 ;; checked back in. |
485 (ediff-maybe-checkout buf-to-patch) | 449 (if (ediff-file-checked-in-p (buffer-file-name buf-to-patch)) |
450 (ediff-toggle-read-only buf-to-patch)) | |
486 | 451 |
487 (ediff-eval-in-buffer patch-diagnostics | 452 (ediff-eval-in-buffer patch-diagnostics |
488 (insert-buffer patch-buf) | 453 (insert-buffer patch-buf) |
489 (message "Applying patch ... ") | 454 (message "Applying patch ... ") |
490 ;; fix environment for gnu patch, so it won't make numbered extensions | 455 ;; fix environment for gnu patch, so it won't make numbered extensions |
491 (setq backup-style (getenv "VERSION_CONTROL")) | 456 (setq backup-style (getenv "VERSION_CONTROL")) |
492 (setenv "VERSION_CONTROL" nil) | 457 (setenv "VERSION_CONTROL" nil) |
493 (setq patch-return-code | 458 ;; always pass patch the -f option, so it won't ask any questions |
494 (call-process-region | 459 (shell-command-on-region |
495 (point-min) (point-max) | 460 (point-min) (point-max) |
496 shell-file-name | 461 (format "%s -f %s -b %s %s" |
497 t ; delete region (which contains the patch | 462 ediff-patch-program ediff-patch-options |
498 t ; insert output (patch diagnostics) in current buffer | 463 backup-extension |
499 nil ; don't redisplay | 464 (expand-file-name true-source-filename)) |
500 shell-command-switch ; usually -c | 465 t) |
501 (format "%s %s %s %s" | |
502 ediff-patch-program | |
503 ediff-patch-options | |
504 ediff-backup-specs | |
505 (expand-file-name true-source-filename)) | |
506 )) | |
507 | |
508 ;; restore environment for gnu patch | 466 ;; restore environment for gnu patch |
509 (setenv "VERSION_CONTROL" backup-style)) | 467 (setenv "VERSION_CONTROL" backup-style)) |
510 | 468 |
511 (message "Applying patch ... done") | 469 (message "Applying patch ... done") |
512 (message "") | 470 (message "") |
513 | 471 |
514 (switch-to-buffer patch-diagnostics) | 472 (switch-to-buffer patch-diagnostics) |
515 (sit-for 0) ; synchronize - let the user see diagnostics | 473 (sit-for 0) ; synchronize - let the user see diagnostics |
516 | 474 |
517 (or (and (eq patch-return-code 0) ; patch reported success | 475 (or (file-exists-p (concat true-source-filename backup-extension)) |
518 (file-exists-p | 476 (error "Patch appears to have failed")) |
519 (concat true-source-filename ediff-backup-extension))) | 477 |
520 (progn | |
521 (with-output-to-temp-buffer ediff-msg-buffer | |
522 (princ (format " | |
523 Patch has failed OR the backup version of the patched file was not created by | |
524 the patch program. | |
525 | |
526 One reason may be that the values of the variables | |
527 | |
528 ediff-patch-options = %S | |
529 ediff-backup-extension = %S | |
530 ediff-backup-specs = %S | |
531 | |
532 are not appropriate for the program specified in the variable | |
533 | |
534 ediff-patch-program = %S | |
535 | |
536 Another reason could be that the %S program doesn't understand | |
537 the format of the patch file you used. | |
538 | |
539 See Ediff on-line manual for more details on these variables. | |
540 \(Or use a GNU-compatible patch program and stay out of trouble.\) | |
541 | |
542 Type any key to continue... | |
543 " | |
544 ediff-patch-options | |
545 ediff-backup-extension | |
546 ediff-backup-specs | |
547 ediff-patch-program | |
548 ediff-patch-program))) | |
549 (beep 1) | |
550 (if (setq aux-wind (get-buffer-window ediff-msg-buffer)) | |
551 (progn | |
552 (select-window aux-wind) | |
553 (goto-char (point-max)))) | |
554 (read-char-exclusive) | |
555 (if aux-wind (bury-buffer)) ; ediff-msg-buffer | |
556 (if (setq aux-wind (get-buffer-window patch-diagnostics)) | |
557 (progn | |
558 (select-window aux-wind) | |
559 (bury-buffer))) | |
560 (error "Patch appears to have failed"))) | |
561 | |
562 ;; If black magic is involved, apply patch to a temp copy of the | 478 ;; If black magic is involved, apply patch to a temp copy of the |
563 ;; file. Otherwise, apply patch to the orig copy. If patch is applied | 479 ;; file. Otherwise, apply patch to the orig copy. If patch is applied |
564 ;; to temp copy, we name the result old-name_patched for local files | 480 ;; to temp copy, we name the result old-name_patched for local files |
565 ;; and temp-copy_patched for remote files. The orig file name isn't | 481 ;; and temp-copy_patched for remote files. The orig file name isn't |
566 ;; changed, and the temp copy of the original is later deleted. | 482 ;; changed, and the temp copy of the original is later deleted. |
567 ;; Without magic, the original file is renamed (usually into | 483 ;; Without magic, the original file is renamed (usually into |
568 ;; old-name_orig) and the result of patching will have the same name as | 484 ;; old-name_orig) and the result of patching will have the same name as |
569 ;; the original. | 485 ;; the original. |
570 (if (not file-name-magic-p) | 486 (if (not file-name-magic-p) |
571 (ediff-eval-in-buffer buf-to-patch | 487 (ediff-eval-in-buffer buf-to-patch |
572 (set-visited-file-name | 488 (set-visited-file-name (concat source-filename backup-extension)) |
573 (concat source-filename ediff-backup-extension)) | |
574 (set-buffer-modified-p nil)) | 489 (set-buffer-modified-p nil)) |
575 | 490 |
576 ;; Black magic in effect. | 491 ;; Black magic in effect. |
577 ;; If orig file was remote, put the patched file in the temp directory. | 492 ;; If orig file was remote, put the patched file in the temp directory. |
578 ;; If orig file is local, put the patched file in the directory of | 493 ;; If orig file is local, put the patched file in the directory of |
585 "_patched")) | 500 "_patched")) |
586 | 501 |
587 (rename-file true-source-filename target-filename t) | 502 (rename-file true-source-filename target-filename t) |
588 | 503 |
589 ;; arrange that the temp copy of orig will be deleted | 504 ;; arrange that the temp copy of orig will be deleted |
590 (rename-file (concat true-source-filename ediff-backup-extension) | 505 (rename-file (concat true-source-filename backup-extension) |
591 true-source-filename t)) | 506 true-source-filename t)) |
592 | 507 |
593 ;; make orig buffer read-only | 508 ;; make orig buffer read-only |
594 (setq startup-hooks | 509 (setq startup-hooks |
595 (cons 'ediff-set-read-only-in-buf-A startup-hooks)) | 510 (cons 'ediff-set-read-only-in-buf-A startup-hooks)) |
638 | 553 |
639 | 554 |
640 ;;; Local Variables: | 555 ;;; Local Variables: |
641 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) | 556 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) |
642 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) | 557 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) |
643 ;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body)) | |
644 ;;; End: | 558 ;;; End: |
645 | 559 |
560 (provide 'ediff-ptch) | |
561 | |
646 ;;; ediff-ptch.el ends here | 562 ;;; ediff-ptch.el ends here |