comparison lisp/ediff/ediff.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.el --- a comprehensive visual interface to diff & patch 1 ;;; ediff.el --- a comprehensive visual interface to diff & patch
2 2
3 ;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
4 4
5 ;; Author: Michael Kifer <kifer@cs.sunysb.edu> 5 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
6 ;; Created: February 2, 1994 6 ;; Created: February 2, 1994
7 ;; Keywords: comparing, merging, patching, version control. 7 ;; Keywords: comparing, merging, patching, version control.
8 8
9 (defconst ediff-version "2.64" "The current version of Ediff") 9 (defconst ediff-version "2.61" "The current version of Ediff")
10 (defconst ediff-date "January 7, 1997" "Date of last update") 10 (defconst ediff-date "June 10, 1996" "Date of last update")
11 11
12 12
13 ;; This file is part of GNU Emacs. 13 ;; This file is part of GNU Emacs.
14 14
15 ;; GNU Emacs is free software; you can redistribute it and/or modify 15 ;; GNU Emacs is free software; you can redistribute it and/or modify
104 ;; its many users. See Ediff on-line Info for the full list of those who 104 ;; its many users. See Ediff on-line Info for the full list of those who
105 ;; helped. Improved defaults in Ediff file-name reading commands. 105 ;; helped. Improved defaults in Ediff file-name reading commands.
106 106
107 ;;; Code: 107 ;;; Code:
108 108
109 (provide 'ediff) 109 (require 'ediff-init)
110 110 ;; ediff-mult is always required, because of the registry stuff
111 ;; Compiler pacifier 111 (require 'ediff-mult)
112 (and noninteractive 112
113 (eval-when-compile
114 (load-library "dired")
115 (load-library "info")
116 (load "pcl-cvs" 'noerror)))
117 (eval-when-compile 113 (eval-when-compile
118 (let ((load-path (cons (expand-file-name ".") load-path))) 114 (load "dired")
119 (or (featurep 'ediff-init) 115 (load-file "./ediff-ptch.el")
120 (load "ediff-init.el" nil nil 'nosuffix)) 116 (load-file "./ediff-vers.el")
121 (or (featurep 'ediff-mult) 117 (load "pcl-cvs" 'noerror))
122 (load "ediff-mult.el" nil nil 'nosuffix))
123 (or (featurep 'ediff-ptch)
124 (load "ediff-ptch.el" nil nil 'nosuffix))
125 (or (featurep 'ediff-vers)
126 (load "ediff-vers.el" nil nil 'nosuffix))
127 ))
128 ;; end pacifier
129
130 (require 'ediff-init)
131 (require 'ediff-mult) ; required because of the registry stuff
132 118
133 (defvar ediff-use-last-dir nil 119 (defvar ediff-use-last-dir nil
134 "*If t, Ediff uses previous directory as default when reading file name.") 120 "*If t, Ediff uses previous directory as default when reading file name.")
135 121
136 (defvar ediff-last-dir-A nil 122 (defvar ediff-last-dir-A nil
139 "Last directory used by an Ediff command for file-B.") 125 "Last directory used by an Ediff command for file-B.")
140 (defvar ediff-last-dir-C nil 126 (defvar ediff-last-dir-C nil
141 "Last directory used by an Ediff command for file-C.") 127 "Last directory used by an Ediff command for file-C.")
142 (defvar ediff-last-dir-ancestor nil 128 (defvar ediff-last-dir-ancestor nil
143 "Last directory used by an Ediff command for the ancestor file.") 129 "Last directory used by an Ediff command for the ancestor file.")
144 (defvar ediff-last-merge-autostore-dir
145 "Last directory used by an Ediff command as the output directory for merge.")
146 130
147 ;; Some defvars to reduce the number of compiler warnings 131 ;; Some defvars to reduce the number of compiler warnings
148 (defvar cvs-cookie-handle) 132 (defvar cvs-cookie-handle)
149 (defvar ediff-last-dir-patch) 133 (defvar ediff-last-dir-patch)
150 (defvar ediff-patch-default-directory) 134 (defvar ediff-patch-default-directory)
286 ;; Setup the buffer 270 ;; Setup the buffer
287 (set buffer-name (find-file-noselect file)) 271 (set buffer-name (find-file-noselect file))
288 272
289 (ediff-eval-in-buffer (symbol-value buffer-name) 273 (ediff-eval-in-buffer (symbol-value buffer-name)
290 (widen) ; Make sure the entire file is seen 274 (widen) ; Make sure the entire file is seen
291 (cond (file-magic ; file has a handler, such as jka-compr-handler or 275 (cond (file-magic ;; file has handler, such as jka-compr-handler or
292 ;;; ange-ftp-hook-function--arrange for temp file 276 ;; ange-ftp-hook-function--arrange for temp file
293 (ediff-verify-file-buffer 'magic) 277 (ediff-verify-file-buffer 'magic)
294 (setq file 278 (setq file
295 (ediff-make-temp-file 279 (ediff-make-temp-file
296 (current-buffer) temp-file-name-prefix)) 280 (current-buffer) temp-file-name-prefix))
297 (set hooks-var (cons (` (lambda () (delete-file (, file)))) 281 (set hooks-var (cons (` (lambda () (delete-file (, file))))
619 ;; Run ediff-action (ediff-files, ediff-merge, ediff-merge-with-ancestors) 603 ;; Run ediff-action (ediff-files, ediff-merge, ediff-merge-with-ancestors)
620 ;; on a pair of directories (three directories, in case of ancestor). 604 ;; on a pair of directories (three directories, in case of ancestor).
621 ;; The third argument, REGEXP, is a regular expression that can be used to 605 ;; The third argument, REGEXP, is a regular expression that can be used to
622 ;; filter out certain file names. 606 ;; filter out certain file names.
623 ;; JOBNAME is the symbol indicating the meta-job to be performed. 607 ;; JOBNAME is the symbol indicating the meta-job to be performed.
624 ;; MERGE-DIR is the directory in which to store merged files. 608 (defun ediff-directories-internal (dir1 dir2 dir3 regexp
625 (defun ediff-directories-internal (dir1 dir2 dir3 regexp action jobname 609 action jobname
626 &optional startup-hooks) 610 &optional startup-hooks)
627 ;; ediff-read-file-name is set to attach a previously entered file name if 611 ;; ediff-read-file-name is set to attach a previously entered file name if
628 ;; the currently entered file is a directory. This code takes care of that. 612 ;; the currently entered file is a directory. This code takes care of that.
629 (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1)) 613 (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1))
630 dir2 (if (file-directory-p dir2) dir2 (file-name-directory dir2))) 614 dir2 (if (file-directory-p dir2) dir2 (file-name-directory dir2)))
640 ((and (eq jobname 'ediff-directories3) 624 ((and (eq jobname 'ediff-directories3)
641 (string= dir2 dir3)) 625 (string= dir2 dir3))
642 (error "Directories B and C are the same: %s" dir1))) 626 (error "Directories B and C are the same: %s" dir1)))
643 627
644 (let (diffs ; var where ediff-intersect-directories returns the diff list 628 (let (diffs ; var where ediff-intersect-directories returns the diff list
645 merge-autostore-dir
646 file-list meta-buf) 629 file-list meta-buf)
647 (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
648 (setq merge-autostore-dir
649 (ediff-read-file-name "Directory to save merged files:"
650 (if ediff-use-last-dir
651 ediff-last-merge-autostore-dir
652 (ediff-strip-last-dir dir1))
653 nil)))
654 ;; verify we are not merging into an orig directory
655 (if (stringp merge-autostore-dir)
656 (cond ((and (stringp dir1) (string= merge-autostore-dir dir1))
657 (or (y-or-n-p "Merge directory same as directory A, sure? ")
658 (error "Directory merge aborted")))
659 ((and (stringp dir2) (string= merge-autostore-dir dir2))
660 (or (y-or-n-p "Merge directory same as directory B, sure? ")
661 (error "Directory merge aborted")))
662 ((and (stringp dir3) (string= merge-autostore-dir dir3))
663 (or (y-or-n-p
664 "Merge directory same as ancestor directory, sure? ")
665 (error "Directory merge aborted")))))
666
667 (setq file-list (ediff-intersect-directories 630 (setq file-list (ediff-intersect-directories
668 jobname 'diffs 631 jobname 'diffs regexp dir1 dir2 dir3))
669 regexp dir1 dir2 dir3 merge-autostore-dir))
670 (setq startup-hooks 632 (setq startup-hooks
671 ;; this sets various vars in the meta buffer inside 633 ;; this sets various vars in the meta buffer inside
672 ;; ediff-prepare-meta-buffer 634 ;; ediff-prepare-meta-buffer
673 (cons (` (lambda () 635 (cons (` (lambda ()
674 ;; tell what to do if the user clicks on a session record 636 ;; tell what to do if the user clicks on a session record
687 )) 649 ))
688 650
689 (defun ediff-directory-revisions-internal (dir1 regexp action jobname 651 (defun ediff-directory-revisions-internal (dir1 regexp action jobname
690 &optional startup-hooks) 652 &optional startup-hooks)
691 (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1))) 653 (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1)))
692 654 (let (file-list meta-buf)
693 (let (file-list meta-buf merge-autostore-dir)
694 (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
695 (setq merge-autostore-dir
696 (ediff-read-file-name "Directory to save merged files:"
697 (if ediff-use-last-dir
698 ediff-last-merge-autostore-dir
699 (ediff-strip-last-dir dir1))
700 nil)))
701 ;; verify merge-autostore-dir != dir1
702 (if (and (stringp merge-autostore-dir)
703 (stringp dir1)
704 (string= merge-autostore-dir dir1))
705 (or (y-or-n-p
706 "Directory for saving merges is the same as directory A. Sure? ")
707 (error "Merge of directory revisions aborted")))
708
709 (setq file-list 655 (setq file-list
710 (ediff-get-directory-files-under-revision 656 (ediff-get-directory-files-under-revision jobname regexp dir1))
711 jobname regexp dir1 merge-autostore-dir))
712 (setq startup-hooks 657 (setq startup-hooks
713 ;; this sets various vars in the meta buffer inside 658 ;; this sets various vars in the meta buffer inside
714 ;; ediff-prepare-meta-buffer 659 ;; ediff-prepare-meta-buffer
715 (cons (` (lambda () 660 (cons (` (lambda ()
716 ;; tell what to do if the user clicks on a session record 661 ;; tell what to do if the user clicks on a session record
857 802
858 (set-buffer buffer-B) 803 (set-buffer buffer-B)
859 (setq reg-B-beg (region-beginning) 804 (setq reg-B-beg (region-beginning)
860 reg-B-end (region-end)) 805 reg-B-end (region-end))
861 ;; enlarge the region to hold full lines 806 ;; enlarge the region to hold full lines
807 (goto-char reg-A-beg)
862 (goto-char reg-B-beg) 808 (goto-char reg-B-beg)
863 (beginning-of-line) 809 (beginning-of-line)
864 (setq reg-B-beg (point)) 810 (setq reg-B-beg (point))
865 (goto-char reg-B-end) 811 (goto-char reg-B-end)
866 (end-of-line) 812 (end-of-line)
1104 (if (stringp file) 1050 (if (stringp file)
1105 (file-name-nondirectory file) "current buffer")))) 1051 (file-name-nondirectory file) "current buffer"))))
1106 (ediff-load-version-control) 1052 (ediff-load-version-control)
1107 ;; ancestor-revision=nil 1053 ;; ancestor-revision=nil
1108 (funcall 1054 (funcall
1109 (intern (format "ediff-%S-merge-internal" ediff-version-control-package)) 1055 (intern (format "%S-ediff-merge-internal" ediff-version-control-package))
1110 rev1 rev2 nil startup-hooks))) 1056 rev1 rev2 nil startup-hooks)))
1111 1057
1112 1058
1113 ;;;###autoload 1059 ;;;###autoload
1114 (defun ediff-merge-revisions-with-ancestor (&optional file startup-hooks) 1060 (defun ediff-merge-revisions-with-ancestor (&optional file startup-hooks)
1115 "Run Ediff by merging two revisions of a file with a common ancestor. 1061 "Run Ediff by merging two revisions of a file with a common ancestor.
1116 The file is the the optional FILE argument or the file visited by the current 1062 The file is the optional FILE argument or the file visited by the current
1117 buffer." 1063 buffer."
1118 (interactive) 1064 (interactive)
1119 (if (stringp file) (find-file file)) 1065 (if (stringp file) (find-file file))
1120 (let (rev1 rev2 ancestor-rev) 1066 (let (rev1 rev2 ancestor-rev)
1121 (setq rev1 1067 (setq rev1
1136 "Ancestor version (default: %s): " 1082 "Ancestor version (default: %s): "
1137 (if (stringp file) 1083 (if (stringp file)
1138 (file-name-nondirectory file) "current buffer")))) 1084 (file-name-nondirectory file) "current buffer"))))
1139 (ediff-load-version-control) 1085 (ediff-load-version-control)
1140 (funcall 1086 (funcall
1141 (intern (format "ediff-%S-merge-internal" ediff-version-control-package)) 1087 (intern (format "%S-ediff-merge-internal" ediff-version-control-package))
1142 rev1 rev2 ancestor-rev startup-hooks))) 1088 rev1 rev2 ancestor-rev startup-hooks)))
1143 1089
1144 ;;;###autoload 1090 ;;;###autoload
1145 (defun run-ediff-from-cvs-buffer (pos) 1091 (defun run-ediff-from-cvs-buffer (pos)
1146 "Run Ediff-merge on appropriate revisions of the selected file. 1092 "Run Ediff-merge on appropriate revisions of the selected file.
1220 (format "Version 2 to compare (default: %s): " 1166 (format "Version 2 to compare (default: %s): "
1221 (if (stringp file) 1167 (if (stringp file)
1222 (file-name-nondirectory file) "current buffer")))) 1168 (file-name-nondirectory file) "current buffer"))))
1223 (ediff-load-version-control) 1169 (ediff-load-version-control)
1224 (funcall 1170 (funcall
1225 (intern (format "ediff-%S-internal" ediff-version-control-package)) 1171 (intern (format "%S-ediff-internal" ediff-version-control-package))
1226 rev1 rev2 startup-hooks) 1172 rev1 rev2 startup-hooks)
1227 )) 1173 ))
1228 1174
1229 1175
1230 ;; Test if version control package is loaded and load if not 1176 ;; Test if version control package is loaded and load if not
1250 (message (ediff-version)) 1196 (message (ediff-version))
1251 (format "Ediff %s of %s" ediff-version ediff-date))) 1197 (format "Ediff %s of %s" ediff-version ediff-date)))
1252 1198
1253 1199
1254 ;;;###autoload 1200 ;;;###autoload
1255 (defun ediff-documentation (&optional node) 1201 (defun ediff-documentation ()
1256 "Display Ediff's manual. 1202 "Display Ediff's manual."
1257 With optional NODE, goes to that node."
1258 (interactive) 1203 (interactive)
1259 (let ((ctl-window ediff-control-window) 1204 (let ((ctl-window ediff-control-window)
1260 (ctl-buf ediff-control-buffer)) 1205 (ctl-buf ediff-control-buffer))
1261 1206
1262 (ediff-skip-unsuitable-frames) 1207 (ediff-skip-unsuitable-frames)
1263 (condition-case nil 1208 (condition-case nil
1264 (progn 1209 (progn
1265 (pop-to-buffer (get-buffer-create "*info*")) 1210 (pop-to-buffer (get-buffer-create "*info*"))
1266 (info (if ediff-xemacs-p "ediff.info" "ediff")) 1211 (info (if ediff-xemacs-p "ediff.info" "ediff"))
1267 (if node 1212 (message "Type `i' to search for a specific topic"))
1268 (Info-goto-node node)
1269 (message "Type `i' to search for a specific topic"))
1270 (raise-frame (selected-frame)))
1271 (error (beep 1) 1213 (error (beep 1)
1272 (with-output-to-temp-buffer ediff-msg-buffer 1214 (with-output-to-temp-buffer ediff-msg-buffer
1273 (princ ediff-BAD-INFO)) 1215 (princ (format "
1216 The Info file for Ediff does not seem to be installed.
1217
1218 This file is part of the distribution of %sEmacs.
1219 Please contact your system administrator. "
1220 (if ediff-xemacs-p "X" ""))))
1274 (if (window-live-p ctl-window) 1221 (if (window-live-p ctl-window)
1275 (progn 1222 (progn
1276 (select-window ctl-window) 1223 (select-window ctl-window)
1277 (set-window-buffer ctl-window ctl-buf))))))) 1224 (set-window-buffer ctl-window ctl-buf)))))))
1278 1225
1280 1227
1281 1228
1282 ;;; Local Variables: 1229 ;;; Local Variables:
1283 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) 1230 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1284 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) 1231 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
1285 ;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body))
1286 ;;; End: 1232 ;;; End:
1287 1233
1234 (provide 'ediff)
1288 (require 'ediff-util) 1235 (require 'ediff-util)
1289 1236
1290 ;;; ediff.el ends here 1237 ;;; ediff.el ends here