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