aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond2014-12-01 11:41:45 -0500
committerEric S. Raymond2014-12-01 11:43:10 -0500
commitd17bae9039021b600ceaec93f2f0e888b12e523d (patch)
treef6ea0b50386d04f4c584415bed7c5221b872d4de
parentdce46a7484d9898cc161a8333ec71db3480b110b (diff)
downloademacs-d17bae9039021b600ceaec93f2f0e888b12e523d.tar.gz
emacs-d17bae9039021b600ceaec93f2f0e888b12e523d.zip
Refactor VC merging to fix a layer violation.
* vc/vc.el, vc/vc-cvs.el, vc/vc-rcs.el, vc/vc-svn.el: The 'merge' backend method of RCS/CVS/SVN is now 'merge-file', to contrast with 'merge-branch'. Prompting for merge revisions is pushed down to the back ends; this fixes a layering violation that caused bad behavior with SVN.
-rw-r--r--lisp/ChangeLog6
-rw-r--r--lisp/vc/vc-cvs.el29
-rw-r--r--lisp/vc/vc-rcs.el25
-rw-r--r--lisp/vc/vc-svn.el23
-rw-r--r--lisp/vc/vc.el41
5 files changed, 94 insertions, 30 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index b736b2d5617..e75cc89e3e9 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -5,6 +5,12 @@
5 5
62014-12-01 Eric S. Raymond <esr@snark.thyrsus.com> 62014-12-01 Eric S. Raymond <esr@snark.thyrsus.com>
7 7
8 * vc/vc.el, vc/vc-cvs.el, vc/vc-rcs.el, vc/vc-svn.el: The 'merge'
9 backend method of RCS/CVS/SVN is now 'merge-file', to contrast with
10 'merge-branch'. Prompting for merge revisions is pushed down to
11 the back ends; this fixes a layering violation that caused bad
12 behavior with SVN.
13
8 * vc/vc.el, vc-hooks.el, and all backends: API simplification; 14 * vc/vc.el, vc-hooks.el, and all backends: API simplification;
9 vc-stay-local-p and repository-hostname are no longer public 15 vc-stay-local-p and repository-hostname are no longer public
10 methods. Only the CVS and SVN backends used these, and the SVN 16 methods. Only the CVS and SVN backends used these, and the SVN
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index a09909a8353..fc1e8572578 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -440,6 +440,35 @@ REV is the revision to check out."
440 ;; Make the file read-only by switching off all w-bits 440 ;; Make the file read-only by switching off all w-bits
441 (set-file-modes file (logand (file-modes file) 3950))))) 441 (set-file-modes file (logand (file-modes file) 3950)))))
442 442
443(defun vc-cvs-merge-file (file)
444 "Accept a file merge request, prompting for revisions."
445 (let* ((first-revision
446 (vc-read-revision
447 (concat "Merge " file
448 " from branch or revision "
449 "(default news on current branch): ")
450 (list file)
451 'CVS))
452 second-revision
453 status)
454 (cond
455 ((string= first-revision "")
456 (setq status (vc-cvs-merge-news file)))
457 (t
458 (if (not (vc-branch-p first-revision))
459 (setq second-revision
460 (vc-read-revision
461 "Second revision: "
462 (list file) 'CVS nil
463 (concat (vc-branch-part first-revision) ".")))
464 ;; We want to merge an entire branch. Set revisions
465 ;; accordingly, so that vc-cvs-merge understands us.
466 (setq second-revision first-revision)
467 ;; first-revision must be the starting point of the branch
468 (setq first-revision (vc-branch-part first-revision)))
469 (setq status (vc-cvs-merge file first-revision second-revision))))
470 status))
471
443(defun vc-cvs-merge (file first-revision &optional second-revision) 472(defun vc-cvs-merge (file first-revision &optional second-revision)
444 "Merge changes into current working copy of FILE. 473 "Merge changes into current working copy of FILE.
445The changes are between FIRST-REVISION and SECOND-REVISION." 474The changes are between FIRST-REVISION and SECOND-REVISION."
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 96ae5836f42..940d967d68b 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -486,6 +486,31 @@ revert all registered files beneath it."
486 (concat (if (eq (vc-state file) 'edited) "-u" "-r") 486 (concat (if (eq (vc-state file) 'edited) "-u" "-r")
487 (vc-working-revision file))))) 487 (vc-working-revision file)))))
488 488
489(defun vc-rcs-merge-file (file)
490 "Accept a file merge request, prompting for revisions."
491 (let* ((first-revision
492 (vc-read-revision
493 (concat "Merge " file " from branch or revision: ")
494 (list file)
495 'RCS))
496 second-revision)
497 (cond
498 ((string= first-revision "")
499 (error "A starting RCS revision is required"))
500 (t
501 (if (not (vc-branch-p first-revision))
502 (setq second-revision
503 (vc-read-revision
504 "Second RCS revision: "
505 (list file) 'RCS nil
506 (concat (vc-branch-part first-revision) ".")))
507 ;; We want to merge an entire branch. Set revisions
508 ;; accordingly, so that vc-rcs-merge understands us.
509 (setq second-revision first-revision)
510 ;; first-revision must be the starting point of the branch
511 (setq first-revision (vc-branch-part first-revision)))))
512 (vc-rcs-merge file first-revision second-revision)))
513
489(defun vc-rcs-merge (file first-version &optional second-version) 514(defun vc-rcs-merge (file first-version &optional second-version)
490 "Merge changes into current working copy of FILE. 515 "Merge changes into current working copy of FILE.
491The changes are between FIRST-VERSION and SECOND-VERSION." 516The changes are between FIRST-VERSION and SECOND-VERSION."
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index c3efcc59b5a..00a0388c599 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -379,6 +379,29 @@ FILE is a file wildcard, relative to the root directory of DIRECTORY."
379 (unless contents-done 379 (unless contents-done
380 (vc-svn-command nil 0 file "revert"))) 380 (vc-svn-command nil 0 file "revert")))
381 381
382(defun vc-svn-merge-file (file)
383 "Accept a file merge request, prompting for revisions."
384 (let* ((first-revision
385 (vc-read-revision
386 (concat "Merge " file
387 " from SVN revision "
388 "(default news on current branch): ")
389 (list file)
390 'SVN))
391 second-revision
392 status)
393 (cond
394 ((string= first-revision "")
395 (setq status (vc-svn-merge-news file)))
396 (t
397 (setq second-revision
398 (vc-read-revision
399 "Second SVN revision: "
400 (list file) 'SVN nil
401 first-revision))
402 (setq status (vc-svn-merge file first-revision second-revision))))
403 status))
404
382(defun vc-svn-merge (file first-version &optional second-version) 405(defun vc-svn-merge (file first-version &optional second-version)
383 "Merge changes into current working copy of FILE. 406 "Merge changes into current working copy of FILE.
384The changes are between FIRST-VERSION and SECOND-VERSION." 407The changes are between FIRST-VERSION and SECOND-VERSION."
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index a30581efb4a..b6ba2d3e863 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -289,10 +289,11 @@
289;; 'cancel-version' and took a single file arg, not a list of 289;; 'cancel-version' and took a single file arg, not a list of
290;; files.) 290;; files.)
291;; 291;;
292;; - merge (file rev1 rev2) 292;; - merge-file (file rev1 rev2)
293;; 293;;
294;; Merge the changes between REV1 and REV2 into the current working file 294;; Merge the changes between REV1 and REV2 into the current working
295;; (for non-distributed VCS). 295;; file (for non-distributed VCS). It is expected that with an
296;; empty first revision this will behave like the merge-news method.
296;; 297;;
297;; - merge-branch () 298;; - merge-branch ()
298;; 299;;
@@ -594,6 +595,11 @@
594;; RCS has setting the initial revision been even possible, let alone 595;; RCS has setting the initial revision been even possible, let alone
595;; sane. 596;; sane.
596;; 597;;
598;; - The backend operation for non-distributed VCSes formerly called
599;; "merge" is now "merge-file" (to contrast with merge-branch), and
600;; does its own prompting for revisions. (This fixes a layer violation
601;; that produced bad behavior under SVN.)
602;;
597;; workfile-unchanged-p is no longer a public back-end method. It 603;; workfile-unchanged-p is no longer a public back-end method. It
598;; was redundant with vc-state and usually implemented with a trivial 604;; was redundant with vc-state and usually implemented with a trivial
599;; call to it. A few older back ends retain versions for internal use in 605;; call to it. A few older back ends retain versions for internal use in
@@ -2060,42 +2066,17 @@ changes from the current branch."
2060 (vc-buffer-sync) 2066 (vc-buffer-sync)
2061 (dolist (file files) 2067 (dolist (file files)
2062 (let* ((state (vc-state file)) 2068 (let* ((state (vc-state file))
2063 first-revision second-revision status) 2069 status)
2064 (cond 2070 (cond
2065 ((stringp state) ;; Locking VCses only 2071 ((stringp state) ;; Locking VCses only
2066 (error "File %s is locked by %s" file state)) 2072 (error "File %s is locked by %s" file state))
2067 ((not (vc-editable-p file)) 2073 ((not (vc-editable-p file))
2068 (vc-checkout file t))) 2074 (vc-checkout file t)))
2069 (setq first-revision 2075 (setq status (vc-call-backend backend 'merge-file file))
2070 (vc-read-revision
2071 (concat "Merge " file
2072 " from branch or revision "
2073 "(default news on current branch): ")
2074 (list file)
2075 backend))
2076 (cond
2077 ((string= first-revision "")
2078 (setq status (vc-call-backend backend 'merge-news file)))
2079 (t
2080 (if (not (vc-branch-p first-revision))
2081 (setq second-revision
2082 (vc-read-revision
2083 "Second revision: "
2084 (list file) backend nil
2085 ;; FIXME: This is CVS/RCS/SCCS specific.
2086 (concat (vc-branch-part first-revision) ".")))
2087 ;; We want to merge an entire branch. Set revisions
2088 ;; accordingly, so that vc-BACKEND-merge understands us.
2089 (setq second-revision first-revision)
2090 ;; first-revision must be the starting point of the branch
2091 (setq first-revision (vc-branch-part first-revision)))
2092 (setq status (vc-call-backend backend 'merge file
2093 first-revision second-revision))))
2094 (vc-maybe-resolve-conflicts file status "WORKFILE" "MERGE SOURCE")))) 2076 (vc-maybe-resolve-conflicts file status "WORKFILE" "MERGE SOURCE"))))
2095 (t 2077 (t
2096 (error "Sorry, merging is not implemented for %s" backend))))) 2078 (error "Sorry, merging is not implemented for %s" backend)))))
2097 2079
2098
2099(defun vc-maybe-resolve-conflicts (file status &optional _name-A _name-B) 2080(defun vc-maybe-resolve-conflicts (file status &optional _name-A _name-B)
2100 (vc-resynch-buffer file t (not (buffer-modified-p))) 2081 (vc-resynch-buffer file t (not (buffer-modified-p)))
2101 (if (zerop status) (message "Merge successful") 2082 (if (zerop status) (message "Merge successful")