Commits

Anonymous committed dfaad5d

Adrian's patch to sync VC with FSF

Comments (0)

Files changed (3)

+2001-02-14  Steve Youngs  <youngs@xemacs.org>
+
+	* vc.el: Require compile, sendmail & ediff-util.
+
+	* Makefile (REQUIRES): Add vc, ediff, mail-lib.
+
+2001-02-13  Adrian Aichner  <adrian@xemacs.org>
+
+	* vc.el: Sync up with GNU Emacs 20.7 to make `cvs-mode-imerge'
+	work again.
+	* vc.el (vc-ensure-vc-buffer): New.
+	* vc.el (vc-merge): New.
+	* vc.el (vc-ediff-windows)): New.
+	* vc.el (vc-ediff-result)): New.
+	* vc.el (vc-resolve-conflicts): New.
+
 2000-10-05  Martin Buchholz  <martin@xemacs.org>
 
 	* *: Mega typo fix.
 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-VERSION = 1.25
+VERSION = 1.26
 AUTHOR_VERSION =
 MAINTAINER = XEmacs Development Team <xemacs-beta@xemacs.org>
 PACKAGE = vc
 PKG_TYPE = regular
-REQUIRES = dired xemacs-base
+REQUIRES = dired xemacs-base vc mail-lib ediff
 CATEGORY = prog
 
 ELCS = vc-hooks.elc vc.elc
 (require 'vc-hooks)
 (require 'ring)
 (eval-when-compile (require 'dired))	; for dired-map-over-marks macro
+(eval-when-compile
+  (require 'sendmail)
+  (require 'compile)
+  (require 'ediff-util))
 
 (if (not (assoc 'vc-parent-buffer minor-mode-alist))
     (setq minor-mode-alist
      ;; CVS
      t))
 
+(defun vc-ensure-vc-buffer ()
+  ;; Make sure that the current buffer visits a version-controlled file.
+  (if vc-dired-mode
+      (set-buffer (find-file-noselect (dired-get-filename)))
+    (while vc-parent-buffer
+      (pop-to-buffer vc-parent-buffer))
+    (if (not (buffer-file-name))
+	(error "Buffer %s is not associated with a file" (buffer-name))
+      (if (not (vc-backend (buffer-file-name)))
+	  (error "File %s is not under version control" (buffer-file-name))))))
+
 (defun vc-registration-error (file)
   (if file
       (error "File %s is not under version control" file)
       (replace-match "$\\1$"))
     (vc-restore-buffer-context context)))
 
+;;;###autoload
+(defun vc-merge ()
+  (interactive)
+  (vc-ensure-vc-buffer)
+  (vc-buffer-sync)
+  (let* ((file buffer-file-name)
+	 (backend (vc-backend file))
+	 first-version second-version locking-user)
+    (if (eq backend 'SCCS)
+	(error "Sorry, merging is not implemented for SCCS")
+      (setq locking-user (vc-locking-user file))
+      (if (eq (vc-checkout-model file) 'manual)
+	  (if (not locking-user)
+	      (if (not (y-or-n-p 
+			(format "File must be %s for merging.  %s now? "
+				(if (eq backend 'RCS) "locked" "writable")
+				(if (eq backend 'RCS) "Lock" "Check out"))))
+		  (error "Merge aborted")
+		(vc-checkout file t))
+	    (if (not (string= locking-user (vc-user-login-name)))
+		(error "File is locked by %s" locking-user))))
+      (setq first-version (read-string "Branch or version to merge from: "))
+      (if (and (>= (elt first-version 0) ?0)
+	       (<= (elt first-version 0) ?9))
+	  (if (not (vc-branch-p first-version))
+	      (setq second-version 
+		    (read-string "Second version: " 
+				 (concat (vc-branch-part first-version) ".")))
+	    ;; We want to merge an entire branch.  Set versions
+	    ;; accordingly, so that vc-backend-merge understands us.
+	    (setq second-version first-version)
+	    ;; first-version must be the starting point of the branch
+	    (setq first-version (vc-branch-part first-version))))
+      (let ((status (vc-backend-merge file first-version second-version)))
+	(if (and (eq (vc-checkout-model file) 'implicit)
+		 (not (vc-locking-user file)))
+	    (vc-file-setprop file 'vc-locking-user nil))
+	(vc-resynch-buffer file t t)
+	(if (not (zerop status))
+	    (if (y-or-n-p "Conflicts detected.  Resolve them now? ")
+		(vc-resolve-conflicts "WORKFILE" "MERGE SOURCE")
+	      (message "File contains conflict markers"))
+	  (message "Merge successful"))))))
+
+(defvar vc-ediff-windows)
+(defvar vc-ediff-result)
+
+;;;###autoload
+(defun vc-resolve-conflicts (&optional name-A name-B)
+  "Invoke ediff to resolve conflicts in the current buffer.
+The conflicts must be marked with rcsmerge conflict markers."
+  (interactive)
+  (vc-ensure-vc-buffer)
+  (let* ((found nil)
+         (file-name (file-name-nondirectory buffer-file-name))
+	 (your-buffer   (generate-new-buffer 
+                         (concat "*" file-name 
+				 " " (or name-A "WORKFILE") "*")))
+	 (other-buffer  (generate-new-buffer 
+                         (concat "*" file-name 
+				 " " (or name-B "CHECKED-IN") "*")))
+         (result-buffer (current-buffer)))
+    (save-excursion 
+      (set-buffer your-buffer)
+      (erase-buffer)
+      (insert-buffer result-buffer)
+      (goto-char (point-min))
+      (while (re-search-forward (concat "^<<<<<<< " 
+					(regexp-quote file-name) "\n") nil t)
+        (setq found t)
+	(replace-match "")
+	(if (not (re-search-forward "^=======\n" nil t))
+	    (error "Malformed conflict marker"))
+	(replace-match "")
+	(let ((start (point)))
+	  (if (not (re-search-forward "^>>>>>>> [0-9.]+\n" nil t))
+	      (error "Malformed conflict marker"))
+	  (delete-region start (point))))
+      (if (not found)
+          (progn
+            (kill-buffer your-buffer)
+            (kill-buffer other-buffer)
+            (error "No conflict markers found")))
+      (set-buffer other-buffer)
+      (erase-buffer)
+      (insert-buffer result-buffer)
+      (goto-char (point-min))
+      (while (re-search-forward (concat "^<<<<<<< " 
+					(regexp-quote file-name) "\n") nil t)
+	(let ((start (match-beginning 0)))
+	(if (not (re-search-forward "^=======\n" nil t))
+	    (error "Malformed conflict marker"))
+	(delete-region start (point))
+	(if (not (re-search-forward "^>>>>>>> [0-9.]+\n" nil t))
+	    (error "Malformed conflict marker"))
+	(replace-match "")))
+      (let ((config (current-window-configuration))
+            (ediff-default-variant 'default-B))
+
+        ;; Fire up ediff.
+
+        (set-buffer (ediff-merge-buffers your-buffer other-buffer))
+
+        ;; Ediff is now set up, and we are in the control buffer.
+        ;; Do a few further adjustments and take precautions for exit.
+
+        (make-local-variable 'vc-ediff-windows)
+        (setq vc-ediff-windows config)
+        (make-local-variable 'vc-ediff-result)
+        (setq vc-ediff-result result-buffer)        
+        (make-local-variable 'ediff-quit-hook)
+        (setq ediff-quit-hook 
+              (function 
+               (lambda ()
+                 (let ((buffer-A ediff-buffer-A)
+                       (buffer-B ediff-buffer-B)
+                       (buffer-C ediff-buffer-C)
+                       (result vc-ediff-result)
+                       (windows vc-ediff-windows))
+                   (ediff-cleanup-mess)
+                   (set-buffer result)
+                   (erase-buffer)
+                   (insert-buffer buffer-C)
+                   (kill-buffer buffer-A)
+                   (kill-buffer buffer-B)
+                   (kill-buffer buffer-C)
+                   (set-window-configuration windows)
+                   (message "Conflict resolution finished; you may save the buffer")))))
+        (message "Please resolve conflicts now; exit ediff when done")
+        nil))))
+
 ;; The VC directory major mode.  Coopt Dired for this.
 ;; All VC commands get mapped into logical equivalents.