]> code.delx.au - gnu-emacs/blobdiff - lisp/vc/vc.el
Remove clear-headers from VC's public method set.
[gnu-emacs] / lisp / vc / vc.el
index 305cc6b561e911f7f7779f7bad7d529e0c25c399..52deb13e4ddcd276d9cc4894cbd15702cbf6d067 100644 (file)
@@ -1,4 +1,4 @@
-;;; vc.el --- drive a version-control system from within Emacs  -*- lexical-binding: t -*-
+;;; vc.el --- drive a version-control system from within Emacs  -*- lexical-binding:t -*-
 
 ;; Copyright (C) 1992-1998, 2000-2014 Free Software Foundation, Inc.
 
@@ -52,7 +52,7 @@
 
 ;; This mode is fully documented in the Emacs user's manual.
 ;;
-;; Supported version-control systems presently include CVS, RCS, GNU
+;; Supported version-control systems presently include CVS, RCS, SRC, GNU
 ;; Arch, Subversion, Bzr, Git, Mercurial, Monotone and SCCS
 ;; (or its free replacement, CSSC).
 ;;
 ;; When using Subversion or a later system, anything you do outside VC
 ;; *through the VCS tools* should safely interlock with VC
 ;; operations. Under these VC does little state caching, because local
-;; operations are assumed to be fast.  The dividing line is
+;; operations are assumed to be fast.
+;;
+;; The 'assumed to be fast' category includes SRC, even though it's
+;; a wrapper around RCS.
 ;;
 ;; ADDING SUPPORT FOR OTHER BACKENDS
 ;;
 ;;   Return the current version control state of FILE.  For a list of
 ;;   possible values, see `vc-state'.  This function should do a full and
 ;;   reliable state computation; it is usually called immediately after
-;;   C-x v v.  If you want to use a faster heuristic when visiting a
-;;   file, put that into `state-heuristic' below.  Note that under most
-;;   VCSes this won't be called at all, dir-status is used instead.
-;;
-;; - state-heuristic (file)
-;;
-;;   If provided, this function is used to estimate the version control
-;;   state of FILE at visiting time.  It should be considerably faster
-;;   than the implementation of `state'.  For a list of possible values,
-;;   see the doc string of `vc-state'.
+;;   C-x v v.
 ;;
 ;; - dir-status (dir update-function)
 ;;
 ;;   Indicate whether FILES need to be "checked out" before they can be
 ;;   edited.  See `vc-checkout-model' for a list of possible values.
 ;;
-;; - workfile-unchanged-p (file)
-;;
-;;   Return non-nil if FILE is unchanged from the working revision.
-;;   This function should do a brief comparison of FILE's contents
-;;   with those of the repository copy of the working revision.  If
-;;   the backend does not have such a brief-comparison feature, the
-;;   default implementation of this function can be used, which
-;;   delegates to a full vc-BACKEND-diff.  (Note that vc-BACKEND-diff
-;;   must not run asynchronously in this case, see variable
-;;   `vc-disable-async-diff'.)
-;;
 ;; - mode-line-string (file)
 ;;
 ;;   If provided, this function should return the VC-specific mode
 ;;   it so VC mode can add files to it.  For file-oriented systems, this
 ;;   need do no more than create a subdirectory with the right name.
 ;;
-;; * register (files &optional rev comment)
+;; * register (files &optional comment)
 ;;
-;;   Register FILES in this backend.  Optionally, an initial revision REV
-;;   and an initial description of the file, COMMENT, may be specified,
-;;   but it is not guaranteed that the backend will do anything with this.
-;;   The implementation should pass the value of vc-register-switches
-;;   to the backend command.  (Note: in older versions of VC, this
-;;   command took a single file argument and not a list.)
-;;   The REV argument is a historical leftover and is never used.
-;;
-;; - init-revision (file)
-;;
-;;   The initial revision to use when registering FILE if one is not
-;;   specified by the user.  If not provided, the variable
-;;   vc-default-init-revision is used instead.
+;;   Register FILES in this backend.  Optionally, an initial
+;;   description of the file, COMMENT, may be specified, but it is not
+;;   guaranteed that the backend will do anything with this.  The
+;;   implementation should pass the value of vc-register-switches to
+;;   the backend command.  (Note: in older versions of VC, this
+;;   command had an optional revision first argument that was
+;;   not used; in still older ones it took a single file argument and
+;;   not a list.)
 ;;
 ;; - responsible-p (file)
 ;;
 ;;   like change log generation.  The default implementation always
 ;;   returns nil.
 ;;
-;; - could-register (file)
-;;
-;;   Return non-nil if FILE could be registered under this backend.  The
-;;   default implementation always returns t.
-;;
 ;; - receive-file (file rev)
 ;;
 ;;   Let this backend "receive" a file that is already registered under
 ;;   Unregister FILE from this backend.  This is only needed if this
 ;;   backend may be used as a "more local" backend for temporary editing.
 ;;
-;; * checkin (files rev comment)
+;; * checkin (files comment)
 ;;
-;;   Commit changes in FILES to this backend.  REV is a historical artifact
-;;   and should be ignored.  COMMENT is used as a check-in comment.
-;;   The implementation should pass the value of vc-checkin-switches to
-;;   the backend command.
+;;   Commit changes in FILES to this backend. COMMENT is used as a
+;;   check-in comment.  The implementation should pass the value of
+;;   vc-checkin-switches to the backend command.  The revision argument
+;;   of some older VC versions is no longer supported.
 ;;
 ;; * find-revision (file rev buffer)
 ;;
 ;;   The implementation should pass the value of vc-checkout-switches
 ;;   to the backend command.
 ;;
-;; * checkout (file &optional editable rev)
+;; * checkout (file &optional rev)
 ;;
-;;   Check out revision REV of FILE into the working area.  If EDITABLE
-;;   is non-nil, FILE should be writable by the user and if locking is
-;;   used for FILE, a lock should also be set.  If REV is non-nil, that
-;;   is the revision to check out (default is the working revision).
-;;   If REV is t, that means to check out the head of the current branch;
-;;   if it is the empty string, check out the head of the trunk.
-;;   The implementation should pass the value of vc-checkout-switches
-;;   to the backend command.
+;;   Check out revision REV of FILE into the working area.  FILE
+;;   should be writable by the user and if locking is used for FILE, a
+;;   lock should also be set.  If REV is non-nil, that is the revision
+;;   to check out (default is the working revision).  If REV is t,
+;;   that means to check out the head of the current branch; if it is
+;;   the empty string, check out the head of the trunk.  The
+;;   implementation should pass the value of vc-checkout-switches to
+;;   the backend command. The 'editable' argument of older VC versions
+;;   is gone; all files are checked out editable.
 ;;
 ;; * revert (file &optional contents-done)
 ;;
 ;;   'cancel-version' and took a single file arg, not a list of
 ;;   files.)
 ;;
-;; - merge (file rev1 rev2)
+;; - merge-file (file rev1 rev2)
 ;;
-;;   Merge the changes between REV1 and REV2 into the current working file
-;;   (for non-distributed VCS).
+;;   Merge the changes between REV1 and REV2 into the current working
+;;   file (for non-distributed VCS).  It is expected that with an
+;;   empty first revision this will behave like the merge-news method.
 ;;
 ;; - merge-branch ()
 ;;
 ;;   default implementation runs rcs2log, which handles RCS- and
 ;;   CVS-style logs.
 ;;
-;; * diff (files &optional rev1 rev2 buffer)
+;; * diff (files &optional async rev1 rev2 buffer)
 ;;
 ;;   Insert the diff for FILE into BUFFER, or the *vc-diff* buffer if
-;;   BUFFER is nil.  If REV1 and REV2 are non-nil, report differences
-;;   from REV1 to REV2.  If REV1 is nil, use the working revision (as
-;;   found in the repository) as the older revision; if REV2 is nil,
-;;   use the current working-copy contents as the newer revision.  This
+;;   BUFFER is nil.  If ASYNC is non-nil, run asynchronously.If REV1
+;;   and REV2 are non-nil, report differences from REV1 to REV2.  If
+;;   REV1 is nil, use the working revision (as found in the
+;;   repository) as the older revision; if REV2 is nil, use the
+;;   current working-copy contents as the newer revision.  This
 ;;   function should pass the value of (vc-switches BACKEND 'diff) to
 ;;   the backend command.  It should return a status of either 0 (no
 ;;   differences found), or 1 (either non-empty diff or the diff is
 ;;   run asynchronously).
+
 ;;
 ;; - revision-completion-table (files)
 ;;
 ;;   If the backend supports annotating through copies and renames,
 ;;   and displays a file name and a revision, then return a cons
 ;;   (REVISION . FILENAME).
+;;
+;; - region-history (FILE BUFFER LFROM LTO)
+;;
+;;   Insert into BUFFER the history (log comments and diffs) of the content of
+;;   FILE between lines LFROM and LTO.  This is typically done asynchronously.
+;;
+;; - region-history-mode ()
+;;
+;;   Major mode to use for the output of `region-history'.
 
 ;; TAG SYSTEM
 ;;
 ;;
 ;;   Return the root of the VC controlled hierarchy for file.
 ;;
-;; - repository-hostname (dirname)
-;;
-;;   Return the hostname that the backend will have to contact
-;;   in order to operate on a file in DIRNAME.  If the return value
-;;   is nil, it means that the repository is local.
-;;   This function is used in `vc-stay-local-p' which backends can use
-;;   for their convenience.
-;;
 ;; - ignore (file &optional directory)
 ;;
 ;;   Ignore FILE under the VCS of DIRECTORY (default is `default-directory').
 ;;
 ;;   Return non-nil if the current buffer contains any version headers.
 ;;
-;; - clear-headers ()
-;;
-;;   In the current buffer, reset all version headers to their unexpanded
-;;   form.  This function should be provided if the state-querying code
-;;   for this backend uses the version headers to determine the state of
-;;   a file.  This function will then be called whenever VC changes the
-;;   version control state in such a way that the headers would give
-;;   wrong information.
-;;
 ;; - delete-file (file)
 ;;
 ;;   Delete FILE and mark it as deleted in the repository.  If this
 ;;   the project that contains DIR.
 ;;   FIXME: what should it do with non-text conflicts?
 
-;;; Todo:
+;;; Changes from the pre-25.1 API:
+;;
+;; - INCOMPATIBLE CHANGE: The 'editable' optional argument of
+;;   vc-checkout is gone. The upper level assumes that all files are
+;;   checked out editable. This moves closer to emulating modern
+;;   non-locking behavior even on very old VCSes.
+;;
+;; - INCOMPATIBLE CHANGE: The vc-register function and its backend
+;;   implementations no longer take a first optional revision
+;;   argument, since on no system since RCS has setting the initial
+;;   revision been even possible, let alone sane.
+;;
+;;   INCOMPATIBLE CHANGE: In older versions of the API, vc-diff did
+;;   not take an async-mode flag as a first optional argument.  (This
+;;   change eliminated a particularly ugly global.)
+;;
+;; - INCOMPATIBLE CHANGE: The backend operation for non-distributed
+;;   VCSes formerly called "merge" is now "merge-file" (to contrast
+;;   with merge-branch), and does its own prompting for revisions.
+;;   (This fixes a layer violation that produced bad behavior under
+;;   SVN.)
+;;
+;; - vc-state-heuristic is no longer a public method (the CVS backend
+;;   retains it as a private one).
+;;
+;; - the vc-mistrust-permissions configuration variable is gone; the
+;;   code no longer relies on permissions except in one corner case where
+;;   CVS leaves no alternative (which was not gated by this variable).  The
+;;   only affected back ends were SCCS and RCS.
+;;
+;; - vc-stay-local-p and repository-hostname are no longer part
+;;   of the public API. The vc-stay-local configuration variable
+;;   remains but only affects the CVS back end.
+;;
+;; - The init-revision function and the default-initial-revision
+;;   variable are gone.  These have't made sense on anything shipped
+;;   since RCS, and using them was a dumb stunt even on RCS.
+;;
+;;   workfile-unchanged-p is no longer a public back-end method.  It
+;;   was redundant with vc-state and usually implemented with a trivial
+;;   call to it.  A few older back ends retain versions for internal use in
+;;   their vc-state functions.
+;;
+;;   could-register is no longer a public method.  Only vc-cvs ever used it
 
-;; - Get rid of the "master file" terminology.
+;;; Todo:
 
 ;; - Add key-binding for vc-delete-file.
 
 ;;;; New Primitives:
 ;;
-;; - deal with push/pull operations.
+;; - deal with push operations.
 ;;
 ;;;; Primitives that need changing:
 ;;
 ;;
 ;;;; Improved branch and tag handling:
 ;;
+;; - Make sure the *vc-dir* buffer is updated after merge-branch operations.
+;;
 ;; - add a generic mechanism for remembering the current branch names,
 ;;   display the branch name in the mode-line. Replace
 ;;   vc-cvs-sticky-tag with that.
 ;;
-;;;; Internal cleanups:
+;; - Add a primitives for switching to a branch (creating it if required.
 ;;
-;; - backends that care about vc-stay-local should try to take it into
-;;   account for vc-dir.  Is this likely to be useful???  YES!
+;; - Add the ability to list tags and branches.
+;;
+;;;; Internal cleanups:
 ;;
 ;; - vc-expand-dirs should take a backend parameter and only look for
 ;;   files managed by that backend.
 ;;   (or nil if it worked synchronously).  Hopefully we can define the old
 ;;   4 operations in term of this one.
 ;;
+;;;; Unify two different versions of the amend capability
+;;
+;; - Some back ends (SCCS/RCS/SVN/SRC), have an amend capability that can
+;;   be invoked from log-view.
+;;
+;; - The git backend supports amending, but in a different
+;;   way (press `C-c C-e' in log-edit buffer, when making a new commit).
+;;
+;; - Second, `log-view-modify-change-comment' doesn't seem to support
+;;   modern backends at all because `log-view-extract-comment'
+;;   unconditionally calls `log-view-current-file'. This should be easy to
+;;   fix.
+;;
+;; - Third, doing message editing in log-view might be a natural way to go
+;;   about it, but editing any but the last commit (and even it, if it's
+;;   been pushed) is a dangerous operation in Git, which we shouldn't make
+;;   too easy for users to perform.
+;;
+;;   There should be a check that the given comment is not reachable
+;;   from any of the "remote" refs?
+;;
 ;;;; Other
 ;;
+;; - asynchronous checkin and commit, so you can keep working in other
+;;   buffers while the repo operation happens.
+;;
+;; - Direct support for stash/shelve.
+;;
 ;; - when a file is in `conflict' state, turn on smerge-mode.
 ;;
 ;; - figure out what to do with conflicts that are not caused by the
 
 (require 'vc-hooks)
 (require 'vc-dispatcher)
+(require 'cl-lib)
 
 (declare-function diff-setup-whitespace "diff-mode" ())
 
 
 (make-obsolete-variable 'vc-initial-comment "it has no effect." "23.2")
 
-(defcustom vc-default-init-revision "1.1"
-  "A string used as the default revision number when a new file is registered.
-This can be overridden by giving a prefix argument to \\[vc-register].  This
-can also be overridden by a particular VC backend."
-  :type 'string
-  :group 'vc
-  :version "20.3")
-
 (defcustom vc-checkin-switches nil
   "A string or list of strings specifying extra switches for checkin.
 These are passed to the checkin program by \\[vc-checkin]."
@@ -826,13 +860,6 @@ is sensitive to blank lines."
   :group 'vc)
 
 \f
-;; Variables users don't need to see
-
-(defvar vc-disable-async-diff nil
-  "VC sets this to t locally to disable some async diff operations.
-Backends that offer asynchronous diffs should respect this variable
-in their implementation of vc-BACKEND-diff.")
-
 ;; File property caching
 
 (defun vc-clear-context ()
@@ -985,6 +1012,9 @@ current buffer."
       (if observer
          (vc-dired-deduce-fileset)
        (error "State changing VC operations not supported in `dired-mode'")))
+     ((and (derived-mode-p 'log-view-mode)
+          (setq backend (vc-responsible-backend default-directory)))
+      (list backend default-directory))
      ((setq backend (vc-backend buffer-file-name))
       (if state-model-only-files
        (list backend (list buffer-file-name)
@@ -1111,7 +1141,7 @@ For old-style locking-based version control systems, like RCS:
      ((eq state 'ignored)
       (error "Fileset files are ignored by the version-control system"))
      ((or (null state) (eq state 'unregistered))
-      (vc-register nil vc-fileset))
+      (vc-register vc-fileset))
      ;; Files are up-to-date, or need a merge and user specified a revision
      ((or (eq state 'up-to-date) (and verbose (eq state 'needs-update)))
       (cond
@@ -1128,10 +1158,10 @@ For old-style locking-based version control systems, like RCS:
              (let ((vsym (intern-soft revision-downcase)))
                (dolist (file files) (vc-transfer-file file vsym)))
            (dolist (file files)
-              (vc-checkout file (eq model 'implicit) revision)))))
+              (vc-checkout file revision)))))
        ((not (eq model 'implicit))
        ;; check the files out
-       (dolist (file files) (vc-checkout file t)))
+       (dolist (file files) (vc-checkout file)))
        (t
         ;; do nothing
         (message "Fileset is up-to-date"))))
@@ -1148,7 +1178,7 @@ For old-style locking-based version control systems, like RCS:
            ;; state of each individual file in the fileset, it seems
            ;; simplest to just check if the file exists.        Bug#9781.
            (when (and (file-exists-p file) (not (file-writable-p file)))
-             ;; Make the file+buffer read-write.
+             ;; Make the file-buffer read-write.
              (unless (y-or-n-p (format "%s is edited but read-only; make it writable and continue? " file))
                (error "Aborted"))
              ;; Maybe we somehow lost permissions on the directory.
@@ -1166,7 +1196,7 @@ For old-style locking-based version control systems, like RCS:
               ;; For files with locking, if the file does not contain
               ;; any changes, just let go of the lock, i.e. revert.
               (when (and (not (eq model 'implicit))
-                        (vc-workfile-unchanged-p file)
+                        (eq state 'up-to-date)
                         ;; If buffer is modified, that means the user just
                         ;; said no to saving it; in that case, don't revert,
                         ;; because the user might intend to save after
@@ -1217,10 +1247,10 @@ For old-style locking-based version control systems, like RCS:
        (if (yes-or-no-p (format
                          "%s is not up-to-date.  Get latest revision? "
                          (file-name-nondirectory file)))
-           (vc-checkout file (eq model 'implicit) t)
+           (vc-checkout file t)
          (when (and (not (eq model 'implicit))
                     (yes-or-no-p "Lock this revision? "))
-           (vc-checkout file t)))))
+           (vc-checkout file)))))
      ;; needs-merge
      ((eq state 'needs-merge)
       (dolist (file files)
@@ -1248,16 +1278,13 @@ For old-style locking-based version control systems, like RCS:
                                   "Claim lock retaining changes? ")))
            (progn (vc-call-backend backend 'steal-lock file)
                   (clear-visited-file-modtime)
-                  ;; Must clear any headers here because they wouldn't
-                  ;; show that the file is locked now.
-                  (vc-clear-headers file)
                   (write-file buffer-file-name)
                   (vc-mode-line file backend))
          (if (not (yes-or-no-p
                    "Revert to checked-in revision, instead? "))
              (error "Checkout aborted")
            (vc-revert-buffer-internal t t)
-           (vc-checkout file t)))))
+           (vc-checkout file)))))
      ;; Unknown fileset state
      (t
       (error "Fileset is in an unknown state %s" state)))))
@@ -1277,12 +1304,11 @@ For old-style locking-based version control systems, like RCS:
 (declare-function vc-dir-move-to-goal-column "vc-dir" ())
 
 ;;;###autoload
-(defun vc-register (&optional set-revision vc-fileset comment)
+(defun vc-register (&optional vc-fileset comment)
   "Register into a version control system.
 If VC-FILESET is given, register the files in that fileset.
 Otherwise register the current file.
-With prefix argument SET-REVISION, allow user to specify initial revision
-level.  If COMMENT is present, use that as an initial comment.
+If COMMENT is present, use that as an initial comment.
 
 The version control system to use is found by cycling through the list
 `vc-handled-backends'.  The first backend in that list which declares
@@ -1314,11 +1340,7 @@ first backend that could register the file is used."
            (vc-buffer-sync)))))
     (message "Registering %s... " files)
     (mapc 'vc-file-clearprops files)
-    (vc-call-backend backend 'register files
-                    (if set-revision
-                        (read-string (format "Initial revision level for %s: " files))
-                      (vc-call-backend backend 'init-revision))
-                    comment)
+    (vc-call-backend backend 'register files comment)
     (mapc
      (lambda (file)
        (vc-file-setprop file 'vc-backend backend)
@@ -1416,29 +1438,27 @@ Argument BACKEND is the backend you are using."
       (replace-match ""))
     (write-region (point-min) (point-max) file)))
 
-(defun vc-checkout (file &optional writable rev)
+(defun vc-checkout (file &optional rev)
   "Retrieve a copy of the revision REV of FILE.
-If WRITABLE is non-nil, make sure the retrieved file is writable.
 REV defaults to the latest revision.
 
 After check-out, runs the normal hook `vc-checkout-hook'."
-  (and writable
-       (not rev)
+  (and (not rev)
        (vc-call make-version-backups-p file)
        (vc-up-to-date-p file)
        (vc-make-version-backup file))
   (let ((backend (vc-backend file)))
     (with-vc-properties (list file)
       (condition-case err
-          (vc-call-backend backend 'checkout file writable rev)
+          (vc-call-backend backend 'checkout file rev)
         (file-error
          ;; Maybe the backend is not installed ;-(
-         (when writable
+         (when t
            (let ((buf (get-file-buffer file)))
              (when buf (with-current-buffer buf (read-only-mode -1)))))
          (signal (car err) (cdr err))))
       `((vc-state . ,(if (or (eq (vc-checkout-model backend (list file)) 'implicit)
-                             (not writable))
+                             nil)
                          (if (vc-call-backend backend 'latest-on-branch-p file)
                              'up-to-date
                            'needs-update)
@@ -1488,13 +1508,11 @@ Type \\[vc-next-action] to check in changes.")
      ".\n")
     (message "Please explain why you stole the lock.  Type C-c C-c when done.")))
 
-(defun vc-checkin (files backend &optional rev comment initial-contents)
-  "Check in FILES.
-The optional argument REV may be a string specifying the new revision
-level (strongly deprecated).  COMMENT is a comment
-string; if omitted, a buffer is popped up to accept a comment.  If
-INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents
-of the log entry buffer.
+(defun vc-checkin (files backend &optional comment initial-contents)
+  "Check in FILES. COMMENT is a comment string; if omitted, a
+buffer is popped up to accept a comment.  If INITIAL-CONTENTS is
+non-nil, then COMMENT is used as the initial contents of the log
+entry buffer.
 
 If `vc-keep-workfiles' is nil, FILE is deleted afterwards, provided
 that the version control system supports this mode of operation.
@@ -1520,7 +1538,7 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
        ;; vc-checkin-switches, but 'the' local buffer is
        ;; not a well-defined concept for filesets.
        (progn
-         (vc-call-backend backend 'checkin files rev comment)
+         (vc-call-backend backend 'checkin files comment)
          (mapc 'vc-delete-automatic-version-backups files))
        `((vc-state . up-to-date)
          (vc-checkout-time . ,(nth 5 (file-attributes file)))
@@ -1684,11 +1702,10 @@ Return t if the buffer had changes, nil otherwise."
               ;; We regard this as "changed".
               ;; Diff it against /dev/null.
               (apply 'vc-do-command buffer
-                     1 "diff" file
+                     (if async 'async 1) "diff" file
                      (append (vc-switches nil 'diff) '("/dev/null"))))))
         (setq files (nreverse filtered))))
-    (let ((vc-disable-async-diff (not async)))
-      (vc-call-backend (car vc-fileset) 'diff files rev1 rev2 buffer))
+    (vc-call-backend (car vc-fileset) 'diff files async rev1 rev2 buffer)
     (set-buffer buffer)
     (diff-mode)
     (set (make-local-variable 'diff-vc-backend) (car vc-fileset))
@@ -1878,6 +1895,19 @@ saving the buffer."
         t (list backend (list rootdir) working-revision) nil nil
         (called-interactively-p 'interactive))))))
 
+;;;###autoload
+(defun vc-root-dir ()
+  "Return the root directory for the current VC tree.
+Return nil if the root directory cannot be identified."
+  (let ((backend (vc-deduce-backend)))
+    (if backend
+        (condition-case err
+            (vc-call-backend backend 'root default-directory)
+          (vc-not-supported
+           (unless (eq (cadr err) 'root)
+             (signal (car err) (cdr err)))
+           nil)))))
+
 ;;;###autoload
 (defun vc-revision-other-window (rev)
   "Visit revision REV of the current file in another window.
@@ -1959,25 +1989,6 @@ the variable `vc-BACKEND-header'."
              (when (string-match (car f) buffer-file-name)
                (insert (format (cdr f) (car hdstrings)))))))))))
 
-(defun vc-clear-headers (&optional file)
-  "Clear all version headers in the current buffer (or FILE).
-The headers are reset to their non-expanded form."
-  (let* ((filename (or file buffer-file-name))
-        (visited (find-buffer-visiting filename))
-        (backend (vc-backend filename)))
-    (when (vc-find-backend-function backend 'clear-headers)
-       (if visited
-           (let ((context (vc-buffer-context)))
-             ;; save-excursion may be able to relocate point and mark
-             ;; properly.  If it fails, vc-restore-buffer-context
-             ;; will give it a second try.
-             (save-excursion
-               (vc-call-backend backend 'clear-headers))
-             (vc-restore-buffer-context context))
-         (set-buffer (find-file-noselect filename))
-         (vc-call-backend backend 'clear-headers)
-         (kill-buffer filename)))))
-
 (defun vc-modify-change-comment (files rev oldcomment)
   "Edit the comment associated with the given files and revision."
   ;; Less of a kluge than it looks like; log-view mode only passes
@@ -2020,42 +2031,17 @@ changes from the current branch."
       (vc-buffer-sync)
       (dolist (file files)
        (let* ((state (vc-state file))
-              first-revision second-revision status)
+              status)
          (cond
           ((stringp state)     ;; Locking VCses only
            (error "File %s is locked by %s" file state))
           ((not (vc-editable-p file))
            (vc-checkout file t)))
-         (setq first-revision
-               (vc-read-revision
-                (concat "Merge " file
-                        " from branch or revision "
-                        "(default news on current branch): ")
-                (list file)
-                backend))
-         (cond
-          ((string= first-revision "")
-           (setq status (vc-call-backend backend 'merge-news file)))
-          (t
-           (if (not (vc-branch-p first-revision))
-               (setq second-revision
-                     (vc-read-revision
-                      "Second revision: "
-                      (list file) backend nil
-                      ;; FIXME: This is CVS/RCS/SCCS specific.
-                      (concat (vc-branch-part first-revision) ".")))
-             ;; We want to merge an entire branch.  Set revisions
-             ;; accordingly, so that vc-BACKEND-merge understands us.
-             (setq second-revision first-revision)
-             ;; first-revision must be the starting point of the branch
-             (setq first-revision (vc-branch-part first-revision)))
-           (setq status (vc-call-backend backend 'merge file
-                                         first-revision second-revision))))
+         (setq status (vc-call-backend backend 'merge-file file))
          (vc-maybe-resolve-conflicts file status "WORKFILE" "MERGE SOURCE"))))
      (t
       (error "Sorry, merging is not implemented for %s" backend)))))
 
-
 (defun vc-maybe-resolve-conflicts (file status &optional _name-A _name-B)
   (vc-resynch-buffer file t (not (buffer-modified-p)))
   (if (zerop status) (message "Merge successful")
@@ -2080,8 +2066,9 @@ changes from the current branch."
   (let* ((backend (or (if buffer-file-name (vc-backend buffer-file-name))
                       (vc-responsible-backend default-directory)
                       (error "No VC backend")))
+         (root (vc-root-dir))
          (files (vc-call-backend backend
-                                 'conflicted-files default-directory)))
+                                 'conflicted-files (or root default-directory))))
     ;; Don't try and visit the current file.
     (if (equal (car files) buffer-file-name) (pop files))
     (if (null files)
@@ -2135,8 +2122,12 @@ checked out in that new branch."
 
 ;;;###autoload
 (defun vc-retrieve-tag (dir name)
-  "Descending recursively from DIR, retrieve the tag called NAME.
-If NAME is empty, it refers to the latest revisions.
+  "For each file in or below DIR, retrieve their tagged version NAME.
+NAME can name a branch, in which case this command will switch to the
+named branch in the directory DIR.
+Interactively, prompt for DIR only for VCS that works at file level;
+otherwise use the default directory of the current buffer.
+If NAME is empty, it refers to the latest revisions of the current branch.
 If locking is used for the files in DIR, then there must not be any
 locked files at or below DIR (but if NAME is empty, locked files are
 allowed and simply skipped)."
@@ -2214,19 +2205,11 @@ earlier revisions.  Show up to LIMIT entries (non-nil means unlimited)."
   ;; Don't switch to the output buffer before running the command,
   ;; so that any buffer-local settings in the vc-controlled
   ;; buffer can be accessed by the command.
-  (let ((dir-present nil)
-       (vc-short-log nil)
+  (let* ((dir-present (cl-some #'file-directory-p files))
+         (shortlog (not (null (memq (if dir-present 'directory 'file)
+                                    vc-log-short-style))))
        (buffer-name "*vc-change-log*")
-       type)
-    (dolist (file files)
-      (when (file-directory-p file)
-       (setq dir-present t)))
-    (setq vc-short-log
-         (not (null (if dir-present
-                        (memq 'directory vc-log-short-style)
-                      (memq 'file vc-log-short-style)))))
-    (setq type (if vc-short-log 'short 'long))
-    (let ((shortlog vc-short-log))
+         (type (if shortlog 'short 'long)))
       (vc-log-internal-common
        backend buffer-name files type
        (lambda (bk buf _type-arg files-arg)
@@ -2239,7 +2222,7 @@ earlier revisions.  Show up to LIMIT entries (non-nil means unlimited)."
         (vc-call-backend bk 'show-log-entry working-revision))
        (lambda (_ignore-auto _noconfirm)
         (vc-print-log-internal backend files working-revision
-                                is-start-revision limit))))))
+                              is-start-revision limit)))))
 
 (defvar vc-log-view-type nil
   "Set this to differentiate the different types of logs.")
@@ -2258,15 +2241,18 @@ earlier revisions.  Show up to LIMIT entries (non-nil means unlimited)."
     (with-current-buffer (get-buffer-create buffer-name)
       (set (make-local-variable 'vc-log-view-type) type))
     (setq retval (funcall backend-func backend buffer-name type files))
+    (with-current-buffer (get-buffer buffer-name)
+      (let ((inhibit-read-only t))
+       ;; log-view-mode used to be called with inhibit-read-only bound
+       ;; to t, so let's keep doing it, just in case.
+       (vc-call-backend backend 'log-view-mode)
+       (set (make-local-variable 'log-view-vc-backend) backend)
+       (set (make-local-variable 'log-view-vc-fileset) files)
+       (set (make-local-variable 'revert-buffer-function)
+            rev-buff-func)))
+    ;; Display after setting up major-mode, so display-buffer-alist can know
+    ;; the major-mode.
     (pop-to-buffer buffer-name)
-    (let ((inhibit-read-only t))
-      ;; log-view-mode used to be called with inhibit-read-only bound
-      ;; to t, so let's keep doing it, just in case.
-      (vc-call-backend backend 'log-view-mode)
-      (set (make-local-variable 'log-view-vc-backend) backend)
-      (set (make-local-variable 'log-view-vc-fileset) files)
-      (set (make-local-variable 'revert-buffer-function)
-          rev-buff-func))
     (vc-run-delayed
      (let ((inhibit-read-only t))
        (funcall setup-buttons-func backend files retval)
@@ -2373,6 +2359,29 @@ When called interactively with a prefix argument, prompt for REMOTE-LOCATION."
     (vc-incoming-outgoing-internal backend remote-location "*vc-outgoing*"
                                    'log-outgoing)))
 
+;;;###autoload
+(defun vc-region-history (from to)
+  "Show the history of the region FROM..TO."
+  (interactive "r")
+  (let* ((lfrom (line-number-at-pos from))
+         (lto   (line-number-at-pos to))
+         (file buffer-file-name)
+         (backend (vc-backend file))
+         (buf (get-buffer-create "*VC-history*")))
+    (with-current-buffer buf
+      (setq-local vc-log-view-type 'long))
+    (vc-call region-history file buf lfrom lto)
+    (with-current-buffer buf
+      (vc-call-backend backend 'region-history-mode)
+      (set (make-local-variable 'log-view-vc-backend) backend)
+      (set (make-local-variable 'log-view-vc-fileset) file)
+      (set (make-local-variable 'revert-buffer-function)
+          (lambda (_ignore-auto _noconfirm)
+             (with-current-buffer buf
+               (let ((inhibit-read-only t)) (erase-buffer)))
+             (vc-call region-history file buf lfrom lto))))
+    (display-buffer buf)))
+
 ;;;###autoload
 (defun vc-revert ()
   "Revert working copies of the selected fileset to their repository contents.
@@ -2505,14 +2514,14 @@ tip revision are merged into the working file."
                    (and file (member file files))))))
       (dolist (file files)
        (if (vc-up-to-date-p file)
-           (vc-checkout file nil t)
+           (vc-checkout file t)
          (vc-maybe-resolve-conflicts
           file (vc-call-backend backend 'merge-news file)))))
      ;; For a locking VCS, check out each file.
      ((eq (vc-checkout-model backend files) 'locking)
       (dolist (file files)
        (if (vc-up-to-date-p file)
-           (vc-checkout file nil t))))
+           (vc-checkout file t))))
      (t
       (error "VC update is unsupported for `%s'" backend)))))
 
@@ -2634,7 +2643,7 @@ backend to NEW-BACKEND, and unregister FILE from the current backend.
          (when modified-file
            (vc-switch-backend file new-backend)
            (unless (eq (vc-checkout-model new-backend (list file)) 'implicit)
-             (vc-checkout file t nil))
+             (vc-checkout file))
            (rename-file modified-file file 'ok-if-already-exists)
            (vc-file-setprop file 'vc-checkout-time nil)))))
     (when move
@@ -2645,34 +2654,7 @@ backend to NEW-BACKEND, and unregister FILE from the current backend.
     (when (or move edited)
       (vc-file-setprop file 'vc-state 'edited)
       (vc-mode-line file new-backend)
-      (vc-checkin file new-backend nil comment (stringp comment)))))
-
-(defun vc-rename-master (oldmaster newfile templates)
-  "Rename OLDMASTER to be the master file for NEWFILE based on TEMPLATES."
-  (let* ((dir (file-name-directory (expand-file-name oldmaster)))
-        (newdir (or (file-name-directory newfile) ""))
-        (newbase (file-name-nondirectory newfile))
-        (masters
-         ;; List of potential master files for `newfile'
-         (mapcar
-          (lambda (s) (vc-possible-master s newdir newbase))
-          templates)))
-    (when (or (file-symlink-p oldmaster)
-             (file-symlink-p (file-name-directory oldmaster)))
-      (error "This is unsafe in the presence of symbolic links"))
-    (rename-file
-     oldmaster
-     (catch 'found
-       ;; If possible, keep the master file in the same directory.
-       (dolist (f masters)
-        (when (and f (string= (file-name-directory (expand-file-name f)) dir))
-          (throw 'found f)))
-       ;; If not, just use the first possible place.
-       (dolist (f masters)
-        (and f (or (not (setq dir (file-name-directory f)))
-                   (file-directory-p dir))
-             (throw 'found f)))
-       (error "New file lacks a version control directory")))))
+      (vc-checkin file new-backend comment (stringp comment)))))
 
 ;;;###autoload
 (defun vc-delete-file (file)
@@ -2807,19 +2789,12 @@ log entries should be gathered."
 The default is to return nil always."
   nil)
 
-(defun vc-default-could-register (_backend _file)
-  "Return non-nil if BACKEND could be used to register FILE.
-The default implementation returns t for all files."
-  t)
-
 (defun vc-default-latest-on-branch-p (_backend _file)
   "Return non-nil if FILE is the latest on its branch.
 This default implementation always returns non-nil, which means that
 editing non-current revisions is not supported by default."
   t)
 
-(defun vc-default-init-revision (_backend) vc-default-init-revision)
-
 (defun vc-default-find-revision (backend file rev buffer)
   "Provide the new `find-revision' op based on the old `checkout' op.
 This is only for compatibility with old backends.  They should be updated