From bd698e987e71743196eb0b317e8df3d39da228d9 Mon Sep 17 00:00:00 2001 From: Michael Kifer Date: Sat, 6 Sep 1997 04:16:05 +0000 Subject: [PATCH] new version --- lisp/ediff-diff.el | 14 +--- lisp/ediff-mult.el | 77 ++++++++++++------- lisp/ediff-ptch.el | 187 +++++++++++++++++++++++++++------------------ lisp/ediff-util.el | 42 ++++++---- lisp/ediff.el | 9 ++- 5 files changed, 200 insertions(+), 129 deletions(-) diff --git a/lisp/ediff-diff.el b/lisp/ediff-diff.el index 6a9bc8d51f8..fffd99a96ef 100644 --- a/lisp/ediff-diff.el +++ b/lisp/ediff-diff.el @@ -68,8 +68,7 @@ to a shell that you are not using or, better, fix your shell's startup file." "*Options to pass to `ediff-diff-program'. If diff\(1\) is used as `ediff-diff-program', then the most useful options are `-w', to ignore space, and `-i', to ignore case of letters. -At present, the option `-c' is ignored, since Ediff doesn't understand this -type of output." +At present, the option `-c' is not allowed." :type 'string :group 'ediff-diff) @@ -158,9 +157,8 @@ one optional arguments, diff-number to refine.") ;; ediff-setup-diff-regions-function, which can also have the value ;; ediff-setup-diff-regions3, which takes 4 arguments. (defun ediff-setup-diff-regions (file-A file-B file-C) -;;; ;; Force all minibuffers to display ediff's messages. -;;; ;; When xemacs implements minibufferless frames, this won't be necessary -;;; (if ediff-xemacs-p (setq synchronize-minibuffers t)) + (if (string-match "c" ediff-diff-options) + (error "Option `-c' is not allowed in `ediff-diff-options'")) ;; create, if it doesn't exist (or (ediff-buffer-live-p ediff-diff-buffer) @@ -210,7 +208,6 @@ one optional arguments, diff-number to refine.") diff-buffer 'synchronize ediff-diff-options file1 file2) - ;;(message "Computing differences ... done") (message "") (ediff-with-current-buffer diff-buffer (buffer-size)))))) @@ -1043,11 +1040,6 @@ one optional arguments, diff-number to refine.") ;; File-C is either the third file to compare (in case of 3-way comparison) ;; or it is the ancestor file. (defun ediff-setup-diff-regions3 (file-A file-B file-C) - -;;; ;; force all minibuffers to display ediff's messages. -;;; ;; when xemacs implements minibufferless frames, this won't be necessary -;;; (if ediff-xemacs-p (setq synchronize-minibuffers t)) - (or (ediff-buffer-live-p ediff-diff-buffer) (setq ediff-diff-buffer (get-buffer-create (ediff-unique-buffer-name "*ediff-diff" "*")))) diff --git a/lisp/ediff-mult.el b/lisp/ediff-mult.el index 7fce125bc8e..223573a2a25 100644 --- a/lisp/ediff-mult.el +++ b/lisp/ediff-mult.el @@ -155,10 +155,15 @@ directories.") ;; history var to use for filtering groups (defvar ediff-filtering-regexp-history nil "") -;; This has the form ((ctl-buf file1 file2) (stl-buf file1 file2) ...) -;; If ctl-buf is nil, the file-pair wasn't processed yet. If it is +;; This has the form ((meta-buf regexp dir1 dir2 dir3 merge-auto-store-dir) +;; (ctl-buf session-status (file1 . eq-status) (file2 . eq-status) (file3 +;; . eq-status)) (ctl-buf session-status (file1 . eq-status) (file2 +;; . eq-status)) ...) +;; If ctl-buf is nil, the file-pair hasn't processed yet. If it is ;; killed-buffer object, the file pair has been processed. If it is a live -;; buffer, this means ediff is still working on the pair +;; buffer, this means ediff is still working on the pair. +;; Eq-status of a file is t if the file equals some other file in the same +;; group. (ediff-defvar-local ediff-meta-list nil "") @@ -204,40 +209,40 @@ buffers." ;;; API for ediff-meta-list ;; group buffer/regexp -(defun ediff-get-group-buffer (meta-list) +(defsubst ediff-get-group-buffer (meta-list) (nth 0 (car meta-list))) -(defun ediff-get-group-regexp (meta-list) +(defsubst ediff-get-group-regexp (meta-list) (nth 1 (car meta-list))) ;; group objects -(defun ediff-get-group-objA (meta-list) +(defsubst ediff-get-group-objA (meta-list) (nth 2 (car meta-list))) -(defun ediff-get-group-objB (meta-list) +(defsubst ediff-get-group-objB (meta-list) (nth 3 (car meta-list))) -(defun ediff-get-group-objC (meta-list) +(defsubst ediff-get-group-objC (meta-list) (nth 4 (car meta-list))) -(defun ediff-get-group-merge-autostore-dir (meta-list) +(defsubst ediff-get-group-merge-autostore-dir (meta-list) (nth 5 (car meta-list))) ;; session buffer -(defun ediff-get-session-buffer (elt) +(defsubst ediff-get-session-buffer (elt) (nth 0 elt)) -(defun ediff-get-session-status (elt) +(defsubst ediff-get-session-status (elt) (nth 1 elt)) -(defun ediff-set-session-status (session-info new-status) +(defsubst ediff-set-session-status (session-info new-status) (setcar (cdr session-info) new-status)) ;; session objects -(defun ediff-get-session-objA (elt) +(defsubst ediff-get-session-objA (elt) (nth 2 elt)) -(defun ediff-get-session-objB (elt) +(defsubst ediff-get-session-objB (elt) (nth 3 elt)) -(defun ediff-get-session-objC (elt) +(defsubst ediff-get-session-objC (elt) (nth 4 elt)) -(defun ediff-get-session-objA-name (elt) +(defsubst ediff-get-session-objA-name (elt) (car (nth 2 elt))) -(defun ediff-get-session-objB-name (elt) +(defsubst ediff-get-session-objB-name (elt) (car (nth 3 elt))) -(defun ediff-get-session-objC-name (elt) +(defsubst ediff-get-session-objC-name (elt) (car (nth 4 elt))) ;; equality indicators (defsubst ediff-get-file-eqstatus (elt) @@ -245,6 +250,15 @@ buffers." (defsubst ediff-set-file-eqstatus (elt value) (setcar (cdr elt) value)) +;; checks if the session is a meta session +(defun ediff-meta-session-p (session-info) + (and (stringp (ediff-get-session-objA-name session-info)) + (file-directory-p (ediff-get-session-objA-name session-info)) + (stringp (ediff-get-session-objB-name session-info)) + (file-directory-p (ediff-get-session-objB-name session-info)) + (if (stringp (ediff-get-session-objC-name session-info)) + (file-directory-p (ediff-get-session-objC-name session-info)) t))) + ;; set up the keymap in the meta buffer (defun ediff-setup-meta-map() (setq ediff-meta-buffer-map (make-sparse-keymap)) @@ -1122,22 +1136,33 @@ Useful commands: (marksym ?*) (numMarked 0) (sessionNum 0) - elt) + (diff-buffer ediff-meta-diff-buffer) + session-buf elt) (while meta-list (setq elt (car meta-list) meta-list (cdr meta-list) sessionNum (1+ sessionNum)) - (if (eq (ediff-get-session-status elt) marksym) - (save-excursion - (setq numMarked (1+ numMarked)) - (funcall operation elt sessionNum)))) + (cond ((eq (ediff-get-session-status elt) marksym) + (save-excursion + (setq numMarked (1+ numMarked)) + (funcall operation elt sessionNum))) + ((and (ediff-meta-session-p elt) + (ediff-buffer-live-p + (setq session-buf (ediff-get-session-buffer elt)))) + (setq numMarked + (+ numMarked + (ediff-with-current-buffer session-buf + ;; pass meta-diff along + (setq ediff-meta-diff-buffer diff-buffer) + ;; collect diffs in child group + (ediff-operate-on-marked-sessions operation))))))) (ediff-update-meta-buffer grp-buf) ; just in case numMarked )) (defun ediff-append-custom-diff (session sessionNum) (or (ediff-collect-diffs-metajob) - (error "Sorry, I don't do this for everyone...")) + (error "Hmm, I'd hate to do it to you ...")) (let ((session-buf (ediff-get-session-buffer session)) (meta-diff-buff ediff-meta-diff-buffer) (metajob ediff-metajob-name) @@ -1256,9 +1281,7 @@ all marked sessions must be active." ;; First handle sessions involving directories (which are themselves ;; session groups) ;; After that handle individual sessions - (cond ((and (file-directory-p file1) - (stringp file2) (file-directory-p file2) - (if (stringp file3) (file-directory-p file1) t)) + (cond ((ediff-meta-session-p info) ;; do ediff/ediff-merge on subdirectories (if (ediff-buffer-live-p session-buf) (ediff-show-meta-buffer session-buf) diff --git a/lisp/ediff-ptch.el b/lisp/ediff-ptch.el index 901e6053986..dc6330492eb 100644 --- a/lisp/ediff-ptch.el +++ b/lisp/ediff-ptch.el @@ -81,18 +81,26 @@ See also `ediff-backup-specs'." :type 'string :group 'ediff-ptch) +(defun ediff-test-patch-utility () + (cond ((zerop (call-process ediff-patch-program nil nil nil "-z." "-b")) + ;; GNU `patch' v. >= 2.2 + 'gnu) + ((zerop (call-process ediff-patch-program nil nil nil "-b")) + 'posix) + (t 'traditional))) + (defcustom ediff-backup-specs - (cond - ((zerop (call-process ediff-patch-program nil nil nil "-z." "-b")) - ;; GNU `patch' v. >= 2.2 - (format "-z%s -b" ediff-backup-extension)) - ((zerop (call-process ediff-patch-program nil nil nil "-b")) - ;; POSIX `patch' -- ediff-backup-extension must be ".orig" - (setq ediff-backup-extension ediff-default-backup-extension) - "-b") - (t - ;; traditional `patch' - (format "-b %s" ediff-backup-extension))) + (let ((type (ediff-test-patch-utility))) + (cond ((eq type 'gnu) + ;; GNU `patch' v. >= 2.2 + (format "-z%s -b" ediff-backup-extension)) + ((eq type 'posix) + ;; POSIX `patch' -- ediff-backup-extension must be ".orig" + (setq ediff-backup-extension ediff-default-backup-extension) + "-b") + (t + ;; traditional `patch' + (format "-b %s" ediff-backup-extension)))) "*Backup directives to pass to the patch program. Ediff requires that the old version of the file \(before applying the patch\) be saved in a file named `the-patch-file.extension'. Usually `extension' is @@ -107,7 +115,11 @@ versions of GNU patch require `-b -z backup-extension'. Note that both `ediff-backup-extension' and `ediff-backup-specs' must be set properly. If your patch program takes the option `-b', but not `-b extension', the variable `ediff-backup-extension' must -still be set so Ediff will know which extension to use." +still be set so Ediff will know which extension to use. + +Ediff tries to guess the appropriate value for this variables. It is believed +to be working for `traditional' patch, all versions of GNU patch, and for POSIX +patch. So, don't change these variables, unless the default doesn't work." :type 'string :group 'ediff-ptch) @@ -278,10 +290,8 @@ program." (princ (format " The patch file contains a context diff for - %s %s - However, Ediff cannot infer the name of the actual file to be patched on your system. If you know the correct file name, please enter it now. @@ -336,7 +346,7 @@ other files, enter /dev/null Ediff has inferred that %s %s -are possible targets for applying the patch. +are two possible targets for applying the patch. Both files seem to be plausible alternatives. Please advice: @@ -351,17 +361,19 @@ Please advice: (f1-exists (setcar triple file1)) (t (with-output-to-temp-buffer ediff-msg-buffer - (princ (format " -Ediff inferred that + (princ "\nEdiff has inferred that") + (if (string= file1 file2) + (princ (format " %s +is the target for this patch. However, this file does not exist." + file1)) + (princ (format " %s -are possible alternative targets for this patch. - -However, these files do not exist. - -Please enter an alternative patch target ... -" - file1 file2))) + %s +are two possible targets for this patch. However, these files do not exist." + file1 file2))) + (princ " +\nPlease enter an alternative patch target ...\n")) (let ((directory t) target) (while directory @@ -392,12 +404,21 @@ Else, read patch file into a new buffer." (ediff-use-last-dir ediff-last-dir-patch) (t default-directory))) patch-buf) - (if (y-or-n-p "Is the patch already in a buffer? ") + (if (let ((last-nonmenu-event t) ; Emacs: don't use dialog box + last-command-event) ; XEmacs: don't use dialog box + (y-or-n-p "Is the patch already in a buffer? ")) (setq patch-buf (get-buffer (read-buffer "Which buffer contains the patch? " - (current-buffer) 'must-match))) + (ediff-other-buffer + (if (eq (next-window (selected-window)) (selected-window)) + ;; only one window in frame --- don't skip current buff + "" + ;; >1 window --- skip current buff, assuming this is the one + ;; to patch, not the one that has the patch + (current-buffer))) + 'must-match))) (setq patch-buf (find-file-noselect (read-file-name "Which file contains the patch? " @@ -433,56 +454,71 @@ Else, read patch file into a new buffer." )) -(defun ediff-patch-buffer-internal (patch-buf buf-to-patch-name - &optional startup-hooks) +;; When patching a buffer, never change the orig file. Instead, create a new +;; buffer, ***_patched, even if the buff visits a file. +;; Users who want to actually patch the buffer should use +;; ediff-patch-file, not ediff-patch-buffer. +(defun ediff-patch-buffer-internal (patch-buf + buf-to-patch-name + &optional startup-hooks) (let* ((buf-to-patch (get-buffer buf-to-patch-name)) - (file-name-ok (if buf-to-patch (buffer-file-name buf-to-patch))) + (visited-file (if buf-to-patch (buffer-file-name buf-to-patch))) (buf-mod-status (buffer-modified-p buf-to-patch)) (multifile-patch-p (> (length (ediff-with-current-buffer patch-buf ediff-patch-map)) 1)) default-dir file-name ctl-buf) - (if file-name-ok - (setq file-name file-name-ok) - (if multifile-patch-p - (error - "Can't apply multi-file patches to buffers that visit no files")) - (ediff-with-current-buffer buf-to-patch - (setq default-dir default-directory) - (setq file-name (ediff-make-temp-file buf-to-patch)) - (set-visited-file-name file-name) - (setq buffer-auto-save-file-name nil) ; don't create auto-save file - ;;don't confuse the user with a new bufname - (rename-buffer buf-to-patch-name) - (set-buffer-modified-p nil) - (set-visited-file-modtime) ; sync buffer and temp file - (setq default-directory default-dir) - )) - + (if multifile-patch-p + (error + "Can't apply multi-file patches to buffers that visit no files")) + + ;; create a temp file to patch + (ediff-with-current-buffer buf-to-patch + (setq default-dir default-directory) + (setq file-name (ediff-make-temp-file buf-to-patch)) + ;; temporarily switch visited file name, if any + (set-visited-file-name file-name) + ;; don't create auto-save file, if buff was visiting a file + (or visited-file + (setq buffer-auto-save-file-name nil)) + ;; don't confuse the user with a new bufname + (rename-buffer buf-to-patch-name) + (set-buffer-modified-p nil) + (set-visited-file-modtime) ; sync buffer and temp file + (setq default-directory default-dir) + ) + ;; dispatch a patch function (setq ctl-buf (ediff-dispatch-file-patching-job patch-buf file-name startup-hooks)) - (if file-name-ok - () - ;; buffer wasn't visiting any file, - ;; so we will not run meta-level ediff here - (ediff-with-current-buffer ctl-buf - (delete-file (buffer-file-name ediff-buffer-A)) - (delete-file (buffer-file-name ediff-buffer-B)) - (ediff-with-current-buffer ediff-buffer-A - (if default-dir (setq default-directory default-dir)) - (set-visited-file-name nil) - (rename-buffer buf-to-patch-name) - (set-buffer-modified-p buf-mod-status)) - (ediff-with-current-buffer ediff-buffer-B - (setq buffer-auto-save-file-name nil) ; don't create auto-save file - (if default-dir (setq default-directory default-dir)) - (set-visited-file-name nil) - (rename-buffer (ediff-unique-buffer-name - (concat buf-to-patch-name "_patched") "")) - (set-buffer-modified-p t)))) + (ediff-with-current-buffer ctl-buf + (delete-file (buffer-file-name ediff-buffer-A)) + (delete-file (buffer-file-name ediff-buffer-B)) + (ediff-with-current-buffer ediff-buffer-A + (if default-dir (setq default-directory default-dir)) + (set-visited-file-name visited-file) ; visited-file might be nil + (rename-buffer buf-to-patch-name) + (set-buffer-modified-p buf-mod-status)) + (ediff-with-current-buffer ediff-buffer-B + (setq buffer-auto-save-file-name nil) ; don't create auto-save file + (if default-dir (setq default-directory default-dir)) + (set-visited-file-name nil) + (rename-buffer (ediff-unique-buffer-name + (concat buf-to-patch-name "_patched") "")) + (set-buffer-modified-p t))) )) + +;; Traditional patch has weird return codes. +;; GNU and Posix return 1 if some hanks failed and 2 in case of trouble. +;; 0 is a good code in all cases. +;; We'll do the concervative thing. +(defun ediff-patch-return-code-ok (code) + (eq code 0)) +;;; (if (eq (ediff-test-patch-utility) 'traditional) +;;; (eq code 0) +;;; (not (eq code 2)))) + (defun ediff-patch-file-internal (patch-buf source-filename &optional startup-hooks) (setq source-filename (expand-file-name source-filename)) @@ -498,7 +534,7 @@ Else, read patch file into a new buffer." target-buf buf-to-patch file-name-magic-p patch-return-code ctl-buf backup-style aux-wind) - (if (string-match "-V" ediff-patch-options) + (if (string-match "V" ediff-patch-options) (error "Ediff doesn't take the -V option in `ediff-patch-options'--sorry")) @@ -550,26 +586,29 @@ Else, read patch file into a new buffer." (switch-to-buffer patch-diagnostics) (sit-for 0) ; synchronize - let the user see diagnostics - (or (and (eq patch-return-code 0) ; patch reported success + (or (and (ediff-patch-return-code-ok patch-return-code) (file-exists-p (concat true-source-filename ediff-backup-extension))) (progn (with-output-to-temp-buffer ediff-msg-buffer (princ (format - "Patch program has failed due to a bad patch file OR -because it couldn't create the backup for the file to be patched. + "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 + ediff-patch-program = %S ediff-patch-options = %S + ediff-backup-extension = %S ediff-backup-specs = %S See Ediff on-line manual for more details on these variables. -In particular, check the documentation for `ediff-backup-specs'. " +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 diff --git a/lisp/ediff-util.el b/lisp/ediff-util.el index 0d0cf25a903..0d11f7b33cb 100644 --- a/lisp/ediff-util.el +++ b/lisp/ediff-util.el @@ -145,10 +145,11 @@ to invocation.") (define-key ediff-mode-map "p" 'ediff-previous-difference) (define-key ediff-mode-map "\C-?" 'ediff-previous-difference) - (define-key ediff-mode-map [backspace] 'ediff-previous-difference) (define-key ediff-mode-map [delete] 'ediff-previous-difference) (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer 'ediff-previous-difference nil)) + ;; must come after C-h, or else C-h wipes out backspace's binding in XEmacs + (define-key ediff-mode-map [backspace] 'ediff-previous-difference) (define-key ediff-mode-map "n" 'ediff-next-difference) (define-key ediff-mode-map " " 'ediff-next-difference) (define-key ediff-mode-map "j" 'ediff-jump-to-difference) @@ -687,10 +688,6 @@ if necessary." Reestablish the default three-window display." (interactive) (ediff-barf-if-not-control-buffer) - -;; ;; No longer needed: XEmacs has surrogate minibuffers now. -;; (if ediff-xemacs-p (setq synchronize-minibuffers t)) - (let (buffer-read-only) (if (and (ediff-buffer-live-p ediff-buffer-A) (ediff-buffer-live-p ediff-buffer-B) @@ -2918,6 +2915,15 @@ Hit \\[ediff-recenter] to reset the windows afterward." (error "Buffer out of sync for file %s" buffer-file-name)))) +(defun ediff-file-compressed-p (file) + (require 'jka-compr) + (string-match (jka-compr-build-file-regexp) file)) + +(defun ediff-filename-magic-p (file) + (or (ediff-file-compressed-p file) + (ediff-file-remote-p file))) + + (defun ediff-save-buffer (arg) "Safe way of saving buffers A, B, C, and the diff output. `wa' saves buffer A, `wb' saves buffer B, `wc' saves buffer C, @@ -3314,17 +3320,23 @@ Ediff Control Panel to restore highlighting." ;; other insignificant buffers (those beginning with "^[ *]"). ;; Gets one arg--buffer name or a list of buffer names (it won't return ;; these buffers). -(defun ediff-other-buffer (buff) - (if (not (listp buff)) (setq buff (list buff))) +(defun ediff-other-buffer (buff-lst) + (or (listp buff-lst) (setq buff-lst (list buff-lst))) (let* ((frame-buffers (buffer-list)) + (buff-name-list + (mapcar + (function (lambda (b) + (cond ((stringp b) b) + ((bufferp b) (buffer-name b))))) + buff-lst)) (significant-buffers (mapcar (function (lambda (x) - (cond ((member (buffer-name x) buff) - nil) - ((not (ediff-get-visible-buffer-window x)) - nil) - ((string-match "^ " (buffer-name x)) + (cond ((member (buffer-name x) buff-name-list) nil) + ((not (ediff-get-visible-buffer-window x)) nil) + ((string-match "^[ *]" (buffer-name x)) nil) + ((memq (ediff-with-current-buffer x major-mode) + '(dired-mode)) nil) (t x)))) frame-buffers)) @@ -3338,8 +3350,12 @@ Ediff Control Panel to restore highlighting." (mapcar (function (lambda (x) - (cond ((member (buffer-name x) buff) nil) + (cond ((member (buffer-name x) buff-name-list) nil) ((string-match "^[ *]" (buffer-name x)) nil) + ((memq + (ediff-with-current-buffer x major-mode) + '(dired-mode)) + nil) (t x)))) frame-buffers))) (car less-significant-buffers)) diff --git a/lisp/ediff.el b/lisp/ediff.el index ea7d747a70a..2cbbc90164b 100644 --- a/lisp/ediff.el +++ b/lisp/ediff.el @@ -7,7 +7,7 @@ ;; Keywords: comparing, merging, patching, version control. (defconst ediff-version "2.67" "The current version of Ediff") -(defconst ediff-date "August 7, 1997" "Date of last update") +(defconst ediff-date "September 3, 1997" "Date of last update") ;; This file is part of GNU Emacs. @@ -275,7 +275,7 @@ ;; deleted. (defun ediff-find-file (file-var buffer-name &optional last-dir hooks-var) (let* ((file (symbol-value file-var)) - (file-magic (find-file-name-handler file 'find-file-noselect)) + (file-magic (ediff-filename-magic-p file)) (temp-file-name-prefix (file-name-nondirectory file))) (cond ((not (file-readable-p file)) (error "File `%s' does not exist or is not readable" file)) @@ -1182,7 +1182,8 @@ file and then run `run-ediff-from-cvs-buffer'." (t default-directory))) (setq source-file ;; the default is the directory, not the visited file name - (ediff-read-file-name "Which file to patch? " source-dir source-dir)) + (ediff-read-file-name + "Which file to patch? " source-dir (ediff-get-default-file-name))) (ediff-dispatch-file-patching-job patch-buf source-file))) ;;;###autoload @@ -1196,7 +1197,7 @@ file and then run `run-ediff-from-cvs-buffer'." patch-buf (read-buffer "Which buffer to patch? " (cond ((eq patch-buf (current-buffer)) - (window-buffer (other-window 1))) + (ediff-other-buffer (current-buffer))) (t (current-buffer))) 'must-match)))) -- 2.39.2