Commit 0e362f54 authored by Gerd Moellmann's avatar Gerd Moellmann
Browse files

(vc-next-action-on-file): Do not visit the file if it's

not necessary.  If verbose in state `needs-patch', do the same as
under `up-to-date'.  When NOT verbose and `needs-patch', check out
latest version instead of `merge-news'.
(vc-next-action-dired): Don't mess with default-directory here; it
breaks other parts of dired.  It is the job of the
backend-specific functions to adjust it temporarily if they need
(vc-next-action): Remove a special CVS case.
(vc-clear-headers): New optional arg FILE.
(vc-checkin, vc-checkout): Set properties vc-state and
vc-checkout-time properly.
(vc-finish-steal): Call steal-lock, not steal, which doesn't
(vc-print-log): Use new backend function `show-log-entry'.
(vc-cancel-version): Do the checks in a different order.  Added a
FIXME concerning RCS-only code.
(vc-responsible-backend): New optional arg `register'.
(vc-default-could-register): New function.
(vc-dired-buffers-for-dir, vc-dired-resynch-file): New functions.
(vc-resynch-buffer): Call vc-dired-resynch-file.
(vc-start-entry, vc-finish-logentry, vc-revert-buffer): Use
vc-resynch-buffer instead of vc-resynch-window.
(vc-next-action-dired): Don't redisplay here, that gets done as a
result of the individual file operations.
(vc-retrieve-snapshot): Corrected prompt order.
(vc-version-diff): Use `require' to check for existence of
(vc-do-command): Doc fix.
(vc-finish-logentry): When checking in from vc-dired, choose the
right backend for logentry check.
(vc-dired-mode-map): Inherit from dired-mode-map.
(vc-dired-mode): Local value of dired-move-to-filename-regexp
(vc-dired-state-info): Removed, updated caller.
(vc-default-dired-state-info): Use parentheses instead of hyphens.
(vc-dired-hook): Use vc-BACKEND-dir-state, if available.
(vc-dired-listing-switches): New variable.
(vc-directory): Use it, instead of dired-listing-switches.
(vc-revert-buffer): Hide the frame for dedicated windows
(vc-update-changelog): Split into generic part and default
implementation.  Doc string adapted.
(vc-default-update-changelog): New function.  Call the `rcs2log'
script in exec-directory, to fix a long-standing nuisance.
(vc-next-action-on-file): Doc fix.
(vc-maybe-resolve-conflicts): Don't just toggle smerge-mode.
(vc-print-log): Eval `file' before constructing the continuation.
(vc-next-action-on-file): Corrected several messages.
(vc-merge): Add prefix arg `merge-news'; handle it.
(vc-finish-logentry): Thinko in the "same comment"
(vc-parent-buffer, vc-parent-buffer-name): Protect them
against kill-all-local-variables.
(vc-log-edit): Don't save vc-parent-buffer any more.
(vc-last-comment-match): Initialize to an empty string.
(vc-post-command-functions): New hook.
(vc-do-command): Run it.
(vc-next-action-on-file): Remove unnecessary pop-to-buffer.
(vc-finish-logentry): Only add the comment to the ring if it's
different from the last comment entered.
(vc-new-comment-index): New function.
(vc-previous-comment): Use it.  Make the minibuffer message
slightly less terse.
(vc-comment-search-reverse): Make it work forward as well.  Don't
set vc-comment-ring-index if no match is found.  Use
(vc-comment-search-forward): Use vc-comment-search-reverse.
(vc-dired-mode-map): Don't inherit from dired-mode-map since
define-derived-mode will do it for us.  Bind `v' to a keymap that
inherits from vc-prefix-map so that we can bind `vt' without
binding C-x v t.
(vc-retrieve-snapshot): Parenthesis typo.
(vc-create-snapshot, vc-default-create-snapshot): Swap DIR
and NAME.
(vc-retrieve-snapshot): Split into two parts.
(vc-default-retrieve-snapshot): New function.
(vc-do-command): Remove unused commands.
(vc-version-diff): Make sure default-directory ends with a slash.
Move the window commands into a vc-exec-after.
(vc-print-log): Move more of the code into the `vc-exec-after'.
(vc-exec-after): Fix disassembly of previous sentinel.
(vc-print-log): Search current revision from beginning of buffer.
(vc-revert-buffer): Clear echo area after the diff is finished.
(vc-prefix-map): Removed definition of "t" for terse display in vc
(vc-dired-mode-map): Inherit from dired-mode-map.  Added
definition of "vt" for terse display.
(vc-dired-mode): Fix dired-move-to-filename-regexp.
(vc-exec-after): Avoid caddr.
(vc-exec-after): New function.
(vc-do-command): Use it to add a termination message for async
(vc-checkout): Try to handle a missing-backend situation.
(vc-version-diff): Use vc-exec-after to fix the behavior for diffs
of a directory with a backend using async diffs.
(vc-print-log): Use vc-exec-after and use log-view-goto-rev if
(vc-next-action-on-file): Use vc-revert-buffer to revert
when there are no changes.
(vc-prefix-map): Move the autoload to vc-hooks.el and move
the `fset' outside of the defvar so that it works even if
vc-prefix-map was already defined.
(vc-setup-buffer): New function, split out of vc-do-command.
(vc-do-command): Allow BUFFER to be t to mean `just use the
current buffer without any fuss'.
(vc-version-diff): Change the `diff' backend operation to just put
the diff in the current buffer without erasing it.  Always use
(vc-workfile-unchanged-p): If checkout-time comparison is
not possible, use vc-BACKEND-workfile-unchanged-p.
(vc-default-workfile-unchanged-p): New function.  Delegates to a
full vc-BACKEND-diff.
(vc-editable-p): Renamed from vc-writable-p.
(with-vc-file, vc-merge): Use vc-editable-p.
(vc-do-command): Remove unused var vc-file and fix the
doubly-defined `status' var.  Add a user message when starting an
async command.
(vc-restore-buffer-context, vc-resynch-buffer, vc-start-entry)
(vc-finish-steal, vc-checkin, vc-finish-logentry, vc-rename-file):
Use with-current-buffer.
(vc-buffer-sync): Use unless.
(vc-next-action-on-file): If the file is 'edited by read-only,
make it read-write instead of trying to commit.
(vc-version-diff, vc-update-change-log): Use `setq
default-directory' rather than `cd'.
(vc-log-edit): Don't forget to set default-directory in the
(vc-checkout): Don't do anything special for ange-ftp
files since ange-ftp already has vc-registered return nil.
(vc-do-command): Use file-relative-name.
(vc-responsible-backend): Use vc-backend if possible.
(vc-create-snapshot): Improve the `interactive' spec. Add support
for branches and dispatch to backend-specific `create-snapshot'.
(vc-default-create-snapshot): New function, containing the bulk of
the old vc-create-snapshot.
(vc-retrieve-snapshot): Improve the interactive spec.
(vc-do-command): Get rid of the `last' argument.
(vc-header-alist): Remove, replaced by vc-X-header.
(vc-insert-headers): Use vc-X-header instead of vc-header-alist.
(vc-dired-hook): Use expand-file-name instead of concat.
(vc-directory): Use file-name-as-directory.
(vc-snapshot-precondition, vc-create-snapshot)
(vc-retrieve-snapshot): Allow the command to operate on any
 Update Copyright and add a crude list of backend funs.
(vc-writable-p): New function.
(with-vc-file): Use vc-writable-p.
(vc-next-action-on-file): Update call to vc-steal-lock and
(vc-register): Avoid vc-name.
(vc-locking-user): Remove.
(vc-steal-lock): Make the `owner' arg non-optional.
(vc-merge): Use vc-writable-p instead of vc-locking-user and
(vc-default-dired-state-info): Use vc-state instead of
vc-locking-user and return special strings for special states.
(vc-dired-hook): Use vc-up-to-date-p instead of vc-locking-user
and get rid of one of the special CVS cases.
(vc-cancel-version): prettify error message with \\[...].
(vc-rename-master): New function.
(vc-rename-file): Use vc-BACKEND-rename-file (which might in turn
use vc-rename-master) instead of vc-BACKEND-record-rename.  Make
the CVS special case generic.
(vc-default-record-rename): Remove.
(vc-file-tree-walk-internal): Only call FUNC for files that are
under control of some VC backend and replace `concat' with
(vc-file-tree-walk): Update docstring.
(vc-version-diff, vc-snapshot-precondition, vc-create-snapshot)
(vc-retrieve-snapshot): Update call to vc-file-tree-walk.
(vc-version-diff): Expand file name read from the
minibuffer.  Handle the case when a previous version number can't
be guessed.  Give suitable messages when there were no differences
(vc-clear-headers): Call backend-specific implementation, if one
(vc-cancel-version): Made error checks generic.  When done, clear
headers generically, too.
(vc-locking-user): Moved from vc-hooks.el.
(vc-version-diff): Left out a vc- in call to
(vc-default-dired-state-info, vc-default-record-rename)
(vc-default-merge-news): Update for the new backend argument.
(vc-merge): Use vc-find-backend-function.
(vc-register): Put a FIXME note for a newly found bug.
Call vc-call-backend without the leading vc-.
(vc-responsible-backend, vc-finish-logentry, vc-annotate)
(vc-check-headers): Call vc-call-backend without the leading vc-.
(vc-annotate-time-span): Replace confusing use of `cond' with
(vc-annotate-display): Replace confusing use of `cond' with `or'.
Call vc-call-backend without the leading vc-.
(vc-process-filter): New function.
(vc-do-command): Setup `vc-process-filter' for the async process.
(vc-maybe-resolve-conflicts): New function to reduce
code-duplication.  Additionally, it puts the buffer in
`smerge-mode' if applicable.
(vc-next-action-on-file): Use `vc-maybe-resolve-conflicts' after
calling `merge-news'.
(vc-merge): Use `vc-maybe-resolve-conflicts' after calling
(vc-log-edit): New function.  Replacement for `vc-log-mode' by
interfacing to log-edit.el.
(vc-start-entry): Call `vc-log-edit' instead of `vc-log-mode' if
log-edit is available.
(vc-resolve-conflicts): Delegate to `smerge-ediff' if available.
(vc-register): Remove `vc-buffer-backend' setup.
(vc-log-mode-map): New name for vc-log-entry-mode and merge the
defvar and the initialization.
(vc-log-mode): Minor docstring fix and use vc-log-mode-map.
(vc-file-clear-masterprops): Removed.
(vc-checkin, vc-revert-buffer): Removed calls to the above.
(vc-version-diff): Use buffer-size without argument.
(vc-register): Heed vc-initial-comment.
(vc-workfile-unchanged-p): Remove unused argument
`want-differences-if-changed' and simplify.
(vc-next-action-on-file) [needs-merge]: Resynch the buffer.
(vc-revert-buffer): Use `unchanged-p' rather than vc-diff's status
output (which is invalid for async vc-diff) to decide whether to
do the revert silently or not.
(with-vc-file, vc-next-action, vc-version-diff)
(vc-dired-mark-locked): Replaced usage of vc-locking-user with
vc-state or vc-up-to-date-p.
(vc-merge): Use vc-backend-defines to check whether merging is
possible.  Set state to 'edited after successful merge.
(vc-recompute-state, vc-next-action-on-file): Update to
new `vc-state' semantics.
(vc-finish-steal): Set 'vc-state to 'edited rather than setting
'vc-locking-user to the current user.
(vc-merge): Inline vc-backend-merge.  Comment out code that I
don't understand and hence can't adapt to the new `vc-state' and
`vc-locking-user' semantics.
(vc-backend-merge): Remove.
(vc-do-command): kill-all-local-variables, to reset any
major-mode in which the buffer might have been put earlier.  Use
`remove' and `when'.  Allow `okstatus' to be `async' and use
`start-process' in this case.
(vc-version-diff): Handle the case where the diff looks empty
because of the use of an async process.
(vc-next-action-on-file): Removed optional parameter
`simple'.  Recompute state unconditionally.
(vc-default-toggle-read-only): Removed.
(vc-backend-dispatch, vc-annotate-mode-syntax-table):
(vc-prefix-map): Move from vc-hooks.el and make autoloaded.
(vc-release-greater-or-equal-p): Move to vc-rcs.el.
(vc-file-clear-masterprops): Braindead "fix".  It was a nop and
still is. So maybe it should be removed.
(vc-head-version, vc-find-binary): Remove.
(vc-recompute-state): Move from vc-hooks.el.
(vc-next-action-on-file): Add a `simple' argument to allow
avoiding the `recompute' step (use for vc-cvs-simple-toggle).
(vc-default-toggle-read-only, vc-default-record-rename): New
(vc-next-action, vc-dired-hook): Use vc-state instead of
(vc-dired-mode-map): Properly defvar it.
(vc-print-log): Call log-view-mode if available.
(small-temporary-file-directory): defvar instead of use boundp.
(vc-merge-news): Moved to vc-cvs.el.
(vc-default-merge-news): New function.
(function' quotes.
(vc-annotate-mode-map, vc-annotate-mode-syntax-table): Initialize
directly in the defvar.
(vc-do-command): Bind inhibit-read-only so as to properly handle
the case where the destination buffer has been made read-only.
(vc-diff): Delegate to vc-version-diff in all cases.
(vc-version-diff): Setup the *vc-diff* buffer as was done in
(vc-annotate-mode-variables): Removed (code moved partly to
defvars and partly to vc-annotate-add-menu).
(vc-annotate-mode): Turned into a derived-mode.
(vc-annotate-add-menu): Moved in code in
(vc-update-change-log): Use make-temp-file if available.
(vc-next-action-on-file): Added handling of state
(vc-checkout-carefully): Is now practically obsolete, unless the
above is too slow to be enabled unconditionally.
(vc-update-change-log): Fixed typo.
(vc-responsible-backend): New function.
(vc-register): Largely rewritten.
(vc-admin): Removed (implementation moved into vc-register).
(vc-checkin): Redocumented.
(vc-finish-logentry): If no backend defined yet (because we are in
the process of registering), use the responsible backend.
 Updated callers of `vc-checkout-required' to use
(vc-backend-release, vc-backend-release-p): Functions
moved into vc-rcs.el
(vc-backend-revert): Function moved into `vc-revert';
`vc-next-action' must be updated to accomodate this change.
(vc-backend-steal): Function moved into `vc-finish-steal'.
(vc-backend-logentry-check): Function moved into
(vc-backend-printlog): Function moved into `vc-print-log'.
(vc-backend-uncheck): Function moved into `vc-cancel-version'.
(vc-backend-assign-name): Function moved into
(vc-workfile-unchanged-p,vc-diff,vc-version-diff): Updated
to use the vc-BACKEND-diff functions instead; `vc-diff' is now
 Typo fixed.  This checkin is made with our new VC code
base for the very first time.  A simple `(vc-checkin
(buffer-file-name))' was used to perform it.
(vc-checkin): Merged with `vc-backend-checkin' and updated
to match the split into various backends.
(vc-backend-checkin): Removed.  Merged with `vc-checkin'.
(vc-retrieve-snapshot): Bug fix.
(vc-next-action-on-file): Bug found and fixed.
(vc-checkout, vc-version-other-window, vc-retrieve-snapshot)
(vc-cancel-version): Handle of vc-BACKEND-checkout updated.
(vc-next-action-on-file): Rewritten for the new state model.
(vc-backend-merge-news): Renamed to `vc-merge-news'.  (Specific parts
still need to be split, and implemented for RCS).
(vc-admin): Updated to handle selection of appropriate
backend.  Current implementation is crufty and need re-thinking.
(vc-annotate-get-backend, vc-annotate-display-default)
(vc-annotate-add-menu, vc-annotate, vc-annotate-display): Annotate
functionality updated quite a lot to support multiple backends.
Variables `vc-annotate-mode', `vc-annotate-buffers',
`vc-annotate-backend' added.
`vc-uses-locking' to `vc-checkout-required'.  Renamed the `locked'
state to `reserved'.
(vc-update-change-log): Use small-temporary-file-directory,
if defined.  (Merged from main line, slightly adapted.)
 Split the annotate feature into a BACKEND specific part
and moved it from the vc-cvs.el file to this one.
(vc-resynch-window): Added TODO comment: check for
interaction with view mode according to recent RCS change.
(vc-backend-merge-news): Merged "CMUP" patch from mainline.
 Converted the remaining function comments to
documentation strings.
(vc-backend-release, vc-release-greater-or-equal)
(vc-backend-release-p, vc-trunk-p, vc-branch-p, vc-branch-part)
(vc-minor-part, vc-previous-version): Functions that operate and
compare revision numbers got proper documentation.  Comments added
about their possible removal.
(vc-latest-on-branch-p): Function removed and replaced in
the vc-backend.el files.
(vc-backend-diff): Function removed and placed in the
backend files.
(vc-backend-checkout): Function removed and replaced in
the vc-backend.el files.
(vc-backend-admin): Removed and replaced in the
vc-backend.el files.
(Martin): Removed all the annotate functionality since it
is CVS backend specific.
 [Merged from mainline.]
(vc-dired-mode): Make the dired-move-to-filename-regexp
regexp match the date, to avoid treating date as file size.
Add YYYY S option to WESTERN/
 Require `compile' when compiling.
(vc-logentry-check-hook): New option.
(vc-steal-lock): Use compose-mail.
(vc-dired-mode-map): Defvar when compiling.
(vc-add-triple, vc-record-rename, vc-lookup-triple): Moved to
vc-sccs.el and renamed.  Callers changed.
(vc-backend-checkout, vc-backend-logentry-check)
(vc-backend-merge-news): Doc fix.
(vc-default-logentry-check): New function.
(vc-backend-checkin, vc-backend-revert, vc-backend-steal)
(vc-backend-uncheck, vc-backend-print-log, vc-backend-assign-name)
(vc-backend-merge): Doc fix.  Use backend functions.
(vc-check-headers): Use backend functions.
(vc-backend-release): Call vc-system-release.
(vc-rcs-release, vc-cvs-release, vc-sccs-release): Moved to
backend files.
(vc-backend-release): Dispatch to backend functions.
(vc-backend-release-p): Don't mention CVS, RCS.  [The SCCS case
probably needs attention.]
(vc-dired-mode, vc-dired-reformat-line, vc-dired-purge):
Doc fix.
(vc-fetch-cvs-status): Moved to vc-cvs.el and renamed.
(vc-default-dired-state-info): New function.
(vc-dired-state-info): Dispatch to backends.
(vc-dired-hook): Doc fix.  Simplify, pending removal of CVS specifics.
(vc-file-clear-masterprops, vc-latest-on-branch-p)
(vc-version-other-window, vc-backend-assign-name): Removed
references to vc-latest-version; sometimes changed into
(with-vc-file, vc-next-action-on-file, vc-merge)
(vc-backend-checkout): Changed calls to `vc-checkout-model' to
(vc-fetch-cvs-status): Use renamed vc-cvs-parse-status.
 Some doc fixes for autoloaded and interactive functions.
Fix compilation warnings from ediff stuff.
(vc-rcs-release, vc-cvs-release, vc-sccs-release): Custom fix.
 This is 1999-03-13T05:04:24Z! from the emacs sources
parent 39efdf3f
;;; vc.el --- drive a version-control system from within Emacs
;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
;; Copyright (C) 1992,93,94,95,96,97,98,2000 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <>
;; Maintainer: Andre Spiegel <>
;; Author: FSF (see below for full credits)
;; Maintainer: Andre Spiegel <>
;; $Id: vc.el,v 1.259 2000/01/26 10:31:13 gerd Exp $
;; $Id: vc.el,v 1.1 2000/09/04 19:35:57 gerd Exp gerd $
;; This file is part of GNU Emacs.
......@@ -24,17 +24,25 @@
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Credits:
;; VC was initially designed and implemented by Eric S. Raymond
;; <>. Over the years, many people have
;; contributed substantial amounts of work to VC. These include:
;; Per Cederqvist <>
;; Paul Eggert <>
;; Sebastian Kremer <>
;; Martin Lorentzson <>
;; Dave Love <>
;; Stefan Monnier <>
;; Andre Spiegel <>
;; Richard Stallman <>
;;; Commentary:
;; This mode is fully documented in the Emacs user's manual.
;; This was designed and implemented by Eric Raymond <>.
;; Paul Eggert <>, Sebastian Kremer <>,
;; and Richard Stallman contributed valuable criticism, support, and testing.
;; CVS support was added by Per Cederqvist <>
;; in Jan-Feb 1994. Further enhancements came from and
;; Andre Spiegel <>.
;; Supported version-control systems presently include SCCS, RCS, and CVS.
;; Some features will not work with old RCS versions. Where
......@@ -45,8 +53,7 @@
;; doesn't understand -t-; this has been known to happen to people running
;; NExTSTEP 3.0.
;; You can support the RCS -x option by adding pairs to the
;; vc-master-templates list.
;; You can support the RCS -x option by customizing vc-rcs-master-templates.
;; Proper function of the SCCS diff commands requires the shellscript vcdiff
;; to be installed somewhere on Emacs's path for executables.
......@@ -54,11 +61,6 @@
;; If your site uses the ChangeLog convention supported by Emacs, the
;; function vc-comment-to-change-log should prove a useful checkin hook.
;; This code depends on call-process passing back the subprocess exit
;; status. Thus, you need Emacs 18.58 or later to run it. For the
;; vc-directory command to work properly as documented, you need 19.
;; You also need Emacs 19's ring.el.
;; The vc code maintains some internal state in order to reduce expensive
;; version-control operations to a minimum. Some names are only computed
;; once. If you perform version control operations with RCS/SCCS/CVS while
......@@ -70,32 +72,90 @@
;;; Code:
;;;;;;;;;;;;;;;;; Backend-specific functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; for each operation FUN, the backend should provide a function vc-BACKEND-FUN.
;; Operations marked with a `-' instead of a `*' have a sensible default
;; behavior.
;; * registered (file)
;; * state (file)
;; - state-heuristic (file)
;; The default behavior delegates to `state'.
;; - dir-state (dir)
;; * checkout-model (file)
;; - mode-line-string (file)
;; * workfile-version (file)
;; * revert (file)
;; * merge-news (file)
;; * merge (file rev1 rev2)
;; * steal-lock (file &optional version)
;; * register (file rev comment)
;; * responsible-p (file)
;; Should also work if FILE is a directory (ends with a slash).
;; - could-register (file)
;; * checkout (file writable &optional rev destfile)
;; Checkout revision REV of FILE into DESTFILE.
;; DESTFILE defaults to FILE.
;; The file should be made writable if WRITABLE is non-nil.
;; REV can be nil (BASE) or "" (HEAD) or any other revision.
;; * checkin (file rev comment)
;; - logentry-check ()
;; * diff (file &optional rev1 rev2)
;; Insert the diff for FILE into the current buffer.
;; REV1 should default to workfile-version.
;; REV2 should default to the current workfile
;; Return a status of either 0 (i.e. no diff) or 1 (i.e. either non-empty
;; diff or the diff is run asynchronously).
;; - workfile-unchanged-p (file)
;; Return non-nil if FILE is unchanged from its current workfile version.
;; This function should do a brief comparison of FILE's contents
;; with those of the master version. 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.
;; - clear-headers ()
;; * check-headers ()
;; - dired-state-info (file)
;; - create-snapshot (dir name branchp)
;; Take a snapshot of the current state of files under DIR and name it NAME.
;; This should make sure that files are up-to-date before proceeding
;; with the action.
;; DIR can also be a file and if BRANCHP is specified, NAME
;; should be created as a branch and DIR should be checked out under
;; this new branch. The default behavior does not support branches
;; but does a sanity check, a tree traversal and for each file calls
;; `assign-name'.
;; * assign-name (file name)
;; Give name NAME to the current version of FILE, assuming it is
;; up-to-date. Only used by the default version of `create-snapshot'.
;; - retrieve-snapshot (dir name update)
;; Retrieve a named snapshot of all registered files at or below DIR.
;; If UPDATE is non-nil, then update buffers of any files in the snapshot
;; that are currently visited.
;; * print-log (file)
;; Insert the revision log of FILE into the current buffer.
;; - show-log-entry (version)
;; - update-changelog (files)
;; Find changelog entries for FILES, or for all files at or below
;; the default-directory if FILES is nil.
;; * latest-on-branch-p (file)
;; Only used for sanity check before calling `uncheck'.
;; * uncheck (file target)
;; * rename-file (old new)
;; * annotate-command (file buf)
;; * annotate-difference (pos)
(require 'vc-hooks)
(require 'ring)
(eval-when-compile (require 'dired)) ; for dired-map-over-marks macro
(require 'compile)
(require 'dired)) ; for dired-map-over-marks macro
(if (not (assoc 'vc-parent-buffer minor-mode-alist))
(setq minor-mode-alist
(cons '(vc-parent-buffer vc-parent-buffer-name)
;; To implement support for a new version-control system, add another
;; branch to the vc-backend-dispatch macro and fill it in in each
;; call. The variable vc-master-templates in vc-hooks.el will also
;; have to change.
(defmacro vc-backend-dispatch (f s r c)
"Execute FORM1, FORM2 or FORM3 for SCCS, RCS or CVS respectively.
If FORM3 is `RCS', use FORM2 for CVS as well as RCS.
\(CVS shares some code with RCS)."
(list 'let (list (list 'type (list 'vc-backend f)))
(list 'cond
(list (list 'eq 'type (quote 'SCCS)) s) ;; SCCS
(list (list 'eq 'type (quote 'RCS)) r) ;; RCS
(list (list 'eq 'type (quote 'CVS)) ;; CVS
(if (eq c 'RCS) r c))
;; General customization
(defgroup vc nil
......@@ -122,7 +182,7 @@ preserve the setting."
(defcustom vc-default-init-version "1.1"
"*A string used as the default version number when a new file is registered.
This can be overriden by giving a prefix argument to \\[vc-register]."
This can be overridden by giving a prefix argument to \\[vc-register]."
:type 'string
:group 'vc
:version "20.3")
......@@ -162,6 +222,12 @@ These are passed to the checkin program by \\[vc-register]."
:group 'vc)
(defcustom vc-dired-listing-switches "-al"
"*Switches passed to `ls' for vc-dired. MUST contain the `l' option."
:type 'string
:group 'vc
:version "21.0")
(defcustom vc-dired-recurse t
"*If non-nil, show directory trees recursively in VC Dired."
:type 'boolean
......@@ -184,8 +250,31 @@ These are passed to the checkin program by \\[vc-register]."
;;; This is duplicated in diff.el.
(defvar diff-switches "-c"
"*A string or list of strings specifying switches to be be passed to diff.")
"*A string or list of strings specifying switches to be passed to diff.")
(defcustom vc-checkin-hook nil
"*Normal hook (list of functions) run after a checkin is done.
See `run-hooks'."
:type 'hook
:options '(vc-comment-to-change-log)
:group 'vc)
(defcustom vc-before-checkin-hook nil
"*Normal hook (list of functions) run before a file gets checked in.
See `run-hooks'."
:type 'hook
:group 'vc)
(defcustom vc-logentry-check-hook nil
"*Normal hook run by `vc-backend-logentry-check'.
Use this to impose your own rules on the entry in addition to any the
version control backend imposes itself."
:type 'hook
:group 'vc)
;; Annotate customization
(defcustom vc-annotate-color-map
'(( 26.3672 . "#FF0000")
( 52.7344 . "#FF3800")
......@@ -207,7 +296,7 @@ These are passed to the checkin program by \\[vc-register]."
"*Association list of age versus color, for \\[vc-annotate].
Ages are given in units of 2**-16 seconds.
Default is eighteen steps using a twenty day increment."
:type 'sexp
:type 'alist
:group 'vc)
(defcustom vc-annotate-very-old-color "#0046FF"
......@@ -224,52 +313,30 @@ Default color is used if nil."
(defcustom vc-annotate-menu-elements '(2 0.5 0.1 0.01)
"*Menu elements for the mode-specific menu of VC-Annotate mode.
List of factors, used to expand/compress the time scale. See `vc-annotate'."
:type 'sexp
:type '(repeat number)
:group 'vc)
(defcustom vc-checkin-hook nil
"*Normal hook (list of functions) run after a checkin is done.
See `run-hooks'."
:type 'hook
:options '(vc-comment-to-change-log)
:group 'vc)
;; vc-annotate functionality (CVS only).
(defvar vc-annotate-mode nil
"Variable indicating if VC-Annotate mode is active.")
(defcustom vc-before-checkin-hook nil
"*Normal hook (list of functions) run before a file gets checked in.
See `run-hooks'."
:type 'hook
:group 'vc)
(defvar vc-annotate-mode-map
(let ((m (make-sparse-keymap)))
(define-key m [menu-bar] (make-sparse-keymap "VC-Annotate"))
"Local keymap used for VC-Annotate mode.")
(defcustom vc-annotate-mode-hook nil
"*Hooks to run when VC-Annotate mode is turned on."
:type 'hook
:group 'vc)
(defvar vc-annotate-mode-menu nil
"Local keymap used for VC-Annotate mode's menu bar menu.")
;; Header-insertion hair
(defcustom vc-header-alist
'((SCCS "\%W\%") (RCS "\$Id\$") (CVS "\$Id\$"))
"*Header keywords to be inserted by `vc-insert-headers'.
Must be a list of two-element lists, the first element of each must
be `RCS', `CVS', or `SCCS'. The second element is the string to
be inserted for this particular backend."
:type '(repeat (list :format "%v"
(choice :tag "System"
(const SCCS)
(const RCS)
(const CVS))
(string :tag "Header")))
:group 'vc)
(defcustom vc-static-header-alist
'(("\\.c$" .
"\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n#endif /* lint */\n"))
"*Associate static header string templates with file types. A \%s in the
template is replaced with the first string associated with the file's
version-control type in `vc-header-alist'."
"*Associate static header string templates with file types.
A \%s in the template is replaced with the first string associated with
the file's version-control type in `vc-header-alist'."
:type '(repeat (cons :format "%v"
(regexp :tag "File Type")
(string :tag "Header String")))
......@@ -288,6 +355,9 @@ is sensitive to blank lines."
:group 'vc)
;; Default is to be extra careful for super-user.
;; TODO: This variable is no longer used; the corresponding checks
;; are always done now. If that turns out to be fast enough,
;; the variable can be obsoleted.
(defcustom vc-checkout-carefully (= (user-uid) 0)
"*Non-nil means be extra-careful in checkout.
Verify that the file really is not locked
......@@ -295,44 +365,61 @@ and that its contents match what the master file says."
:type 'boolean
:group 'vc)
(defcustom vc-rcs-release nil
"*The release number of your RCS installation, as a string.
If nil, VC itself computes this value when it is first needed."
:type '(choice (const :tag "Auto" nil)
(const :tag "Unknown" unknown))
:group 'vc)
(defcustom vc-sccs-release nil
"*The release number of your SCCS installation, as a string.
If nil, VC itself computes this value when it is first needed."
:type '(choice (const :tag "Auto" nil)
(const :tag "Unknown" unknown))
:group 'vc)
;;; The main keymap
(defvar vc-prefix-map
(let ((map (make-sparse-keymap)))
(define-key map "a" 'vc-update-change-log)
(define-key map "c" 'vc-cancel-version)
(define-key map "d" 'vc-directory)
(define-key map "g" 'vc-annotate)
(define-key map "h" 'vc-insert-headers)
(define-key map "i" 'vc-register)
(define-key map "l" 'vc-print-log)
(define-key map "m" 'vc-merge)
(define-key map "r" 'vc-retrieve-snapshot)
(define-key map "s" 'vc-create-snapshot)
(define-key map "u" 'vc-revert-buffer)
(define-key map "v" 'vc-next-action)
(define-key map "=" 'vc-diff)
(define-key map "~" 'vc-version-other-window)
(fset 'vc-prefix-map vc-prefix-map)
(defcustom vc-cvs-release nil
"*The release number of your CVS installation, as a string.
If nil, VC itself computes this value when it is first needed."
:type '(choice (const :tag "Auto" nil)
(const :tag "Unknown" unknown))
:group 'vc)
;; Initialization code, to be done just once at load-time
(defvar vc-log-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\M-n" 'vc-next-comment)
(define-key map "\M-p" 'vc-previous-comment)
(define-key map "\M-r" 'vc-comment-search-reverse)
(define-key map "\M-s" 'vc-comment-search-forward)
(define-key map "\C-c\C-c" 'vc-finish-logentry)
;; Compatibility with old name. Should we bother ?
(defvar vc-log-entry-mode vc-log-mode-map)
;; Variables the user doesn't need to know about.
(defvar vc-log-entry-mode nil)
(defvar vc-log-operation nil)
(defvar vc-log-after-operation-hook nil)
(defvar vc-checkout-writable-buffer-hook 'vc-checkout-writable-buffer)
(defvar vc-annotate-buffers nil
"An association list of current \"Annotate\" buffers and their
corresponding backends. The keys are \(BUFFER . BACKEND\). See also
;; In a log entry buffer, this is a local variable
;; that points to the buffer for which it was made
;; (either a file, or a VC dired buffer).
(defvar vc-parent-buffer nil)
(put 'vc-parent-buffer 'permanent-local t)
(defvar vc-parent-buffer-name nil)
(put 'vc-parent-buffer-name 'permanent-local t)
(defvar vc-log-file)
(defvar vc-log-version)
;; FIXME: only used in vc-sccs.el
(defconst vc-name-assoc-file "VC-names")
(defvar vc-dired-mode nil)
......@@ -340,93 +427,30 @@ If nil, VC itself computes this value when it is first needed."
(defvar vc-comment-ring (make-ring vc-maximum-comment-ring-size))
(defvar vc-comment-ring-index nil)
(defvar vc-last-comment-match nil)
;;; Find and compare backend releases
(defun vc-backend-release (backend)
;; Returns which backend release is installed on this system.
((eq backend 'RCS)
(or vc-rcs-release
(and (zerop (vc-do-command nil nil "rcs" nil nil "-V"))
(set-buffer (get-buffer "*vc*"))
(setq vc-rcs-release
(car (vc-parse-buffer
'(("^RCS version \\([0-9.]+ *.*\\)" 1)))))))
(setq vc-rcs-release 'unknown)))
((eq backend 'CVS)
(or vc-cvs-release
(and (zerop (vc-do-command nil 1 "cvs" nil nil "-v"))
(set-buffer (get-buffer "*vc*"))
(setq vc-cvs-release
(car (vc-parse-buffer
'(("^Concurrent Versions System (CVS) \\([0-9.]+\\)"
(setq vc-cvs-release 'unknown)))
((eq backend 'SCCS)
(defun vc-release-greater-or-equal (r1 r2)
;; Compare release numbers, represented as strings.
;; Release components are assumed cardinal numbers, not decimal
;; fractions (5.10 is a higher release than 5.9). Omitted fields
;; are considered lower (5.6.7 is earlier than
;; Comparison runs till the end of the string is found, or a
;; non-numeric component shows up (5.6.7 is earlier than "5.6.7 beta",
;; which is probably not what you want in some cases).
;; This code is suitable for existing RCS release numbers.
;; CVS releases are handled reasonably, too (1.3 < 1.4* < 1.5).
(let (v1 v2 i1 i2)
(catch 'done
(or (and (string-match "^\\.?\\([0-9]+\\)" r1)
(setq i1 (match-end 0))
(setq v1 (string-to-number (match-string 1 r1)))
(or (and (string-match "^\\.?\\([0-9]+\\)" r2)
(setq i2 (match-end 0))
(setq v2 (string-to-number (match-string 1 r2)))
(if (> v1 v2) (throw 'done t)
(if (< v1 v2) (throw 'done nil)
(throw 'done
(substring r1 i1)
(substring r2 i2)))))))
(throw 'done t)))
(or (and (string-match "^\\.?\\([0-9]+\\)" r2)
(throw 'done nil))
(throw 'done t)))))
(defun vc-backend-release-p (backend release)
;; Return t if we have RELEASE of BACKEND or better
(let (i r (ri 0) (ii 0) is rs (installation (vc-backend-release backend)))
(if (not (eq installation 'unknown))
((or (eq backend 'RCS) (eq backend 'CVS))
(vc-release-greater-or-equal installation release))))))
;;; functions that operate on RCS revision numbers
(defvar vc-last-comment-match "")
;;; functions that operate on RCS revision numbers. This code should
;;; also be moved into the backends. It stays for now, however, since
;;; it is used in code below.
(defun vc-trunk-p (rev)
;; return t if REV is a revision on the trunk
"Return t if REV is a revision on the trunk"
(not (eq nil (string-match "\\`[0-9]+\\.[0-9]+\\'" rev))))
(defun vc-branch-p (rev)
;; return t if REV is a branch revision
"Return t if REV is a branch revision"
(not (eq nil (string-match "\\`[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*\\'" rev))))
(defun vc-branch-part (rev)
;; return the branch part of a revision number REV
"return the branch part of a revision number REV"
(substring rev 0 (string-match "\\.[0-9]+\\'" rev)))
(defun vc-minor-part (rev)
;; return the minor version number of a revision number REV
"Return the minor version number of a revision number REV"
(string-match "[0-9]+\\'" rev)
(substring rev (match-beginning 0) (match-end 0)))
(defun vc-previous-version (rev)
;; guess the previous version number
"Guess the previous version number"
(let ((branch (vc-branch-part rev))
(minor-num (string-to-number (vc-minor-part rev))))
(if (> minor-num 1)
......@@ -450,86 +474,36 @@ If nil, VC itself computes this value when it is first needed."
;; log buffer with a nonzero local value of vc-comment-ring-index.
(setq vc-comment-ring (make-ring vc-maximum-comment-ring-size)))
(defun vc-file-clear-masterprops (file)
;; clear all properties of FILE that were retrieved
;; from the master file
(vc-file-setprop file 'vc-latest-version nil)
(vc-file-setprop file 'vc-your-latest-version nil)
(vc-backend-dispatch file
(progn ;; SCCS
(vc-file-setprop file 'vc-master-locks nil))
(progn ;; RCS
(vc-file-setprop file 'vc-default-branch nil)
(vc-file-setprop file 'vc-head-version nil)
(vc-file-setprop file 'vc-master-workfile-version nil)
(vc-file-setprop file 'vc-master-locks nil))
(vc-file-setprop file 'vc-cvs-status nil))))
(defun vc-head-version (file)
;; Return the RCS head version of FILE
(cond ((vc-file-getprop file 'vc-head-version))
(t (vc-fetch-master-properties file)
(vc-file-getprop file 'vc-head-version))))
;; Random helper functions
(defun vc-latest-on-branch-p (file)
;; return t iff the current workfile version of FILE is
;; the latest on its branch.
(vc-backend-dispatch file
(string= (vc-workfile-version file) (vc-latest-version file))
;; RCS
(let ((workfile-version (vc-workfile-version file)) tip-version)
(if (vc-trunk-p workfile-version)
;; Re-fetch the head version number. This is to make
;; sure that no-one has checked in a new version behind
;; our back.
(vc-fetch-master-properties file)
(string= (vc-file-getprop file 'vc-head-version)
;; If we are not on the trunk, we need to examine the
;; whole current branch. (vc-master-workfile-version
;; is not what we need.)
(set-buffer (get-buffer-create "*vc-info*"))
(vc-insert-file (vc-name file) "^desc")
(setq tip-version (car (vc-parse-buffer (list (list
(concat "^\\(" (regexp-quote (vc-branch-part workfile-version))
"\\.[0-9]+\\)\ndate[ \t]+\\([0-9.]+\\);") 1 2)))))
(if (get-buffer "*vc-info*")
(kill-buffer (get-buffer "*vc-info*")))
(string= tip-version workfile-version))))
;; CVS
(defsubst vc-editable-p (file)
(or (eq (vc-checkout-model file) 'implicit)
(eq (vc-state file) 'edited)
(eq (vc-state file) 'needs-merge)))
;;; Two macros for elisp programming
(defmacro with-vc-file (file comment &rest body)
"Execute BODY, checking out a writable copy of FILE first if necessary.
After BODY has been executed, check-in FILE with COMMENT (a string).
"Check out a writable copy of FILE if necessary and execute the body.
Check in FILE with COMMENT (a string) after BODY has been executed.
FILE is passed through `expand-file-name'; BODY executed within
`save-excursion'. If FILE is not under version control, or locked by
somebody else, signal error."
`(let ((file (expand-file-name ,file)))
(or (vc-registered file)
(error (format "File not under version control: `%s'" file)))
(let ((locking-user (vc-locking-user file)))
(cond ((and (not locking-user)
(eq (vc-checkout-model file) 'manual))
(vc-checkout file t))
((and (stringp locking-user)
(not (string= locking-user (vc-user-login-name))))
(error (format "`%s' is locking `%s'" locking-user file)))))
(unless (vc-editable-p file)
(let ((state (vc-state file)))
(if (stringp state) (error (format "`%s' is locking `%s'" state file))
(vc-checkout file t))))
(vc-checkin file nil ,comment)))
(defmacro edit-vc-file (file comment &rest body)
"Edit FILE under version control, executing BODY. Checkin with COMMENT.
"Edit FILE under version control, executing body.
Checkin with COMMENT after executing BODY.
This macro uses `with-vc-file', passing args to it.
However, before executing BODY, find FILE, and after BODY, save buffer."
......@@ -539,7 +513,8 @@ However, before executing BODY, find FILE, and after BODY, save buffer."
(defun vc-ensure-vc-buffer ()
;; Make sure that the current buffer visits a version-controlled file.
"Make sure that the current buffer visits a version-controlled
(if vc-dired-mode
(set-buffer (find-file-noselect (dired-get-filename)))
(while vc-parent-buffer
......@@ -554,69 +529,88 @@ However, before executing BODY, find FILE, and after BODY, save buffer."
(if (memq system-type '(ms-dos windows-nt))
'(".exe" ".com" ".bat" ".cmd" ".btm" "")
(defun vc-find-binary (name)
"Look for a command anywhere on the subprocess-command search path."
(or (cdr (assoc name vc-binary-assoc))
(catch 'found
(lambda (s)
(if s
(let ((full (concat s "/" name))
(suffixes vc-binary-suffixes)
(while suffixes
(setq candidate (concat full (car suffixes)))
(if (and (file-executable-p candidate)