]> code.delx.au - gnu-emacs/blobdiff - lisp/emerge.el
(Version, mh-version): Update for release 7.95.
[gnu-emacs] / lisp / emerge.el
index 023727e26b2813056e7420e33f3b2c56c4abef63..447e45f14f3eb72e647134fb18b8b13f4f0a97ca 100644 (file)
@@ -2,6 +2,8 @@
 
 ;;; The author has placed this file in the public domain.
 
+;; This file is part of GNU Emacs.
+
 ;; Author: Dale R. Worley <worley@world.std.com>
 ;; Version: 5fsf
 ;; Keywords: unix, tools
 ;; LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL
 ;; DAMAGES.
 
+;;; Commentary:
+
 ;;; Code:
 
 ;;;###autoload
 (defvar menu-bar-emerge-menu (make-sparse-keymap "Emerge"))
-;;;###autoload
-(fset 'menu-bar-emerge-menu (symbol-value 'menu-bar-emerge-menu))
-
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-merge-directories]
-  '("Merge Directories..." . emerge-merge-directories))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-revisions-with-ancestor]
-  '("Revisions with Ancestor..." . emerge-revisions-with-ancestor))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-revisions]
-  '("Revisions..." . emerge-revisions))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-files-with-ancestor]
-  '("Files with Ancestor..." . emerge-files-with-ancestor))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-files]
-  '("Files..." . emerge-files))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-buffers-with-ancestor]
-  '("Buffers with Ancestor..." . emerge-buffers-with-ancestor))
-;;;###autoload
-(define-key menu-bar-emerge-menu [emerge-buffers]
-  '("Buffers..." . emerge-buffers))
+;;;###autoload (fset 'menu-bar-emerge-menu (symbol-value 'menu-bar-emerge-menu))
+
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-merge-directories]
+;;;###autoload   '("Merge Directories..." . emerge-merge-directories))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-revisions-with-ancestor]
+;;;###autoload   '("Revisions with Ancestor..." . emerge-revisions-with-ancestor))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-revisions]
+;;;###autoload   '("Revisions..." . emerge-revisions))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-files-with-ancestor]
+;;;###autoload   '("Files with Ancestor..." . emerge-files-with-ancestor))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-files]
+;;;###autoload   '("Files..." . emerge-files))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-buffers-with-ancestor]
+;;;###autoload   '("Buffers with Ancestor..." . emerge-buffers-with-ancestor))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-buffers]
+;;;###autoload   '("Buffers..." . emerge-buffers))
+
+;; There aren't really global variables, just dynamic bindings
+(defvar A-begin)
+(defvar A-end)
+(defvar B-begin)
+(defvar B-end)
+(defvar diff)
+(defvar diff-vector)
+(defvar merge-begin)
+(defvar merge-end)
+(defvar template)
+(defvar valid-diff)
 
 ;;; Macros
 
 (defmacro emerge-eval-in-buffer (buffer &rest forms)
   "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
 Differs from `save-excursion' in that it doesn't save the point and mark."
-  (` (let ((StartBuffer (current-buffer)))
+  `(let ((StartBuffer (current-buffer)))
     (unwind-protect
-       (progn
-         (set-buffer (, buffer))
-         (,@ forms))
-      (set-buffer StartBuffer)))))
+         (progn
+           (set-buffer ,buffer)
+           ,@forms)
+      (set-buffer StartBuffer))))
 
-(defmacro emerge-defvar-local (var value doc) 
-  "Defines SYMBOL as an advertised variable.  
+(defmacro emerge-defvar-local (var value doc)
+  "Defines SYMBOL as an advertised variable.
 Performs a defvar, then executes `make-variable-buffer-local' on
 the variable.  Also sets the `preserved' property, so that
-`kill-all-local-variables' (called by major-mode setting commands) 
+`kill-all-local-variables' (called by major-mode setting commands)
 won't destroy Emerge control variables."
-  (` (progn
-       (defvar (, var) (, value) (, doc))
-       (make-variable-buffer-local '(, var))
-       (put '(, var) 'preserved t))))
+  `(progn
+    (defvar ,var ,value ,doc)
+    (make-variable-buffer-local ',var)
+    (put ',var 'preserved t)))
 
 ;; Add entries to minor-mode-alist so that emerge modes show correctly
 (defvar emerge-minor-modes-list
@@ -123,7 +131,7 @@ When called interactively, displays the version."
 ;; to be provided (emerge-diff-options).  The order in which the file names
 ;; are given is fixed.
 ;; The file names are always expanded (see expand-file-name) before being
-;; passed to diff, thus they need not be invoked under a shell that 
+;; passed to diff, thus they need not be invoked under a shell that
 ;; understands `~'.
 ;; The code which processes the diff/diff3 output depends on all the
 ;; finicky details of their output, including the somewhat strange
@@ -396,10 +404,8 @@ Must be set before Emerge is loaded."
   ;; Allow emerge-fast-keymap to be referenced indirectly
   (fset 'emerge-fast-keymap emerge-fast-keymap)
   ;; Suppress write-file and save-buffer
-  (substitute-key-definition 'write-file 'emerge-query-write-file
-                            emerge-fast-keymap (current-global-map))
-  (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
-                            emerge-fast-keymap (current-global-map))
+  (define-key emerge-fast-keymap [remap write-file] 'emerge-query-write-file)
+  (define-key emerge-fast-keymap [remap save-buffer] 'emerge-query-save-buffer)
 
   (define-key emerge-basic-keymap [menu-bar] (make-sparse-keymap))
 
@@ -563,7 +569,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
 ;;; Setup functions for two-file mode.
 
 (defun emerge-files-internal (file-A file-B &optional startup-hooks quit-hooks
-                                    output-file)
+                              output-file)
   (if (not (file-readable-p file-A))
       (error "File `%s' does not exist or is not readable" file-A))
   (if (not (file-readable-p file-B))
@@ -576,17 +582,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     (if output-file
        (setq emerge-last-dir-output (file-name-directory output-file)))
     ;; Make sure the entire files are seen, and they reflect what is on disk
-    (emerge-eval-in-buffer 
+    (emerge-eval-in-buffer
      buffer-A
      (widen)
      (let ((temp (file-local-copy file-A)))
        (if temp
           (setq file-A temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-A))))
+                (cons `(lambda () (delete-file ,file-A))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-eval-in-buffer
      buffer-B
      (widen)
@@ -594,10 +600,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-B temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-B))))
+                (cons `(lambda () (delete-file ,file-B))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-setup buffer-A file-A buffer-B file-B startup-hooks quit-hooks
                  output-file)))
 
@@ -663,20 +669,20 @@ This is *not* a user option, since Emerge uses it for its own processing.")
      diff-buffer
      (goto-char (point-min))
      (while (re-search-forward emerge-match-diff-line nil t)
-       (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
-                                                       (match-end 1))))
+       (let* ((a-begin (string-to-number (buffer-substring (match-beginning 1)
+                                                           (match-end 1))))
              (a-end  (let ((b (match-beginning 3))
                            (e (match-end 3)))
                        (if b
-                           (string-to-int (buffer-substring b e))
+                           (string-to-number (buffer-substring b e))
                          a-begin)))
              (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
-             (b-begin (string-to-int (buffer-substring (match-beginning 5)
-                                                       (match-end 5))))
+             (b-begin (string-to-number (buffer-substring (match-beginning 5)
+                                                           (match-end 5))))
              (b-end (let ((b (match-beginning 7))
                           (e (match-end 7)))
                       (if b
-                          (string-to-int (buffer-substring b e))
+                          (string-to-number (buffer-substring b e))
                         b-begin))))
         ;; fix the beginning and end numbers, because diff is somewhat
         ;; strange about how it numbers lines
@@ -737,10 +743,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-A temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-A))))
+                (cons `(lambda () (delete-file ,file-A))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-eval-in-buffer
      buffer-B
      (widen)
@@ -748,10 +754,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-B temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-B))))
+                (cons `(lambda () (delete-file ,file-B))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-eval-in-buffer
      buffer-ancestor
      (widen)
@@ -759,10 +765,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-ancestor temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-ancestor))))
+                (cons `(lambda () (delete-file ,file-ancestor))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-setup-with-ancestor buffer-A file-A buffer-B file-B
                                buffer-ancestor file-ancestor
                                startup-hooks quit-hooks output-file)))
@@ -840,7 +846,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
         ;; if the A and B files are the same, ignore the difference
         (if (not (string-equal agreement "2"))
             (setq list
-                  (cons 
+                  (cons
                    (let (group-1 group-3 pos)
                      (setq pos (point))
                      (setq group-1 (emerge-get-diff3-group "1"))
@@ -868,16 +874,16 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        ;; it is a "c" group
        (if (match-beginning 2)
            ;; it has two numbers
-           (list (string-to-int
+           (list (string-to-number
                   (buffer-substring (match-beginning 1) (match-end 1)))
-                 (1+ (string-to-int
+                 (1+ (string-to-number
                       (buffer-substring (match-beginning 3) (match-end 3)))))
          ;; it has one number
-         (let ((x (string-to-int
+         (let ((x (string-to-number
                    (buffer-substring (match-beginning 1) (match-end 1)))))
            (list x (1+ x))))
       ;; it is an "a" group
-      (let ((x (1+ (string-to-int
+      (let ((x (1+ (string-to-number
                    (buffer-substring (match-beginning 1) (match-end 1))))))
        (list x x)))))
 
@@ -897,7 +903,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
                (emerge-read-file-name "Output file" emerge-last-dir-output
                                       f f nil)))))
   (if file-out
-      (add-hook 'quit-hooks (` (lambda () (emerge-files-exit (, file-out))))))
+      (add-hook 'quit-hooks `(lambda () (emerge-files-exit ,file-out))))
   (emerge-files-internal
    file-A file-B startup-hooks
    quit-hooks
@@ -919,7 +925,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
                (emerge-read-file-name "Output file" emerge-last-dir-output
                                       f f nil)))))
   (if file-out
-      (add-hook 'quit-hooks (` (lambda () (emerge-files-exit (, file-out))))))
+      (add-hook 'quit-hooks `(lambda () (emerge-files-exit ,file-out))))
   (emerge-files-with-ancestor-internal
    file-A file-B file-ancestor startup-hooks
    quit-hooks
@@ -947,17 +953,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
      (write-region (point-min) (point-max) emerge-file-B nil 'no-message))
     (emerge-setup (get-buffer buffer-A) emerge-file-A
                  (get-buffer buffer-B) emerge-file-B
-                 (cons (` (lambda ()
-                            (delete-file (, emerge-file-A))
-                            (delete-file (, emerge-file-B))))
+                 (cons `(lambda ()
+                          (delete-file ,emerge-file-A)
+                          (delete-file ,emerge-file-B))
                        startup-hooks)
                  quit-hooks
                  nil)))
 
 ;;;###autoload
 (defun emerge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor
-                                             &optional startup-hooks
-                                             quit-hooks)
+                                     &optional startup-hooks
+                                     quit-hooks)
   "Run Emerge on two buffers, giving another buffer as the ancestor."
   (interactive
    "bBuffer A to merge: \nbBuffer B to merge: \nbAncestor buffer: ")
@@ -978,11 +984,11 @@ This is *not* a user option, since Emerge uses it for its own processing.")
                                (get-buffer buffer-B) emerge-file-B
                                (get-buffer buffer-ancestor)
                                emerge-file-ancestor
-                               (cons (` (lambda ()
-                                          (delete-file (, emerge-file-A))
-                                          (delete-file (, emerge-file-B))
-                                          (delete-file
-                                           (, emerge-file-ancestor))))
+                               (cons `(lambda ()
+                                        (delete-file ,emerge-file-A)
+                                        (delete-file ,emerge-file-B)
+                                        (delete-file
+                                         ,emerge-file-ancestor))
                                      startup-hooks)
                                quit-hooks
                                nil)))
@@ -997,7 +1003,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     (setq command-line-args-left (nthcdr 3 command-line-args-left))
     (emerge-files-internal
      file-a file-b nil
-     (list (` (lambda () (emerge-command-exit (, file-out))))))))
+     (list `(lambda () (emerge-command-exit ,file-out))))))
 
 ;;;###autoload
 (defun emerge-files-with-ancestor-command ()
@@ -1011,16 +1017,16 @@ This is *not* a user option, since Emerge uses it for its own processing.")
          (setq file-anc (nth 1 command-line-args-left))
          (setq file-out (nth 4 command-line-args-left))
          (setq command-line-args-left (nthcdr 5 command-line-args-left)))
-      ;; arguments are "file-a file-b ancestor file-out"
-      (setq file-a (nth 0 command-line-args-left))
-      (setq file-b (nth 1 command-line-args-left))
-      (setq file-anc (nth 2 command-line-args-left))
-      (setq file-out (nth 3 command-line-args-left))
-      (setq command-line-args-left (nthcdr 4 command-line-args-left)))
+        ;; arguments are "file-a file-b ancestor file-out"
+        (setq file-a (nth 0 command-line-args-left))
+        (setq file-b (nth 1 command-line-args-left))
+        (setq file-anc (nth 2 command-line-args-left))
+        (setq file-out (nth 3 command-line-args-left))
+        (setq command-line-args-left (nthcdr 4 command-line-args-left)))
     (emerge-files-with-ancestor-internal
      file-a file-b file-anc nil
-     (list (` (lambda () (emerge-command-exit (, file-out))))))))
-      
+     (list `(lambda () (emerge-command-exit ,file-out))))))
+
 (defun emerge-command-exit (file-out)
   (emerge-write-and-delete file-out)
   (kill-emacs (if emerge-prefix-argument 1 0)))
@@ -1032,7 +1038,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (setq emerge-file-out file-out)
   (emerge-files-internal
    file-a file-b nil
-   (list (` (lambda () (emerge-remote-exit (, file-out) '(, emerge-exit-func)))))
+   (list `(lambda () (emerge-remote-exit ,file-out ',emerge-exit-func)))
    file-out)
   (throw 'client-wait nil))
 
@@ -1041,7 +1047,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (setq emerge-file-out file-out)
   (emerge-files-with-ancestor-internal
    file-a file-b file-anc nil
-   (list (` (lambda () (emerge-remote-exit (, file-out) '(, emerge-exit-func)))))
+   (list `(lambda () (emerge-remote-exit ,file-out ',emerge-exit-func)))
    file-out)
   (throw 'client-wait nil))
 
@@ -1066,17 +1072,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (emerge-revisions-internal
    file revision-A revision-B startup-hooks
    (if arg
-       (cons (` (lambda ()
-                 (shell-command
-                  (, (format "%s %s" emerge-rcs-ci-program file)))))
+       (cons `(lambda ()
+               (shell-command
+                ,(format "%s %s" emerge-rcs-ci-program file)))
             quit-hooks)
-     quit-hooks)))
+       quit-hooks)))
 
 ;;;###autoload
 (defun emerge-revisions-with-ancestor (arg file revision-A
-                                          revision-B ancestor
-                                          &optional
-                                          startup-hooks quit-hooks)
+                                       revision-B ancestor
+                                       &optional
+                                       startup-hooks quit-hooks)
   "Emerge two RCS revisions of a file, with another revision as ancestor."
   (interactive
    (list current-prefix-arg
@@ -1091,14 +1097,14 @@ This is *not* a user option, since Emerge uses it for its own processing.")
    file revision-A revision-B ancestor startup-hooks
    (if arg
        (let ((cmd ))
-        (cons (` (lambda ()
-                   (shell-command
-                    (, (format "%s %s" emerge-rcs-ci-program file)))))
+        (cons `(lambda ()
+                 (shell-command
+                  ,(format "%s %s" emerge-rcs-ci-program file)))
               quit-hooks))
-     quit-hooks)))
+       quit-hooks)))
 
 (defun emerge-revisions-internal (file revision-A revision-B &optional
-                                     startup-hooks quit-hooks output-file)
+                                  startup-hooks quit-hooks output-file)
   (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
        (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
        (emerge-file-A (emerge-make-temp-file "A"))
@@ -1123,18 +1129,18 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     ;; Do the merge
     (emerge-setup buffer-A emerge-file-A
                  buffer-B emerge-file-B
-                 (cons (` (lambda ()
-                            (delete-file (, emerge-file-A))
-                            (delete-file (, emerge-file-B))))
+                 (cons `(lambda ()
+                          (delete-file ,emerge-file-A)
+                          (delete-file ,emerge-file-B))
                        startup-hooks)
-                 (cons (` (lambda () (emerge-files-exit (, file))))
+                 (cons `(lambda () (emerge-files-exit ,file))
                        quit-hooks)
                  nil)))
 
 (defun emerge-revision-with-ancestor-internal (file revision-A revision-B
-                                                   ancestor
-                                                   &optional startup-hooks
-                                                   quit-hooks output-file)
+                                               ancestor
+                                               &optional startup-hooks
+                                               quit-hooks output-file)
   (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
        (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
        (buffer-ancestor (get-buffer-create (format "%s,%s" file ancestor)))
@@ -1171,12 +1177,12 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     (emerge-setup-with-ancestor
      buffer-A emerge-file-A buffer-B emerge-file-B
      buffer-ancestor emerge-ancestor
-     (cons (` (lambda ()
-               (delete-file (, emerge-file-A))
-               (delete-file (, emerge-file-B))
-               (delete-file (, emerge-ancestor))))
+     (cons `(lambda ()
+             (delete-file ,emerge-file-A)
+             (delete-file ,emerge-file-B)
+             (delete-file ,emerge-ancestor))
           startup-hooks)
-     (cons (` (lambda () (emerge-files-exit (, file))))
+     (cons `(lambda () (emerge-files-exit ,file))
           quit-hooks)
      output-file)))
 
@@ -1221,26 +1227,26 @@ Otherwise, the A or B file present is copied to the output file."
            (goto-char (match-end 0))
            ;; Store the filename in the right variable
            (cond
-            ((string-equal tag "a")
-             (if file-A
-                 (error "This line has two `A' entries"))
-             (setq file-A file))
-            ((string-equal tag "b")
-             (if file-B
-                 (error "This line has two `B' entries"))
-             (setq file-B file))
-            ((or (string-equal tag "anc") (string-equal tag "ancestor"))
-             (if file-ancestor
-                 (error "This line has two `ancestor' entries"))
-             (setq file-ancestor file))
-            ((or (string-equal tag "out") (string-equal tag "output"))
-             (if file-out
-                 (error "This line has two `output' entries"))
-             (setq file-out file))
-            (t
-             (error "Unrecognized entry"))))
-       ;; If the match on the entry pattern failed
-       (error "Unparsable entry")))
+              ((string-equal tag "a")
+               (if file-A
+                   (error "This line has two `A' entries"))
+               (setq file-A file))
+              ((string-equal tag "b")
+               (if file-B
+                   (error "This line has two `B' entries"))
+               (setq file-B file))
+              ((or (string-equal tag "anc") (string-equal tag "ancestor"))
+               (if file-ancestor
+                   (error "This line has two `ancestor' entries"))
+               (setq file-ancestor file))
+              ((or (string-equal tag "out") (string-equal tag "output"))
+               (if file-out
+                   (error "This line has two `output' entries"))
+               (setq file-out file))
+              (t
+               (error "Unrecognized entry"))))
+          ;; If the match on the entry pattern failed
+          (error "Unparsable entry")))
     ;; Make sure that file-A and file-B are present
     (if (not (or (and file-A file-B) file-out))
        (error "Must have both `A' and `B' entries"))
@@ -1251,37 +1257,37 @@ Otherwise, the A or B file present is copied to the output file."
     (beginning-of-line 2)
     ;; Execute the correct command
     (cond
-     ;; Merge of two files with ancestor
-     ((and file-A file-B file-ancestor)
-      (message "Merging %s and %s..." file-A file-B)
-      (emerge-files-with-ancestor (not (not file-out)) file-A file-B
-                                 file-ancestor file-out
-                                 nil
-                                 ;; When done, return to this buffer.
-                                 (list
-                                  (` (lambda ()
-                                       (switch-to-buffer (, (current-buffer)))
-                                       (message "Merge done."))))))
-     ;; Merge of two files without ancestor
-     ((and file-A file-B)
-      (message "Merging %s and %s..." file-A file-B)
-      (emerge-files (not (not file-out)) file-A file-B file-out
-                   nil
-                   ;; When done, return to this buffer.
-                   (list 
-                    (` (lambda ()
-                         (switch-to-buffer (, (current-buffer)))
-                         (message "Merge done."))))))
-     ;; There is an output file (or there would have been an error above),
-     ;; but only one input file.
-     ;; The file appears to have been deleted in one version; do nothing.
-     ((and file-ancestor emerge-execute-line-deletions)
-      (message "No action."))
-     ;; The file should be copied from the version that contains it
-     (t (let ((input-file (or file-A file-B)))
-         (message "Copying...")
-         (copy-file input-file file-out)
-         (message "%s copied to %s." input-file file-out))))))
+      ;; Merge of two files with ancestor
+      ((and file-A file-B file-ancestor)
+       (message "Merging %s and %s..." file-A file-B)
+       (emerge-files-with-ancestor (not (not file-out)) file-A file-B
+                                   file-ancestor file-out
+                                   nil
+                                   ;; When done, return to this buffer.
+                                   (list
+                                    `(lambda ()
+                                      (switch-to-buffer ,(current-buffer))
+                                      (message "Merge done.")))))
+      ;; Merge of two files without ancestor
+      ((and file-A file-B)
+       (message "Merging %s and %s..." file-A file-B)
+       (emerge-files (not (not file-out)) file-A file-B file-out
+                     nil
+                     ;; When done, return to this buffer.
+                     (list
+                      `(lambda ()
+                        (switch-to-buffer ,(current-buffer))
+                        (message "Merge done.")))))
+      ;; There is an output file (or there would have been an error above),
+      ;; but only one input file.
+      ;; The file appears to have been deleted in one version; do nothing.
+      ((and file-ancestor emerge-execute-line-deletions)
+       (message "No action."))
+      ;; The file should be copied from the version that contains it
+      (t (let ((input-file (or file-A file-B)))
+           (message "Copying...")
+           (copy-file input-file file-out)
+           (message "%s copied to %s." input-file file-out))))))
 
 ;;; Sample function for creating information for emerge-execute-line
 
@@ -1292,7 +1298,7 @@ Otherwise, the A or B file present is copied to the output file."
 
 ;;;###autoload
 (defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
-  (interactive 
+  (interactive
    (list
     (read-file-name "A directory: " nil nil 'confirm)
     (read-file-name "B directory: " nil nil 'confirm)
@@ -1428,10 +1434,8 @@ Otherwise, the A or B file present is copied to the output file."
   (substitute-key-definition 'save-buffer
                             'emerge-query-save-buffer
                             emerge-edit-keymap)
-  (substitute-key-definition 'write-file 'emerge-query-write-file
-                            emerge-edit-keymap (current-global-map))
-  (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
-                            emerge-edit-keymap (current-global-map))
+  (define-key emerge-edit-keymap [remap write-file] 'emerge-query-write-file)
+  (define-key emerge-edit-keymap [remap save-buffer] 'emerge-query-save-buffer)
   (use-local-map emerge-fast-keymap)
   (setq emerge-edit-mode nil)
   (setq emerge-fast-mode t))
@@ -1462,7 +1466,7 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
                                     emerge-merging-values)))))
 
 (defun emerge-restore-buffer-characteristics ()
-  "Restores characteristics saved by `emerge-remember-buffer-characteristics'."
+  "Restore characteristics saved by `emerge-remember-buffer-characteristics'."
   (let ((A-values emerge-A-buffer-values)
        (B-values emerge-B-buffer-values))
     (emerge-eval-in-buffer emerge-A-buffer
@@ -1539,7 +1543,7 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
     ;; fast access
     (setq emerge-difference-list (apply 'vector (nreverse marker-list)))))
 
-;; If we have an ancestor, select all B variants that we prefer 
+;; If we have an ancestor, select all B variants that we prefer
 (defun emerge-select-prefer-Bs ()
   (let ((n 0))
     (while (< n emerge-number-of-differences)
@@ -1663,7 +1667,7 @@ the height of the merge window.
 `C-u -' alone as argument scrolls half the height of the merge window."
   (interactive "P")
   (emerge-operate-on-windows
-   'scroll-up 
+   'scroll-up
    ;; calculate argument to scroll-up
    ;; if there is an explicit argument
    (if (and arg (not (equal arg '-)))
@@ -1906,7 +1910,7 @@ buffer after this will cause serious problems."
     (run-hooks 'emerge-quit-hook)))
 
 (defun emerge-select-A (&optional force)
-  "Select the A variant of this difference.  
+  "Select the A variant of this difference.
 Refuses to function if this difference has been edited, i.e., if it
 is neither the A nor the B variant.
 A prefix argument forces the variant to be selected
@@ -2579,15 +2583,15 @@ been edited."
         (if (= c ?%)
             (progn
               (setq i (1+ i))
-              (setq c 
+              (setq c
                     (condition-case nil
                         (aref template i)
                       (error ?%)))
               (cond ((= c ?a)
                      (insert-buffer-substring emerge-A-buffer A-begin A-end))
-                    ((= c ?b) 
+                    ((= c ?b)
                      (insert-buffer-substring emerge-B-buffer B-begin B-end))
-                    ((= c ?%) 
+                    ((= c ?%)
                      (insert ?%))
                     (t
                      (insert c))))
@@ -2848,7 +2852,7 @@ keymap.  Leaves merge in fast mode."
       (while (< x-begin x-end)
        ;; bite off and compare no more than 1000 characters at a time
        (let* ((compare-length (min (- x-end x-begin) 1000))
-              (x-string (emerge-eval-in-buffer 
+              (x-string (emerge-eval-in-buffer
                          buffer-x
                          (buffer-substring x-begin
                                            (+ x-begin compare-length))))
@@ -2863,7 +2867,7 @@ keymap.  Leaves merge in fast mode."
       t)))
 
 ;; Construct a unique buffer name.
-;; The first one tried is prefixsuffix, then prefix<2>suffix, 
+;; The first one tried is prefixsuffix, then prefix<2>suffix,
 ;; prefix<3>suffix, etc.
 (defun emerge-unique-buffer-name (prefix suffix)
   (if (null (get-buffer (concat prefix suffix)))
@@ -2907,10 +2911,12 @@ keymap.  Leaves merge in fast mode."
 ;; Make a temporary file that only we have access to.
 ;; PREFIX is appended to emerge-temp-file-prefix to make the filename prefix.
 (defun emerge-make-temp-file (prefix)
-  (let ((f (make-temp-name (concat emerge-temp-file-prefix prefix))))
-    ;; create the file
-    (write-region (point-min) (point-min) f nil 'no-message)
-    (set-file-modes f emerge-temp-file-mode)
+  (let (f (old-modes (default-file-modes)))
+    (unwind-protect
+       (progn
+         (set-default-file-modes emerge-temp-file-mode)
+         (setq f (make-temp-file (concat emerge-temp-file-prefix prefix))))
+      (set-default-file-modes old-modes))
     f))
 
 ;;; Functions that query the user before he can write out the current buffer.
@@ -3104,16 +3110,19 @@ SPC, it is ignored; if it is anything else, it is processed as a command."
        (setq name "Buffer has no file name."))
     (save-window-excursion
       (select-window (minibuffer-window))
-      (erase-buffer)
-      (insert name)
-      (if (not (pos-visible-in-window-p))
-         (let ((echo-keystrokes 0))
-           (while (and (not (pos-visible-in-window-p))
-                       (> (1- (screen-height)) (window-height)))
-             (enlarge-window 1))
-           (let ((c (read-event)))
+      (unwind-protect
+         (progn
+           (erase-buffer)
+           (insert name)
+           (if (not (pos-visible-in-window-p))
+               (while (and (not (pos-visible-in-window-p))
+                           (> (1- (frame-height)) (window-height)))
+                 (enlarge-window 1)))
+           (let* ((echo-keystrokes 0)
+                  (c (read-event)))
              (if (not (eq c 32))
-                 (setq unread-command-events (list c)))))))))
+                 (setq unread-command-events (list c)))))
+       (erase-buffer)))))
 
 ;; Improved auto-save file names.
 ;; This function fixes many problems with the standard auto-save file names:
@@ -3212,4 +3221,5 @@ More precisely, a [...] regexp to match any one such character."
 
 (provide 'emerge)
 
+;;; arch-tag: a575f092-6e44-400e-b8a2-4124e9377585
 ;;; emerge.el ends here