Add @top to some misc/*.texi files.
[bpt/emacs.git] / lisp / vc / vc.el
CommitLineData
66321b2f 1;;; vc.el --- drive a version-control system from within Emacs
594722a8 2
95df8112 3;; Copyright (C) 1992-1998, 2000-2011 Free Software Foundation, Inc.
594722a8 4
0e362f54
GM
5;; Author: FSF (see below for full credits)
6;; Maintainer: Andre Spiegel <spiegel@gnu.org>
9766adfb 7;; Keywords: vc tools
594722a8
ER
8
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
594722a8 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
594722a8
ER
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
594722a8 23
0e362f54
GM
24;;; Credits:
25
26;; VC was initially designed and implemented by Eric S. Raymond
61de26cb 27;; <esr@thyrsus.com> in 1992. Over the years, many other people have
0e362f54 28;; contributed substantial amounts of work to VC. These include:
61de26cb 29;;
0e362f54
GM
30;; Per Cederqvist <ceder@lysator.liu.se>
31;; Paul Eggert <eggert@twinsun.com>
32;; Sebastian Kremer <sk@thp.uni-koeln.de>
33;; Martin Lorentzson <martinl@gnu.org>
166a0ef7 34;; Dave Love <fx@gnu.org>
0e362f54 35;; Stefan Monnier <monnier@cs.yale.edu>
7fbb4797
DN
36;; Thien-Thi Nguyen <ttn@gnu.org>
37;; Dan Nicolaescu <dann@ics.uci.edu>
6f1ecae4 38;; J.D. Smith <jdsmith@alum.mit.edu>
0e362f54
GM
39;; Andre Spiegel <spiegel@gnu.org>
40;; Richard Stallman <rms@gnu.org>
61de26cb
ER
41;;
42;; In July 2007 ESR returned and redesigned the mode to cope better
43;; with modern version-control systems that do commits by fileset
44;; rather than per individual file.
45;;
a7192ddb
SM
46;; If you maintain a client of the mode or customize it in your .emacs,
47;; note that some backend functions which formerly took single file arguments
61de26cb
ER
48;; now take a list of files. These include: register, checkin, print-log,
49;; rollback, and diff.
0e362f54 50
594722a8
ER
51;;; Commentary:
52
1a2f456b
ER
53;; This mode is fully documented in the Emacs user's manual.
54;;
c0edfa75 55;; Supported version-control systems presently include CVS, RCS, GNU
6aa5d910 56;; Arch, Subversion, Bzr, Git, Mercurial, Monotone and SCCS
5e8c0b8b 57;; (or its free replacement, CSSC).
b0c9bc8c 58;;
1a2f456b 59;; If your site uses the ChangeLog convention supported by Emacs, the
93a142e1
DN
60;; function `log-edit-comment-to-change-log' could prove a useful checkin hook,
61;; although you might prefer to use C-c C-a (i.e. `log-edit-insert-changelog')
1cca5da4 62;; from the commit buffer instead or to set `log-edit-setup-invert'.
1a2f456b 63;;
004f9b3f
ER
64;; When using SCCS, RCS, CVS: be careful not to do repo surgery, or
65;; operations like registrations and deletions and renames, outside VC
66;; while VC is running. The support for these systems was designed
67;; when disks were much slower, and the code maintains a lot of
68;; internal state in order to reduce expensive operations to a
69;; minimum. Thus, if you mess with the repo while VC's back is turned,
70;; VC may get seriously confused.
71;;
72;; When using Subversion or a later system, anything you do outside VC
73;; *through the VCS tools* should safely interlock with VC
74;; operations. Under these VC does little state caching, because local
75;; operations are assumed to be fast. The dividing line is
594722a8 76;;
fcb500ea
AS
77;; ADDING SUPPORT FOR OTHER BACKENDS
78;;
79;; VC can use arbitrary version control systems as a backend. To add
80;; support for a new backend named SYS, write a library vc-sys.el that
81;; contains functions of the form `vc-sys-...' (note that SYS is in lower
82;; case for the function and library names). VC will use that library if
83;; you put the symbol SYS somewhere into the list of
84;; `vc-handled-backends'. Then, for example, if `vc-sys-registered'
85;; returns non-nil for a file, all SYS-specific versions of VC commands
86;; will be available for that file.
87;;
88;; VC keeps some per-file information in the form of properties (see
89;; vc-file-set/getprop in vc-hooks.el). The backend-specific functions
90;; do not generally need to be aware of these properties. For example,
ac3f4c6f 91;; `vc-sys-working-revision' should compute the working revision and
fcb500ea
AS
92;; return it; it should not look it up in the property, and it needn't
93;; store it there either. However, if a backend-specific function does
94;; store a value in a property, that value takes precedence over any
99cb8c8b 95;; value that the generic code might want to set (check for uses of
fcb500ea
AS
96;; the macro `with-vc-properties' in vc.el).
97;;
98;; In the list of functions below, each identifier needs to be prepended
99;; with `vc-sys-'. Some of the functions are mandatory (marked with a
100;; `*'), others are optional (`-').
2c3160c5 101
8cdd17b4
ER
102;; BACKEND PROPERTIES
103;;
104;; * revision-granularity
105;;
61de26cb
ER
106;; Takes no arguments. Returns either 'file or 'repository. Backends
107;; that return 'file have per-file revision numbering; backends
108;; that return 'repository have per-repository revision numbering,
109;; so a revision level implicitly identifies a changeset
2c3160c5 110
fcb500ea
AS
111;; STATE-QUERYING FUNCTIONS
112;;
0e362f54 113;; * registered (file)
fcb500ea 114;;
37a5e97a 115;; Return non-nil if FILE is registered in this backend. Both this
73770b03
DN
116;; function as well as `state' should be careful to fail gracefully
117;; in the event that the backend executable is absent. It is
118;; preferable that this function's body is autoloaded, that way only
119;; calling vc-registered does not cause the backend to be loaded
120;; (all the vc-FOO-registered functions are called to try to find
121;; the controlling backend for FILE.
fcb500ea 122;;
99cb8c8b 123;; * state (file)
fcb500ea
AS
124;;
125;; Return the current version control state of FILE. For a list of
126;; possible values, see `vc-state'. This function should do a full and
127;; reliable state computation; it is usually called immediately after
128;; C-x v v. If you want to use a faster heuristic when visiting a
3702367b 129;; file, put that into `state-heuristic' below. Note that under most
4903369a 130;; VCSes this won't be called at all, dir-status is used instead.
fcb500ea 131;;
0e362f54 132;; - state-heuristic (file)
fcb500ea
AS
133;;
134;; If provided, this function is used to estimate the version control
135;; state of FILE at visiting time. It should be considerably faster
136;; than the implementation of `state'. For a list of possible values,
137;; see the doc string of `vc-state'.
138;;
c1b51374 139;; - dir-status (dir update-function)
00ca5ce2 140;;
1b3f2d4e
DN
141;; Produce RESULT: a list of lists of the form (FILE VC-STATE EXTRA)
142;; for the files in DIR.
143;; EXTRA can be used for backend specific information about FILE.
144;; If a command needs to be run to compute this list, it should be
145;; run asynchronously using (current-buffer) as the buffer for the
146;; command. When RESULT is computed, it should be passed back by
c1b51374 147;; doing: (funcall UPDATE-FUNCTION RESULT nil).
d63aa41f 148;; If the backend uses a process filter, hence it produces partial results,
5a84a937 149;; they can be passed back by doing:
c1b51374
SM
150;; (funcall UPDATE-FUNCTION RESULT t)
151;; and then do a (funcall UPDATE-FUNCTION RESULT nil)
5a84a937 152;; when all the results have been computed.
e1aec6fb 153;; To provide more backend specific functionality for `vc-dir'
13ad7457
DN
154;; the following functions might be needed: `dir-extra-headers',
155;; `dir-printer', `extra-dir-menu' and `dir-status-files'.
00ca5ce2 156;;
fb0ac090
AJ
157;; - dir-status-files (dir files default-state update-function)
158;;
159;; This function is identical to dir-status except that it should
160;; only report status for the specified FILES. Also it needs to
161;; report on all requested files, including up-to-date or ignored
162;; files. If not provided, the default is to consider that the files
163;; are in DEFAULT-STATE.
164;;
13ad7457 165;; - dir-extra-headers (dir)
115c0061 166;;
e1aec6fb 167;; Return a string that will be added to the *vc-dir* buffer header.
15c5c970 168;;
13ad7457 169;; - dir-printer (fileinfo)
58f10bff 170;;
e1aec6fb 171;; Pretty print the `vc-dir-fileinfo' FILEINFO.
58f10bff 172;; If a backend needs to show more information than the default FILE
e1aec6fb
SM
173;; and STATE in the vc-dir listing, it can store that extra
174;; information in `vc-dir-fileinfo->extra'. This function can be
175;; used to display that extra information in the *vc-dir* buffer.
58f10bff 176;;
5a84a937
DN
177;; - status-fileinfo-extra (file)
178;;
e1aec6fb 179;; Compute `vc-dir-fileinfo->extra' for FILE.
5a84a937 180;;
ac3f4c6f 181;; * working-revision (file)
fcb500ea 182;;
ac3f4c6f 183;; Return the working revision of FILE. This is the revision fetched
61de26cb 184;; by the last checkout or upate, not necessarily the same thing as the
a7192ddb 185;; head or tip revision. Should return "0" for a file added but not yet
61de26cb 186;; committed.
fcb500ea
AS
187;;
188;; - latest-on-branch-p (file)
189;;
ac3f4c6f
ER
190;; Return non-nil if the working revision of FILE is the latest revision
191;; on its branch (many VCSes call this the 'tip' or 'head' revision).
0d0e9356 192;; The default implementation always returns t, which means that
ac3f4c6f 193;; working with non-current revisions is not supported by default.
fcb500ea 194;;
e0607aaa 195;; * checkout-model (files)
fcb500ea 196;;
e0607aaa 197;; Indicate whether FILES need to be "checked out" before they can be
fcb500ea
AS
198;; edited. See `vc-checkout-model' for a list of possible values.
199;;
aae91380 200;; - workfile-unchanged-p (file)
fcb500ea 201;;
ac3f4c6f
ER
202;; Return non-nil if FILE is unchanged from the working revision.
203;; This function should do a brief comparison of FILE's contents
004f9b3f 204;; with those of the repository copy of the working revision. If
ac3f4c6f
ER
205;; the backend does not have such a brief-comparison feature, the
206;; default implementation of this function can be used, which
207;; delegates to a full vc-BACKEND-diff. (Note that vc-BACKEND-diff
208;; must not run asynchronously in this case, see variable
0d0e9356 209;; `vc-disable-async-diff'.)
fcb500ea 210;;
0e362f54 211;; - mode-line-string (file)
fcb500ea 212;;
3a12f9f8 213;; If provided, this function should return the VC-specific mode
a7192ddb 214;; line string for FILE. The returned string should have a
3a12f9f8
DN
215;; `help-echo' property which is the text to be displayed as a
216;; tooltip when the mouse hovers over the VC entry on the mode-line.
217;; The default implementation deals well with all states that
218;; `vc-state' can return.
fcb500ea 219;;
fcb500ea
AS
220;; STATE-CHANGING FUNCTIONS
221;;
61de26cb 222;; * create-repo (backend)
8cdd17b4 223;;
a7192ddb
SM
224;; Create an empty repository in the current directory and initialize
225;; it so VC mode can add files to it. For file-oriented systems, this
8cdd17b4
ER
226;; need do no more than create a subdirectory with the right name.
227;;
228;; * register (files &optional rev comment)
fcb500ea 229;;
8cdd17b4
ER
230;; Register FILES in this backend. Optionally, an initial revision REV
231;; and an initial description of the file, COMMENT, may be specified,
232;; but it is not guaranteed that the backend will do anything with this.
ecd50f65 233;; The implementation should pass the value of vc-register-switches
a7192ddb 234;; to the backend command. (Note: in older versions of VC, this
8cdd17b4 235;; command took a single file argument and not a list.)
fcb500ea 236;;
ac3f4c6f 237;; - init-revision (file)
b470cb65 238;;
ac3f4c6f 239;; The initial revision to use when registering FILE if one is not
b470cb65 240;; specified by the user. If not provided, the variable
ac3f4c6f 241;; vc-default-init-revision is used instead.
b470cb65 242;;
099bd78a 243;; - responsible-p (file)
fcb500ea
AS
244;;
245;; Return non-nil if this backend considers itself "responsible" for
246;; FILE, which can also be a directory. This function is used to find
247;; out what backend to use for registration of new files and for things
248;; like change log generation. The default implementation always
249;; returns nil.
250;;
0e362f54 251;; - could-register (file)
fcb500ea
AS
252;;
253;; Return non-nil if FILE could be registered under this backend. The
254;; default implementation always returns t.
255;;
aae91380 256;; - receive-file (file rev)
fcb500ea
AS
257;;
258;; Let this backend "receive" a file that is already registered under
259;; another backend. The default implementation simply calls `register'
260;; for FILE, but it can be overridden to do something more specific,
261;; e.g. keep revision numbers consistent or choose editing modes for
262;; FILE that resemble those of the other backend.
263;;
264;; - unregister (file)
265;;
266;; Unregister FILE from this backend. This is only needed if this
267;; backend may be used as a "more local" backend for temporary editing.
268;;
e97a42c1 269;; * checkin (files rev comment)
fcb500ea 270;;
e97a42c1
SM
271;; Commit changes in FILES to this backend. REV is a historical artifact
272;; and should be ignored. COMMENT is used as a check-in comment.
273;; The implementation should pass the value of vc-checkin-switches to
274;; the backend command.
fcb500ea 275;;
ac3f4c6f 276;; * find-revision (file rev buffer)
fd8160f7
SM
277;;
278;; Fetch revision REV of file FILE and put it into BUFFER.
279;; If REV is the empty string, fetch the head of the trunk.
280;; The implementation should pass the value of vc-checkout-switches
281;; to the backend command.
282;;
9e6da495 283;; * checkout (file &optional editable rev)
fcb500ea
AS
284;;
285;; Check out revision REV of FILE into the working area. If EDITABLE
286;; is non-nil, FILE should be writable by the user and if locking is
287;; used for FILE, a lock should also be set. If REV is non-nil, that
ac3f4c6f 288;; is the revision to check out (default is the working revision).
4279775b
AS
289;; If REV is t, that means to check out the head of the current branch;
290;; if it is the empty string, check out the head of the trunk.
291;; The implementation should pass the value of vc-checkout-switches
fd8160f7 292;; to the backend command.
fcb500ea 293;;
bbfc07d3 294;; * revert (file &optional contents-done)
fcb500ea 295;;
ac3f4c6f 296;; Revert FILE back to the working revision. If optional
bbfc07d3
AS
297;; arg CONTENTS-DONE is non-nil, then the contents of FILE have
298;; already been reverted from a version backup, and this function
299;; only needs to update the status of FILE within the backend.
239b3340
DN
300;; If FILE is in the `added' state it should be returned to the
301;; `unregistered' state.
fcb500ea 302;;
8cdd17b4 303;; - rollback (files)
fcb500ea 304;;
ac3f4c6f
ER
305;; Remove the tip revision of each of FILES from the repository. If
306;; this function is not provided, trying to cancel a revision is
8cdd17b4
ER
307;; caught as an error. (Most backends don't provide it.) (Also
308;; note that older versions of this backend command were called
309;; 'cancel-version' and took a single file arg, not a list of
310;; files.)
fcb500ea 311;;
aae91380 312;; - merge (file rev1 rev2)
fcb500ea 313;;
2c3160c5
CY
314;; Merge the changes between REV1 and REV2 into the current working file
315;; (for non-distributed VCS).
316;;
3d92f44e 317;; - merge-branch ()
2c3160c5 318;;
3d92f44e
CY
319;; Merge another branch into the current one, prompting for a
320;; location to merge from.
fcb500ea 321;;
aae91380 322;; - merge-news (file)
fcb500ea
AS
323;;
324;; Merge recent changes from the current branch into FILE.
2c3160c5
CY
325;; (for non-distributed VCS).
326;;
327;; - pull (prompt)
328;;
329;; Pull "upstream" changes into the current branch (for distributed
330;; VCS). If PROMPT is non-nil, or if necessary, prompt for a
331;; location to pull from.
fcb500ea 332;;
ac3f4c6f 333;; - steal-lock (file &optional revision)
fcb500ea 334;;
ac3f4c6f 335;; Steal any lock on the working revision of FILE, or on REVISION if
0d0e9356
ER
336;; that is provided. This function is only needed if locking is
337;; used for files under this backend, and if files can indeed be
338;; locked by other users.
fcb500ea 339;;
9b64a7f0
ER
340;; - modify-change-comment (files rev comment)
341;;
df49d02e 342;; Modify the change comments associated with the files at the
9b64a7f0
ER
343;; given revision. This is optional, many backends do not support it.
344;;
7fbb4797
DN
345;; - mark-resolved (files)
346;;
347;; Mark conflicts as resolved. Some VC systems need to run a
348;; command to mark conflicts as resolved.
2c3160c5 349
fcb500ea
AS
350;; HISTORY FUNCTIONS
351;;
662c5698 352;; * print-log (files buffer &optional shortlog start-revision limit)
fcb500ea 353;;
6616006b 354;; Insert the revision log for FILES into BUFFER.
32ba3abc 355;; If SHORTLOG is true insert a short version of the log.
48b27575
DN
356;; If LIMIT is true insert only insert LIMIT log entries. If the
357;; backend does not support limiting the number of entries to show
358;; it should return `limit-unsupported'.
662c5698
DN
359;; If START-REVISION is given, then show the log starting from the
360;; revision. At this point START-REVISION is only required to work
361;; in conjunction with LIMIT = 1.
fcb500ea 362;;
31527c56
DN
363;; * log-outgoing (backend remote-location)
364;;
365;; Insert in BUFFER the revision log for the changes that will be
366;; sent when performing a push operation to REMOTE-LOCATION.
367;;
368;; * log-incoming (backend remote-location)
369;;
370;; Insert in BUFFER the revision log for the changes that will be
371;; received when performing a pull operation from REMOTE-LOCATION.
372;;
37a5e97a
SM
373;; - log-view-mode ()
374;;
375;; Mode to use for the output of print-log. This defaults to
376;; `log-view-mode' and is expected to be changed (if at all) to a derived
377;; mode of `log-view-mode'.
378;;
ac3f4c6f 379;; - show-log-entry (revision)
fcb500ea 380;;
ac3f4c6f 381;; If provided, search the log entry for REVISION in the current buffer,
fcb500ea
AS
382;; and make sure it is displayed in the buffer's window. The default
383;; implementation of this function works for RCS-style logs.
384;;
aae91380 385;; - comment-history (file)
fcb500ea 386;;
d6ba9c39 387;; Return a string containing all log entries that were made for FILE.
fcb500ea 388;; This is used for transferring a file from one backend to another,
f0fbfd43 389;; retaining comment information.
fcb500ea 390;;
aae91380 391;; - update-changelog (files)
fcb500ea
AS
392;;
393;; Using recent log entries, create ChangeLog entries for FILES, or for
394;; all files at or below the default-directory if FILES is nil. The
395;; default implementation runs rcs2log, which handles RCS- and
396;; CVS-style logs.
397;;
d7b60083 398;; * diff (files &optional rev1 rev2 buffer)
fcb500ea 399;;
ac9ff209
AS
400;; Insert the diff for FILE into BUFFER, or the *vc-diff* buffer if
401;; BUFFER is nil. If REV1 and REV2 are non-nil, report differences
ac3f4c6f
ER
402;; from REV1 to REV2. If REV1 is nil, use the working revision (as
403;; found in the repository) as the older revision; if REV2 is nil,
404;; use the current working-copy contents as the newer revision. This
405;; function should pass the value of (vc-switches BACKEND 'diff) to
406;; the backend command. It should return a status of either 0 (no
407;; differences found), or 1 (either non-empty diff or the diff is
408;; run asynchronously).
fcb500ea 409;;
a7192ddb 410;; - revision-completion-table (files)
4d83a657 411;;
a7192ddb 412;; Return a completion table for existing revisions of FILES.
4d83a657
SM
413;; The default is to not use any completion table.
414;;
3c42cc64 415;; - annotate-command (file buf &optional rev)
fcb500ea 416;;
3c42cc64 417;; If this function is provided, it should produce an annotated display
ac3f4c6f 418;; of FILE in BUF, relative to revision REV. Annotation means each line
3c42cc64
TTN
419;; of FILE displayed is prefixed with version information associated with
420;; its addition (deleted lines leave no history) and that the text of the
421;; file is fontified according to age.
fcb500ea 422;;
75665141 423;; - annotate-time ()
fcb500ea
AS
424;;
425;; Only required if `annotate-command' is defined for the backend.
75665141
AS
426;; Return the time of the next line of annotation at or after point,
427;; as a floating point fractional number of days. The helper
428;; function `vc-annotate-convert-time' may be useful for converting
429;; multi-part times as returned by `current-time' and `encode-time'
0ff9b955 430;; to this format. Return nil if no more lines of annotation appear
75665141
AS
431;; in the buffer. You can safely assume that point is placed at the
432;; beginning of each line, starting at `point-min'. The buffer that
433;; point is placed in is the Annotate output, as defined by the
946b248f
TTN
434;; relevant backend. This function also affects how much of the line
435;; is fontified; where it leaves point is where fontification begins.
75665141
AS
436;;
437;; - annotate-current-time ()
438;;
439;; Only required if `annotate-command' is defined for the backend,
440;; AND you'd like the current time considered to be anything besides
cb223bba 441;; (vc-annotate-convert-time (current-time)) -- i.e. the current
75665141
AS
442;; time with hours, minutes, and seconds included. Probably safe to
443;; ignore. Return the current-time, in units of fractional days.
fcb500ea 444;;
1b5a7343
AS
445;; - annotate-extract-revision-at-line ()
446;;
447;; Only required if `annotate-command' is defined for the backend.
448;; Invoked from a buffer in vc-annotate-mode, return the revision
449;; corresponding to the current line, or nil if there is no revision
450;; corresponding to the current line.
d1e4c403
DN
451;; If the backend supports annotating through copies and renames,
452;; and displays a file name and a revision, then return a cons
453;; (REVISION . FILENAME).
2c3160c5 454
370fded4 455;; TAG SYSTEM
fcb500ea 456;;
370fded4 457;; - create-tag (dir name branchp)
fcb500ea 458;;
370fded4
ER
459;; Attach the tag NAME to the state of the working copy. This
460;; should make sure that files are up-to-date before proceeding with
461;; the action. DIR can also be a file and if BRANCHP is specified,
462;; NAME should be created as a branch and DIR should be checked out
463;; under this new branch. The default implementation does not
464;; support branches but does a sanity check, a tree traversal and
465;; assigns the tag to each file.
fcb500ea 466;;
370fded4 467;; - retrieve-tag (dir name update)
fcb500ea 468;;
370fded4 469;; Retrieve the version tagged by NAME of all registered files at or below DIR.
fcb500ea 470;; If UPDATE is non-nil, then update buffers of any files in the
370fded4 471;; tag that are currently visited. The default implementation
fcb500ea
AS
472;; does a sanity check whether there aren't any uncommitted changes at
473;; or below DIR, and then performs a tree walk, using the `checkout'
ac3f4c6f 474;; function to retrieve the corresponding revisions.
2c3160c5 475
fcb500ea
AS
476;; MISCELLANEOUS
477;;
aae91380 478;; - make-version-backups-p (file)
fcb500ea 479;;
ac3f4c6f 480;; Return non-nil if unmodified repository revisions of FILE should be
fcb500ea
AS
481;; backed up locally. If this is done, VC can perform `diff' and
482;; `revert' operations itself, without calling the backend system. The
483;; default implementation always returns nil.
484;;
32ba3abc
DN
485;; - root (file)
486;; Return the root of the VC controlled hierarchy for file.
487;;
a36319a4
SM
488;; - repository-hostname (dirname)
489;;
490;; Return the hostname that the backend will have to contact
491;; in order to operate on a file in DIRNAME. If the return value
0452b6e7 492;; is nil, it means that the repository is local.
a36319a4
SM
493;; This function is used in `vc-stay-local-p' which backends can use
494;; for their convenience.
495;;
ac3f4c6f 496;; - previous-revision (file rev)
869131a5 497;;
ac3f4c6f
ER
498;; Return the revision number that precedes REV for FILE, or nil if no such
499;; revision exists.
1b5a7343 500;;
ac3f4c6f 501;; - next-revision (file rev)
1b5a7343 502;;
ac3f4c6f
ER
503;; Return the revision number that follows REV for FILE, or nil if no such
504;; revision exists.
869131a5 505;;
09158997
DN
506;; - log-edit-mode ()
507;;
508;; Turn on the mode used for editing the check in log. This
509;; defaults to `log-edit-mode'. If changed, it should use a mode
510;; derived from`log-edit-mode'.
511;;
aae91380 512;; - check-headers ()
fcb500ea
AS
513;;
514;; Return non-nil if the current buffer contains any version headers.
515;;
aae91380 516;; - clear-headers ()
fcb500ea
AS
517;;
518;; In the current buffer, reset all version headers to their unexpanded
519;; form. This function should be provided if the state-querying code
520;; for this backend uses the version headers to determine the state of
521;; a file. This function will then be called whenever VC changes the
522;; version control state in such a way that the headers would give
523;; wrong information.
524;;
a36319a4
SM
525;; - delete-file (file)
526;;
527;; Delete FILE and mark it as deleted in the repository. If this
528;; function is not provided, the command `vc-delete-file' will
529;; signal an error.
530;;
099bd78a 531;; - rename-file (old new)
fcb500ea
AS
532;;
533;; Rename file OLD to NEW, both in the working area and in the
a36319a4
SM
534;; repository. If this function is not provided, the renaming
535;; will be done by (vc-delete-file old) and (vc-register new).
86a65190 536;;
6e54fa53
SM
537;; - find-file-hook ()
538;;
81c63b50 539;; Operation called in current buffer when opening a file. This can
6e54fa53 540;; be used by the backend to setup some local variables it might need.
cb223bba 541;;
cb223bba
DN
542;; - extra-menu ()
543;;
544;; Return a menu keymap, the items in the keymap will appear at the
545;; end of the Version Control menu. The goal is to allow backends
546;; to specify extra menu items that appear in the VC menu. This way
547;; you can provide menu entries for functionality that is specific
548;; to your backend and which does not map to any of the VC generic
549;; concepts.
6656ecaa 550;;
13ad7457 551;; - extra-dir-menu ()
6656ecaa 552;;
25a4ea6d
DN
553;; Return a menu keymap, the items in the keymap will appear at the
554;; end of the VC Status menu. The goal is to allow backends to
555;; specify extra menu items that appear in the VC Status menu. This
556;; makes it possible to provide menu entries for functionality that
557;; is specific to a backend and which does not map to any of the VC
558;; generic concepts.
e97a42c1
SM
559;;
560;; - conflicted-files (dir)
561;;
562;; Return the list of files where conflict resolution is needed in
563;; the project that contains DIR.
564;; FIXME: what should it do with non-text conflicts?
aae91380 565
ba463d9e
DN
566;;; Todo:
567
de7a9afa
SM
568;; - Get rid of the "master file" terminology.
569
ee91bfdf
SM
570;; - Add key-binding for vc-delete-file.
571
2e4f4469
ER
572;;;; New Primitives:
573;;
fc30d544
DN
574;; - deal with push/pull operations.
575;;
2e4f4469
ER
576;; - add a mechanism for editing the underlying VCS's list of files
577;; to be ignored, when that's possible.
fc30d544 578;;
84cb74cf
DN
579;;;; Primitives that need changing:
580;;
581;; - vc-update/vc-merge should deal with VC systems that don't
582;; update/merge on a file basis, but on a whole repository basis.
583;; vc-update and vc-merge assume the arguments are always files,
584;; they don't deal with directories. Make sure the *vc-dir* buffer
f0fbfd43 585;; is updated after these operations.
84cb74cf
DN
586;; At least bzr, git and hg should benefit from this.
587;;
2e4f4469 588;;;; Improved branch and tag handling:
7fbb4797 589;;
fc30d544
DN
590;; - add a generic mechanism for remembering the current branch names,
591;; display the branch name in the mode-line. Replace
592;; vc-cvs-sticky-tag with that.
593;;
2e4f4469
ER
594;;;; Internal cleanups:
595;;
596;; - backends that care about vc-stay-local should try to take it into
ee91bfdf 597;; account for vc-dir. Is this likely to be useful??? YES!
2e4f4469
ER
598;;
599;; - vc-expand-dirs should take a backend parameter and only look for
600;; files managed by that backend.
601;;
602;; - Another important thing: merge all the status-like backend operations.
603;; We should remove dir-status, state, and dir-status-files, and
604;; replace them with just `status' which takes a fileset and a continuation
605;; (like dir-status) and returns a buffer in which the process(es) are run
606;; (or nil if it worked synchronously). Hopefully we can define the old
607;; 4 operations in term of this one.
608;;
609;;;; Other
610;;
611;; - when a file is in `conflict' state, turn on smerge-mode.
612;;
613;; - figure out what to do with conflicts that are not caused by the
614;; file contents, but by metadata or other causes. Example: File A
615;; gets renamed to B in one branch and to C in another and you merge
616;; the two branches. Or you locally add file FOO and then pull a
617;; change that also adds a new file FOO, ...
618;;
fc30d544
DN
619;; - make it easier to write logs. Maybe C-x 4 a should add to the log
620;; buffer, if one is present, instead of adding to the ChangeLog.
ba463d9e 621;;
5bd20ee6
DN
622;; - When vc-next-action calls vc-checkin it could pre-fill the
623;; *VC-log* buffer with some obvious items: the list of files that
624;; were added, the list of files that were removed. If the diff is
625;; available, maybe it could even call something like
626;; `diff-add-change-log-entries-other-window' to create a detailed
627;; skeleton for the log...
628;;
e1aec6fb 629;; - most vc-dir backends need more work. They might need to
7fbb4797
DN
630;; provide custom headers, use the `extra' field and deal with all
631;; possible VC states.
632;;
8234f5be 633;; - add a function that calls vc-dir to `find-directory-functions'.
d6f47dff 634;;
d3201e0b
DN
635;; - vc-diff, vc-annotate, etc. need to deal better with unregistered
636;; files. Now that unregistered and ignored files are shown in
4903369a 637;; vc-dir, it is possible that these commands are called
d3201e0b
DN
638;; for unregistered/ignored files.
639;;
572aed3d
DN
640;; - vc-next-action needs work in order to work with multiple
641;; backends: `vc-state' returns the state for the default backend,
642;; not for the backend in the current *vc-dir* buffer.
18a083fd 643;;
74d0991f
DN
644;; - vc-dir-kill-dir-status-process should not be specific to dir-status,
645;; it should work for other async commands done through vc-do-command
646;; as well,
647;;
648;; - vc-dir toolbar needs more icons.
649;;
f6ff0e87
DN
650;; - The backends should avoid using `vc-file-setprop' and `vc-file-getprop'.
651;;
fcb500ea 652;;; Code:
0e362f54 653
594722a8 654(require 'vc-hooks)
92d1eebf 655(require 'vc-dispatcher)
64db3a90 656
b1ddeeb7 657(eval-when-compile
8de724f3
DN
658 (require 'cl)
659 (require 'dired))
b1ddeeb7 660
b5446276
DN
661(unless (assoc 'vc-parent-buffer minor-mode-alist)
662 (setq minor-mode-alist
663 (cons '(vc-parent-buffer vc-parent-buffer-name)
664 minor-mode-alist)))
594722a8
ER
665
666;; General customization
667
0101cc40
RS
668(defgroup vc nil
669 "Version-control system in Emacs."
670 :group 'tools)
671
0101cc40 672(defcustom vc-initial-comment nil
04864eb0 673 "If non-nil, prompt for initial comment when a file is registered."
0101cc40
RS
674 :type 'boolean
675 :group 'vc)
676
ac3f4c6f
ER
677(defcustom vc-default-init-revision "1.1"
678 "A string used as the default revision number when a new file is registered.
b470cb65
AS
679This can be overridden by giving a prefix argument to \\[vc-register]. This
680can also be overridden by a particular VC backend."
0d53f466 681 :type 'string
cd32a7ba
DN
682 :group 'vc
683 :version "20.3")
0d53f466 684
0101cc40 685(defcustom vc-checkin-switches nil
04864eb0 686 "A string or list of strings specifying extra switches for checkin.
0101cc40
RS
687These are passed to the checkin program by \\[vc-checkin]."
688 :type '(choice (const :tag "None" nil)
689 (string :tag "Argument String")
690 (repeat :tag "Argument List"
691 :value ("")
692 string))
693 :group 'vc)
694
695(defcustom vc-checkout-switches nil
04864eb0 696 "A string or list of strings specifying extra switches for checkout.
0101cc40
RS
697These are passed to the checkout program by \\[vc-checkout]."
698 :type '(choice (const :tag "None" nil)
699 (string :tag "Argument String")
700 (repeat :tag "Argument List"
701 :value ("")
702 string))
703 :group 'vc)
704
705(defcustom vc-register-switches nil
04864eb0 706 "A string or list of strings; extra switches for registering a file.
0101cc40
RS
707These are passed to the checkin program by \\[vc-register]."
708 :type '(choice (const :tag "None" nil)
709 (string :tag "Argument String")
710 (repeat :tag "Argument List"
711 :value ("")
712 string))
713 :group 'vc)
714
acc5b122 715(defcustom vc-diff-switches nil
04864eb0 716 "A string or list of strings specifying switches for diff under VC.
d2ee9b13
GM
717When running diff under a given BACKEND, VC uses the first
718non-nil value of `vc-BACKEND-diff-switches', `vc-diff-switches',
719and `diff-switches', in that order. Since nil means to check the
720next variable in the sequence, either of the first two may use
721the value t to mean no switches at all. `vc-diff-switches'
722should contain switches that are specific to version control, but
723not specific to any particular backend."
724 :type '(choice (const :tag "Unspecified" nil)
725 (const :tag "None" t)
acc5b122 726 (string :tag "Argument String")
d2ee9b13 727 (repeat :tag "Argument List" :value ("") string))
acc5b122
AS
728 :group 'vc
729 :version "21.1")
730
48033a08 731(defcustom vc-diff-knows-L nil
9201cc28 732 "Indicates whether diff understands the -L option.
48033a08
AS
733The value is either `yes', `no', or nil. If it is nil, VC tries
734to use -L and sets this variable to remember whether it worked."
735 :type '(choice (const :tag "Work out" nil) (const yes) (const no))
736 :group 'vc)
737
48b27575 738(defcustom vc-log-show-limit 2000
6616006b
DN
739 "Limit the number of items shown by the VC log commands.
740Zero means unlimited.
741Not all VC backends are able to support this feature."
742 :type 'integer
743 :group 'vc)
744
f1d1d46a 745(defcustom vc-allow-async-revert nil
e4d26892 746 "Specifies whether the diff during \\[vc-revert] may be asynchronous.
f1d1d46a
AS
747Enabling this option means that you can confirm a revert operation even
748if the local changes in the file have not been found and displayed yet."
749 :type '(choice (const :tag "No" nil)
750 (const :tag "Yes" t))
751 :group 'vc
bf247b6e 752 :version "22.1")
f1d1d46a 753
7cad930d
AS
754;;;###autoload
755(defcustom vc-checkout-hook nil
04864eb0 756 "Normal hook (list of functions) run after checking out a file.
7cad930d
AS
757See `run-hooks'."
758 :type 'hook
759 :group 'vc
760 :version "21.1")
761
0e362f54
GM
762;;;###autoload
763(defcustom vc-checkin-hook nil
61de26cb 764 "Normal hook (list of functions) run after commit or file checkin.
1cca5da4 765See also `log-edit-done-hook'."
0e362f54 766 :type 'hook
1cca5da4 767 :options '(log-edit-comment-to-change-log)
0e362f54
GM
768 :group 'vc)
769
770;;;###autoload
771(defcustom vc-before-checkin-hook nil
61de26cb 772 "Normal hook (list of functions) run before a commit or a file checkin.
0e362f54
GM
773See `run-hooks'."
774 :type 'hook
775 :group 'vc)
776
594722a8
ER
777;; Header-insertion hair
778
0101cc40 779(defcustom vc-static-header-alist
04864eb0 780 '(("\\.c\\'" .
594722a8 781 "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n#endif /* lint */\n"))
9201cc28 782 "Associate static header string templates with file types.
0e362f54 783A \%s in the template is replaced with the first string associated with
67141a37 784the file's version control type in `vc-BACKEND-header'."
0101cc40
RS
785 :type '(repeat (cons :format "%v"
786 (regexp :tag "File Type")
787 (string :tag "Header String")))
788 :group 'vc)
7b4f934d 789
0101cc40 790(defcustom vc-comment-alist
594722a8 791 '((nroff-mode ".\\\"" ""))
9201cc28 792 "Special comment delimiters for generating VC headers.
099bd78a
SM
793Add an entry in this list if you need to override the normal `comment-start'
794and `comment-end' variables. This will only be necessary if the mode language
0101cc40
RS
795is sensitive to blank lines."
796 :type '(repeat (list :format "%v"
797 (symbol :tag "Mode")
798 (string :tag "Comment Start")
799 (string :tag "Comment End")))
800 :group 'vc)
594722a8 801
0101cc40 802(defcustom vc-checkout-carefully (= (user-uid) 0)
9201cc28 803 "Non-nil means be extra-careful in checkout.
bbf97570 804Verify that the file really is not locked
004f9b3f 805and that its contents match what the repository version says."
0101cc40
RS
806 :type 'boolean
807 :group 'vc)
bf142f28
JB
808(make-obsolete-variable 'vc-checkout-carefully
809 "the corresponding checks are always done now."
810 "21.1")
bbf97570 811
0e362f54 812\f
83affd96 813;; Variables users don't need to see
594722a8 814
f1d1d46a
AS
815(defvar vc-disable-async-diff nil
816 "VC sets this to t locally to disable some async diff operations.
817Backends that offer asynchronous diffs should respect this variable
818in their implementation of vc-BACKEND-diff.")
819
594722a8
ER
820;; File property caching
821
8c0aaf40 822(defun vc-clear-context ()
11cdd167 823 "Clear all cached file properties."
8c0aaf40 824 (interactive)
11cdd167 825 (fillarray vc-file-prop-obarray 0))
8c0aaf40 826
d7b60083
ER
827(defmacro with-vc-properties (files form settings)
828 "Execute FORM, then maybe set per-file properties for FILES.
7902c120
DN
829If any of FILES is actually a directory, then do the same for all
830buffers for files in that directory.
6f1ecae4
AS
831SETTINGS is an association list of property/value pairs. After
832executing FORM, set those properties from SETTINGS that have not yet
833been updated to their corresponding values."
b4e4e3a8 834 (declare (debug t))
7902c120
DN
835 `(let ((vc-touched-properties (list t))
836 (flist nil))
d7b60083 837 (dolist (file ,files)
7902c120
DN
838 (if (file-directory-p file)
839 (dolist (buffer (buffer-list))
840 (let ((fname (buffer-file-name buffer)))
841 (when (and fname (vc-string-prefix-p file fname))
842 (push fname flist))))
843 (push file flist)))
844 ,form
845 (dolist (file flist)
a7192ddb
SM
846 (dolist (setting ,settings)
847 (let ((property (car setting)))
848 (unless (memq property vc-touched-properties)
849 (put (intern file vc-file-prop-obarray)
850 property (cdr setting))))))))
099bd78a 851
d7b60083
ER
852;;; Code for deducing what fileset and backend to assume
853
a9a2a6db 854(defun vc-backend-for-registration (file)
6ab196f9
DN
855 "Return a backend that can be used for registering FILE.
856
857If no backend declares itself responsible for FILE, then FILE
858must not be in a version controlled directory, so try to create a
859repository, prompting for the directory and the VC backend to
860use."
861 (catch 'found
862 ;; First try: find a responsible backend, it must be a backend
863 ;; under which FILE is not yet registered.
864 (dolist (backend vc-handled-backends)
865 (and (not (vc-call-backend backend 'registered file))
866 (vc-call-backend backend 'responsible-p file)
867 (throw 'found backend)))
868 ;; no responsible backend
869 (let* ((possible-backends
870 (let (pos)
871 (dolist (crt vc-handled-backends)
872 (when (vc-find-backend-function crt 'create-repo)
873 (push crt pos)))
874 pos))
875 (bk
876 (intern
877 ;; Read the VC backend from the user, only
878 ;; complete with the backends that have the
879 ;; 'create-repo method.
880 (completing-read
881 (format "%s is not in a version controlled directory.\nUse VC backend: " file)
882 (mapcar 'symbol-name possible-backends) nil t)))
883 (repo-dir
884 (let ((def-dir (file-name-directory file)))
885 ;; read the directory where to create the
886 ;; repository, make sure it's a parent of
887 ;; file.
888 (read-file-name
889 (format "create %s repository in: " bk)
890 default-directory def-dir t nil
891 (lambda (arg)
892 (message "arg %s" arg)
893 (and (file-directory-p arg)
894 (vc-string-prefix-p (expand-file-name arg) def-dir)))))))
895 (let ((default-directory repo-dir))
896 (vc-call-backend bk 'create-repo))
897 (throw 'found bk))))
898
899(defun vc-responsible-backend (file)
2765044b 900 "Return the name of a backend system that is responsible for FILE.
2765044b 901
6ab196f9 902If FILE is already registered, return the
b4e813ca 903backend of FILE. If FILE is not registered, then the
2765044b 904first backend in `vc-handled-backends' that declares itself
6ab196f9
DN
905responsible for FILE is returned."
906 (or (and (not (file-directory-p file)) (vc-backend file))
2765044b
DN
907 (catch 'found
908 ;; First try: find a responsible backend. If this is for registration,
909 ;; it must be a backend under which FILE is not yet registered.
910 (dolist (backend vc-handled-backends)
6ab196f9
DN
911 (and (vc-call-backend backend 'responsible-p file)
912 (throw 'found backend))))
913 (error "No VC backend is responsible for %s" file)))
2765044b
DN
914
915(defun vc-expand-dirs (file-or-dir-list)
916 "Expands directories in a file list specification.
77c5055c 917Within directories, only files already under version control are noticed."
2765044b
DN
918 (let ((flattened '()))
919 (dolist (node file-or-dir-list)
918e2ac4
DN
920 (when (file-directory-p node)
921 (vc-file-tree-walk
922 node (lambda (f) (when (vc-backend f) (push f flattened)))))
923 (unless (file-directory-p node) (push node flattened)))
2765044b
DN
924 (nreverse flattened)))
925
74d0991f 926(defvar vc-dir-backend)
a2f043d3
CY
927(defvar log-view-vc-backend)
928(defvar diff-vc-backend)
929
930(defun vc-deduce-backend ()
931 (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
932 ((derived-mode-p 'log-view-mode) log-view-vc-backend)
933 ((derived-mode-p 'diff-mode) diff-vc-backend)
ebff325e
SM
934 ;; Maybe we could even use comint-mode rather than shell-mode?
935 ((derived-mode-p 'dired-mode 'shell-mode 'compilation-mode)
a2f043d3
CY
936 (vc-responsible-backend default-directory))
937 (vc-mode (vc-backend buffer-file-name))))
114515eb 938
74d0991f 939(declare-function vc-dir-current-file "vc-dir" ())
2913a58d 940(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files))
74d0991f 941
2913a58d
DN
942(defun vc-deduce-fileset (&optional observer allow-unregistered
943 state-model-only-files)
114515eb
DN
944 "Deduce a set of files and a backend to which to apply an operation.
945
2913a58d 946Return (BACKEND FILESET FILESET-ONLY-FILES STATE CHECKOUT-MODEL).
114515eb
DN
947If we're in VC-dir mode, the fileset is the list of marked files.
948Otherwise, if we're looking at a buffer visiting a version-controlled file,
949the fileset is a singleton containing this file.
950If none of these conditions is met, but ALLOW_UNREGISTERED is on and the
951visited file is not registered, return a singleton fileset containing it.
de7a9afa 952Otherwise, throw an error.
2913a58d
DN
953
954STATE-MODEL-ONLY-FILES if non-nil, means that the caller needs
955the FILESET-ONLY-FILES STATE and MODEL info. Otherwise, that
956part may be skipped.
957BEWARE: this function may change the
958current buffer."
114515eb 959 ;; FIXME: OBSERVER is unused. The name is not intuitive and is not
de7a9afa 960 ;; documented. It's set to t when called from diff and print-log.
114515eb
DN
961 (let (backend)
962 (cond
963 ((derived-mode-p 'vc-dir-mode)
2913a58d 964 (vc-dir-deduce-fileset state-model-only-files))
8de724f3
DN
965 ((derived-mode-p 'dired-mode)
966 (if observer
967 (vc-dired-deduce-fileset)
968 (error "State changing VC operations not supported in `dired-mode'")))
114515eb 969 ((setq backend (vc-backend buffer-file-name))
2913a58d
DN
970 (if state-model-only-files
971 (list backend (list buffer-file-name)
972 (list buffer-file-name)
973 (vc-state buffer-file-name)
974 (vc-checkout-model backend buffer-file-name))
975 (list backend (list buffer-file-name))))
de7a9afa
SM
976 ((and (buffer-live-p vc-parent-buffer)
977 ;; FIXME: Why this test? --Stef
978 (or (buffer-file-name vc-parent-buffer)
114515eb 979 (with-current-buffer vc-parent-buffer
77bf3f54 980 (derived-mode-p 'vc-dir-mode))))
de7a9afa 981 (progn ;FIXME: Why not `with-current-buffer'? --Stef.
114515eb 982 (set-buffer vc-parent-buffer)
2913a58d 983 (vc-deduce-fileset observer allow-unregistered state-model-only-files)))
39693840
DN
984 ((not buffer-file-name)
985 (error "Buffer %s is not associated with a file" (buffer-name)))
114515eb 986 ((and allow-unregistered (not (vc-registered buffer-file-name)))
2913a58d 987 (if state-model-only-files
a9a2a6db 988 (list (vc-backend-for-registration (buffer-file-name))
2913a58d
DN
989 (list buffer-file-name)
990 (list buffer-file-name)
991 (when state-model-only-files 'unregistered)
992 nil)
a9a2a6db 993 (list (vc-backend-for-registration (buffer-file-name))
2913a58d 994 (list buffer-file-name))))
5a0c3f56 995 (t (error "No fileset is available here")))))
d7b60083 996
8de724f3
DN
997(defun vc-dired-deduce-fileset ()
998 (let ((backend (vc-responsible-backend default-directory)))
999 (unless backend (error "Directory not under VC"))
1000 (list backend
ebff325e 1001 (dired-map-over-marks (dired-get-filename nil t) nil))))
8de724f3 1002
2765044b
DN
1003(defun vc-ensure-vc-buffer ()
1004 "Make sure that the current buffer visits a version-controlled file."
ca8dfeda 1005 (cond
2913a58d 1006 ((derived-mode-p 'vc-dir-mode)
e1aec6fb 1007 (set-buffer (find-file-noselect (vc-dir-current-file))))
ca8dfeda 1008 (t
772111be 1009 (while (and vc-parent-buffer
cc72026b 1010 (buffer-live-p vc-parent-buffer)
772111be
MR
1011 ;; Avoid infinite looping when vc-parent-buffer and
1012 ;; current buffer are the same buffer.
1013 (not (eq vc-parent-buffer (current-buffer))))
2765044b
DN
1014 (set-buffer vc-parent-buffer))
1015 (if (not buffer-file-name)
1016 (error "Buffer %s is not associated with a file" (buffer-name))
b5446276
DN
1017 (unless (vc-backend buffer-file-name)
1018 (error "File %s is not under version control" buffer-file-name))))))
2765044b 1019
e0607aaa
SM
1020;;; Support for the C-x v v command.
1021;; This is where all the single-file-oriented code from before the fileset
1022;; rewrite lives.
61de26cb 1023
2765044b
DN
1024(defsubst vc-editable-p (file)
1025 "Return non-nil if FILE can be edited."
e0607aaa
SM
1026 (let ((backend (vc-backend file)))
1027 (and backend
70e2f6c7 1028 (or (eq (vc-checkout-model backend (list file)) 'implicit)
e0607aaa 1029 (memq (vc-state file) '(edited needs-merge conflict))))))
2765044b 1030
484c1b1f
ER
1031(defun vc-compatible-state (p q)
1032 "Controls which states can be in the same commit."
1033 (or
1034 (eq p q)
1035 (and (member p '(edited added removed)) (member q '(edited added removed)))))
1036
2765044b
DN
1037;; Here's the major entry point.
1038
1039;;;###autoload
1040(defun vc-next-action (verbose)
d7b60083
ER
1041 "Do the next logical version control operation on the current fileset.
1042This requires that all files in the fileset be in the same state.
2765044b 1043
d7b60083
ER
1044For locking systems:
1045 If every file is not already registered, this registers each for version
2765044b 1046control.
d7b60083
ER
1047 If every file is registered and not locked by anyone, this checks out
1048a writable and locked file of each ready for editing.
1049 If every file is checked out and locked by the calling user, this
1050first checks to see if each file has changed since checkout. If not,
1051it performs a revert on that file.
1052 If every file has been changed, this pops up a buffer for entry
2765044b
DN
1053of a log message; when the message has been entered, it checks in the
1054resulting changes along with the log message as change commentary. If
1055the variable `vc-keep-workfiles' is non-nil (which is its default), a
d7b60083
ER
1056read-only copy of each changed file is left in place afterwards.
1057 If the affected file is registered and locked by someone else, you are
1058given the option to steal the lock(s).
1059
1060For merging systems:
1061 If every file is not already registered, this registers each one for version
1062control. This does an add, but not a commit.
1063 If every file is added but not committed, each one is committed.
1064 If every working file is changed, but the corresponding repository file is
2765044b
DN
1065unchanged, this pops up a buffer for entry of a log message; when the
1066message has been entered, it checks in the resulting changes along
1067with the logmessage as change commentary. A writable file is retained.
1068 If the repository file is changed, you are asked if you want to
1069merge in the changes into your working copy."
2765044b 1070 (interactive "P")
2913a58d 1071 (let* ((vc-fileset (vc-deduce-fileset nil t 'state-model-only-files))
e0607aaa 1072 (backend (car vc-fileset))
114515eb
DN
1073 (files (nth 1 vc-fileset))
1074 (fileset-only-files (nth 2 vc-fileset))
ee5657de 1075 ;; FIXME: We used to call `vc-recompute-state' here.
2913a58d 1076 (state (nth 3 vc-fileset))
734abae3
SM
1077 ;; The backend should check that the checkout-model is consistent
1078 ;; among all the `files'.
e97a42c1 1079 (model (nth 4 vc-fileset)))
734abae3 1080
0e362f54 1081 ;; Do the right thing
a7192ddb 1082 (cond
3c73c30e 1083 ((eq state 'missing)
5a0c3f56 1084 (error "Fileset files are missing, so cannot be operated on"))
86048828 1085 ((eq state 'ignored)
5a0c3f56 1086 (error "Fileset files are ignored by the version-control system"))
114515eb 1087 ((or (null state) (eq state 'unregistered))
39693840 1088 (vc-register nil vc-fileset))
ac3f4c6f 1089 ;; Files are up-to-date, or need a merge and user specified a revision
3702367b 1090 ((or (eq state 'up-to-date) (and verbose (eq state 'needs-update)))
0e362f54 1091 (cond
d7b60083 1092 (verbose
ac3f4c6f 1093 ;; go to a different revision
e97a42c1
SM
1094 (let* ((revision
1095 (read-string "Branch, revision, or backend to move to: "))
1096 (revision-downcase (downcase revision)))
57b037f9
DN
1097 (if (member
1098 revision-downcase
e97a42c1
SM
1099 (mapcar (lambda (arg) (downcase (symbol-name arg)))
1100 vc-handled-backends))
57b037f9
DN
1101 (let ((vsym (intern-soft revision-downcase)))
1102 (dolist (file files) (vc-transfer-file file vsym)))
a7192ddb
SM
1103 (dolist (file files)
1104 (vc-checkout file (eq model 'implicit) revision)))))
d7b60083
ER
1105 ((not (eq model 'implicit))
1106 ;; check the files out
a7192ddb 1107 (dolist (file files) (vc-checkout file t)))
d7b60083 1108 (t
a7192ddb
SM
1109 ;; do nothing
1110 (message "Fileset is up-to-date"))))
1111 ;; Files have local changes
484c1b1f 1112 ((vc-compatible-state state 'edited)
d7b60083
ER
1113 (let ((ready-for-commit files))
1114 ;; If files are edited but read-only, give user a chance to correct
1115 (dolist (file files)
e166638d
DN
1116 (unless (file-writable-p file)
1117 ;; Make the file+buffer read-write.
1118 (unless (y-or-n-p (format "%s is edited but read-only; make it writable and continue?" file))
1119 (error "Aborted"))
1120 (set-file-modes file (logior (file-modes file) 128))
1121 (let ((visited (get-file-buffer file)))
1122 (when visited
1123 (with-current-buffer visited
1124 (toggle-read-only -1))))))
d7b60083
ER
1125 ;; Allow user to revert files with no changes
1126 (save-excursion
a7192ddb
SM
1127 (dolist (file files)
1128 (let ((visited (get-file-buffer file)))
1129 ;; For files with locking, if the file does not contain
1130 ;; any changes, just let go of the lock, i.e. revert.
e166638d
DN
1131 (when (and (not (eq model 'implicit))
1132 (vc-workfile-unchanged-p file)
1133 ;; If buffer is modified, that means the user just
1134 ;; said no to saving it; in that case, don't revert,
1135 ;; because the user might intend to save after
1136 ;; finishing the log entry and committing.
1137 (not (and visited (buffer-modified-p))))
1138 (vc-revert-file file)
554c98c5 1139 (setq ready-for-commit (delete file ready-for-commit))))))
d7b60083
ER
1140 ;; Remaining files need to be committed
1141 (if (not ready-for-commit)
1142 (message "No files remain to be committed")
1d502d5a 1143 (if (not verbose)
01cf1a52 1144 (vc-checkin ready-for-commit backend)
e97a42c1
SM
1145 (let* ((revision (read-string "New revision or backend: "))
1146 (revision-downcase (downcase revision)))
57b037f9
DN
1147 (if (member
1148 revision-downcase
1149 (mapcar (lambda (arg) (downcase (symbol-name arg)))
1150 vc-handled-backends))
1151 (let ((vsym (intern revision-downcase)))
1152 (dolist (file files) (vc-transfer-file file vsym)))
1153 (vc-checkin ready-for-commit backend revision)))))))
d7b60083
ER
1154 ;; locked by somebody else (locking VCSes only)
1155 ((stringp state)
d36122a2
TTN
1156 ;; In the old days, we computed the revision once and used it on
1157 ;; the single file. Then, for the 2007-2008 fileset rewrite, we
1158 ;; computed the revision once (incorrectly, using a free var) and
1159 ;; used it on all files. To fix the free var bug, we can either
1160 ;; use `(car files)' or do what we do here: distribute the
1161 ;; revision computation among `files'. Although this may be
1162 ;; tedious for those backends where a "revision" is a trans-file
1163 ;; concept, it is nonetheless correct for both those and (more
1164 ;; importantly) for those where "revision" is a per-file concept.
1165 ;; If the intersection of the former group and "locking VCSes" is
1166 ;; non-empty [I vaguely doubt it --ttn], we can reinstate the
1167 ;; pre-computation approach of yore.
1168 (dolist (file files)
1169 (vc-steal-lock
1170 file (if verbose
1171 (read-string (format "%s revision to steal: " file))
1172 (vc-working-revision file))
1173 state)))
7fbb4797
DN
1174 ;; conflict
1175 ((eq state 'conflict)
a749e19d
SM
1176 ;; FIXME: Is it really the UI we want to provide?
1177 ;; In my experience, the conflicted files should be marked as resolved
1178 ;; one-by-one when saving the file after resolving the conflicts.
1179 ;; I.e. stating explicitly that the conflicts are resolved is done
1180 ;; very rarely.
1181 (vc-mark-resolved backend files))
3702367b
ER
1182 ;; needs-update
1183 ((eq state 'needs-update)
d7b60083 1184 (dolist (file files)
6f41eeb5 1185 (if (yes-or-no-p (format
ac3f4c6f 1186 "%s is not up-to-date. Get latest revision? "
0e362f54 1187 (file-name-nondirectory file)))
d7b60083 1188 (vc-checkout file (eq model 'implicit) t)
e166638d
DN
1189 (when (and (not (eq model 'implicit))
1190 (yes-or-no-p "Lock this revision? "))
1191 (vc-checkout file t)))))
d7b60083
ER
1192 ;; needs-merge
1193 ((eq state 'needs-merge)
1194 (dolist (file files)
e166638d 1195 (when (yes-or-no-p (format
0e362f54
GM
1196 "%s is not up-to-date. Merge in changes now? "
1197 (file-name-nondirectory file)))
a749e19d
SM
1198 (vc-maybe-resolve-conflicts
1199 file (vc-call-backend backend 'merge-news file)))))
46e33aee 1200
d7b60083
ER
1201 ;; unlocked-changes
1202 ((eq state 'unlocked-changes)
1203 (dolist (file files)
b5446276
DN
1204 (when (not (equal buffer-file-name file))
1205 (find-file-other-window file))
0e362f54 1206 (if (save-window-excursion
f0fbfd43 1207 (vc-diff-internal nil
86048828 1208 (cons (car vc-fileset) (cons (cadr vc-fileset) (list file)))
ae67f2d0 1209 (vc-working-revision file) nil)
0e362f54 1210 (goto-char (point-min))
ceec5a0c 1211 (let ((inhibit-read-only t))
f4f34b33 1212 (insert
ceec5a0c 1213 (format "Changes to %s since last lock:\n\n" file)))
0e362f54
GM
1214 (not (beep))
1215 (yes-or-no-p (concat "File has unlocked changes. "
1216 "Claim lock retaining changes? ")))
a749e19d 1217 (progn (vc-call-backend backend 'steal-lock file)
61de26cb 1218 (clear-visited-file-modtime)
0e362f54
GM
1219 ;; Must clear any headers here because they wouldn't
1220 ;; show that the file is locked now.
1221 (vc-clear-headers file)
a36319a4 1222 (write-file buffer-file-name)
77bf3f54 1223 (vc-mode-line file backend))
0e362f54 1224 (if (not (yes-or-no-p
ac3f4c6f 1225 "Revert to checked-in revision, instead? "))
0e362f54 1226 (error "Checkout aborted")
61de26cb 1227 (vc-revert-buffer-internal t t)
3702367b
ER
1228 (vc-checkout file t)))))
1229 ;; Unknown fileset state
1230 (t
1231 (error "Fileset is in an unknown state %s" state)))))
e1f297e6 1232
61de26cb
ER
1233(defun vc-create-repo (backend)
1234 "Create an empty repository in the current directory."
1235 (interactive
1236 (list
1237 (intern
1238 (upcase
1239 (completing-read
1240 "Create repository for: "
1241 (mapcar (lambda (b) (list (downcase (symbol-name b)))) vc-handled-backends)
1242 nil t)))))
1243 (vc-call-backend backend 'create-repo))
1244
10b5dcad
DN
1245(declare-function vc-dir-move-to-goal-column "vc-dir" ())
1246
637a8ae9 1247;;;###autoload
39693840 1248(defun vc-register (&optional set-revision vc-fileset comment)
30a308aa 1249 "Register into a version control system.
39693840
DN
1250If VC-FILESET is given, register the files in that fileset.
1251Otherwise register the current file.
ac3f4c6f 1252With prefix argument SET-REVISION, allow user to specify initial revision
2765044b 1253level. If COMMENT is present, use that as an initial comment.
0e362f54 1254
2765044b
DN
1255The version control system to use is found by cycling through the list
1256`vc-handled-backends'. The first backend in that list which declares
1257itself responsible for the file (usually because other files in that
1258directory are already registered under that backend) will be used to
1259register the file. If no backend declares itself responsible, the
1260first backend that could register the file is used."
1261 (interactive "P")
39693840
DN
1262 (let* ((fileset-arg (or vc-fileset (vc-deduce-fileset nil t)))
1263 (backend (car fileset-arg))
de7a9afa
SM
1264 (files (nth 1 fileset-arg)))
1265 ;; We used to operate on `only-files', but VC wants to provide the
1266 ;; possibility to register directories rather than files only, since
1267 ;; many VCS allow that as well.
1268 (dolist (fname files)
39693840
DN
1269 (let ((bname (get-file-buffer fname)))
1270 (unless fname (setq fname buffer-file-name))
1271 (when (vc-backend fname)
1272 (if (vc-registered fname)
1273 (error "This file is already registered")
1274 (unless (y-or-n-p "Previous master file has vanished. Make a new one? ")
1275 (error "Aborted"))))
1276 ;; Watch out for new buffers of size 0: the corresponding file
1277 ;; does not exist yet, even though buffer-modified-p is nil.
1278 (when bname
1279 (with-current-buffer bname
1280 (when (and (not (buffer-modified-p))
1281 (zerop (buffer-size))
1282 (not (file-exists-p buffer-file-name)))
1283 (set-buffer-modified-p t))
1284 (vc-buffer-sync)))))
77bf3f54
DN
1285 (message "Registering %s... " files)
1286 (mapc 'vc-file-clearprops files)
1287 (vc-call-backend backend 'register files
1288 (if set-revision
1289 (read-string (format "Initial revision level for %s: " files))
1290 (vc-call-backend backend 'init-revision))
1291 comment)
1292 (mapc
1293 (lambda (file)
1294 (vc-file-setprop file 'vc-backend backend)
1295 ;; FIXME: This is wrong: it should set `backup-inhibited' in all
1296 ;; the buffers visiting files affected by this `vc-register', not
1297 ;; in the current-buffer.
1298 ;; (unless vc-make-backup-files
1299 ;; (make-local-variable 'backup-inhibited)
1300 ;; (setq backup-inhibited t))
1301
1302 (vc-resynch-buffer file vc-keep-workfiles t))
1303 files)
1304 (when (derived-mode-p 'vc-dir-mode)
1305 (vc-dir-move-to-goal-column))
1306 (message "Registering %s... done" files)))
d7b60083
ER
1307
1308(defun vc-register-with (backend)
1309 "Register the current file with a specified back end."
1310 (interactive "SBackend: ")
b5446276 1311 (when (not (member backend vc-handled-backends))
5a0c3f56 1312 (error "Unknown back end"))
d7b60083
ER
1313 (let ((vc-handled-backends (list backend)))
1314 (call-interactively 'vc-register)))
8989ab56 1315
c6d4f628 1316(defun vc-checkout (file &optional writable rev)
099bd78a
SM
1317 "Retrieve a copy of the revision REV of FILE.
1318If WRITABLE is non-nil, make sure the retrieved file is writable.
133a84aa
AS
1319REV defaults to the latest revision.
1320
1321After check-out, runs the normal hook `vc-checkout-hook'."
ffda0460
AS
1322 (and writable
1323 (not rev)
10b48cc4 1324 (vc-call make-version-backups-p file)
ffda0460 1325 (vc-up-to-date-p file)
10b48cc4 1326 (vc-make-version-backup file))
e0607aaa
SM
1327 (let ((backend (vc-backend file)))
1328 (with-vc-properties (list file)
1329 (condition-case err
af36f8ed 1330 (vc-call-backend backend 'checkout file writable rev)
e0607aaa
SM
1331 (file-error
1332 ;; Maybe the backend is not installed ;-(
1333 (when writable
1334 (let ((buf (get-file-buffer file)))
1335 (when buf (with-current-buffer buf (toggle-read-only -1)))))
1336 (signal (car err) (cdr err))))
70e2f6c7 1337 `((vc-state . ,(if (or (eq (vc-checkout-model backend (list file)) 'implicit)
e0607aaa 1338 (not writable))
a749e19d 1339 (if (vc-call-backend backend 'latest-on-branch-p file)
e0607aaa 1340 'up-to-date
3702367b 1341 'needs-update)
e0607aaa
SM
1342 'edited))
1343 (vc-checkout-time . ,(nth 5 (file-attributes file))))))
7cad930d
AS
1344 (vc-resynch-buffer file t t)
1345 (run-hooks 'vc-checkout-hook))
594722a8 1346
a749e19d 1347(defun vc-mark-resolved (backend files)
6002d9b9
CY
1348 (prog1 (with-vc-properties
1349 files
1350 (vc-call-backend backend 'mark-resolved files)
1351 ;; FIXME: Is this TRTD? Might not be.
1352 `((vc-state . edited)))
1353 (message
1354 (substitute-command-keys
1355 "Conflicts have been resolved in %s. \
f41d99b0 1356Type \\[vc-next-action] to check in changes.")
6002d9b9
CY
1357 (if (> (length files) 1)
1358 (format "%d files" (length files))
1359 "this file"))))
7fbb4797 1360
0e362f54 1361(defun vc-steal-lock (file rev owner)
099bd78a 1362 "Steal the lock on FILE."
29fc1ce9 1363 (let (file-description)
29fc1ce9
RS
1364 (if rev
1365 (setq file-description (format "%s:%s" file rev))
1366 (setq file-description file))
b5446276
DN
1367 (when (not (yes-or-no-p (format "Steal the lock on %s from %s? "
1368 file-description owner)))
1369 (error "Steal canceled"))
869131a5
AS
1370 (message "Stealing lock on %s..." file)
1371 (with-vc-properties
d7b60083 1372 (list file)
869131a5
AS
1373 (vc-call steal-lock file rev)
1374 `((vc-state . edited)))
1375 (vc-resynch-buffer file t t)
1376 (message "Stealing lock on %s...done" file)
1377 ;; Write mail after actually stealing, because if the stealing
1378 ;; goes wrong, we don't want to send any mail.
1379 (compose-mail owner (format "Stolen lock on %s" file-description))
29fc1ce9 1380 (setq default-directory (expand-file-name "~/"))
29fc1ce9
RS
1381 (goto-char (point-max))
1382 (insert
1383 (format "I stole the lock on %s, " file-description)
1384 (current-time-string)
1385 ".\n")
1386 (message "Please explain why you stole the lock. Type C-c C-c when done.")))
594722a8 1387
01cf1a52 1388(defun vc-checkin (files backend &optional rev comment initial-contents)
d7b60083 1389 "Check in FILES.
ac3f4c6f 1390The optional argument REV may be a string specifying the new revision
e97a42c1 1391level (strongly deprecated). COMMENT is a comment
0ab66291
AS
1392string; if omitted, a buffer is popped up to accept a comment. If
1393INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents
1394of the log entry buffer.
0e362f54
GM
1395
1396If `vc-keep-workfiles' is nil, FILE is deleted afterwards, provided
1397that the version control system supports this mode of operation.
861f3c29 1398
17f039f3
ER
1399Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
1400 (when vc-before-checkin-hook
1401 (run-hooks 'vc-before-checkin-hook))
01cf1a52
DN
1402 (lexical-let
1403 ((backend backend))
1404 (vc-start-logentry
e97a42c1 1405 files comment initial-contents
01cf1a52
DN
1406 "Enter a change comment."
1407 "*VC-log*"
09158997
DN
1408 (lambda ()
1409 (vc-call-backend backend 'log-edit-mode))
e97a42c1
SM
1410 (lexical-let ((rev rev))
1411 (lambda (files comment)
1412 (message "Checking in %s..." (vc-delistify files))
1413 ;; "This log message intentionally left almost blank".
1414 ;; RCS 5.7 gripes about white-space-only comments too.
1415 (or (and comment (string-match "[^\t\n ]" comment))
1416 (setq comment "*** empty log message ***"))
1417 (with-vc-properties
1418 files
1419 ;; We used to change buffers to get local value of
1420 ;; vc-checkin-switches, but 'the' local buffer is
1421 ;; not a well-defined concept for filesets.
1422 (progn
1423 (vc-call-backend backend 'checkin files rev comment)
1424 (mapc 'vc-delete-automatic-version-backups files))
1425 `((vc-state . up-to-date)
1426 (vc-checkout-time . ,(nth 5 (file-attributes file)))
1427 (vc-working-revision . nil)))
1428 (message "Checking in %s...done" (vc-delistify files))))
01cf1a52 1429 'vc-checkin-hook)))
594722a8 1430
2765044b
DN
1431;;; Additional entry points for examining version histories
1432
a7192ddb
SM
1433;; (defun vc-default-diff-tree (backend dir rev1 rev2)
1434;; "List differences for all registered files at and below DIR.
1435;; The meaning of REV1 and REV2 is the same as for `vc-revision-diff'."
1436;; ;; This implementation does an explicit tree walk, and calls
1437;; ;; vc-BACKEND-diff directly for each file. An optimization
1438;; ;; would be to use `vc-diff-internal', so that diffs can be local,
1439;; ;; and to call it only for files that are actually changed.
1440;; ;; However, this is expensive for some backends, and so it is left
1441;; ;; to backend-specific implementations.
1442;; (setq default-directory dir)
1443;; (vc-file-tree-walk
1444;; default-directory
1445;; (lambda (f)
1446;; (vc-exec-after
1447;; `(let ((coding-system-for-read (vc-coding-system-for-diff ',f)))
1448;; (message "Looking at %s" ',f)
1449;; (vc-call-backend ',(vc-backend f)
1450;; 'diff (list ',f) ',rev1 ',rev2))))))
2765044b 1451
f253ef6a
RS
1452(defvar vc-coding-system-inherit-eol t
1453 "When non-nil, inherit the EOL format for reading Diff output from the file.
1454
1455Used in `vc-coding-system-for-diff' to determine the EOL format to use
1456for reading Diff output for a file. If non-nil, the EOL format is
1457inherited from the file itself.
1458Set this variable to nil if your Diff tool might use a different
1459EOL. Then Emacs will auto-detect the EOL format in Diff output, which
1460gives better results.") ;; Cf. bug#4451.
1461
2765044b
DN
1462(defun vc-coding-system-for-diff (file)
1463 "Return the coding system for reading diff output for FILE."
1464 (or coding-system-for-read
1465 ;; if we already have this file open,
1466 ;; use the buffer's coding system
1467 (let ((buf (find-buffer-visiting file)))
b5446276 1468 (when buf (with-current-buffer buf
f253ef6a
RS
1469 (if vc-coding-system-inherit-eol
1470 buffer-file-coding-system
1471 ;; Don't inherit the EOL part of the coding-system,
1472 ;; because some Diff tools may choose to use
1473 ;; a different one. bug#4451.
1474 (coding-system-base buffer-file-coding-system)))))
2765044b
DN
1475 ;; otherwise, try to find one based on the file name
1476 (car (find-operation-coding-system 'insert-file-contents file))
1477 ;; and a final fallback
1478 'undecided))
1479
1480(defun vc-switches (backend op)
559ca68a
GM
1481 "Return a list of vc-BACKEND switches for operation OP.
1482BACKEND is a symbol such as `CVS', which will be downcased.
1483OP is a symbol such as `diff'.
1484
9201cc28 1485In decreasing order of preference, return the value of:
559ca68a
GM
1486vc-BACKEND-OP-switches (e.g. `vc-cvs-diff-switches');
1487vc-OP-switches (e.g. `vc-diff-switches'); or, in the case of
10d5dd8c 1488diff only, `diff-switches'.
559ca68a 1489
9201cc28 1490If the chosen value is not a string or a list, return nil.
559ca68a
GM
1491This is so that you may set, e.g. `vc-svn-diff-switches' to t in order
1492to override the value of `vc-diff-switches' and `diff-switches'."
2765044b 1493 (let ((switches
b5446276
DN
1494 (or (when backend
1495 (let ((sym (vc-make-backend-sym
1496 backend (intern (concat (symbol-name op)
1497 "-switches")))))
1498 (when (boundp sym) (symbol-value sym))))
2765044b 1499 (let ((sym (intern (format "vc-%s-switches" (symbol-name op)))))
b5446276 1500 (when (boundp sym) (symbol-value sym)))
2765044b
DN
1501 (cond
1502 ((eq op 'diff) diff-switches)))))
1503 (if (stringp switches) (list switches)
1504 ;; If not a list, return nil.
1505 ;; This is so we can set vc-diff-switches to t to override
1506 ;; any switches in diff-switches.
b5446276 1507 (when (listp switches) switches))))
594722a8 1508
2765044b
DN
1509;; Old def for compatibility with Emacs-21.[123].
1510(defmacro vc-diff-switches-list (backend) `(vc-switches ',backend 'diff))
1511(make-obsolete 'vc-diff-switches-list 'vc-switches "22.1")
1512
1d5b2149 1513(defun vc-diff-finish (buffer messages)
17f3909f 1514 ;; The empty sync output case has already been handled, so the only
fddde1f0 1515 ;; possibility of an empty output is for an async process.
1d5b2149
TTN
1516 (when (buffer-live-p buffer)
1517 (let ((window (get-buffer-window buffer t))
1518 (emptyp (zerop (buffer-size buffer))))
1519 (with-current-buffer buffer
1520 (and messages emptyp
1521 (let ((inhibit-read-only t))
1522 (insert (cdr messages) ".\n")
1523 (message "%s" (cdr messages))))
1524 (goto-char (point-min))
fddde1f0 1525 (when window
1d5b2149
TTN
1526 (shrink-window-if-larger-than-buffer window)))
1527 (when (and messages (not emptyp))
1528 (message "%sdone" (car messages))))))
d7b60083 1529
a7192ddb
SM
1530(defvar vc-diff-added-files nil
1531 "If non-nil, diff added files by comparing them to /dev/null.")
1532
ae67f2d0 1533(defun vc-diff-internal (async vc-fileset rev1 rev2 &optional verbose)
d7b60083
ER
1534 "Report diffs between two revisions of a fileset.
1535Diff output goes to the *vc-diff* buffer. The function
1536returns t if the buffer had changes, nil otherwise."
6986e5c9 1537 (let* ((files (cadr vc-fileset))
ae67f2d0 1538 (messages (cons (format "Finding changes in %s..."
1d5b2149
TTN
1539 (vc-delistify files))
1540 (format "No changes between %s and %s"
1541 (or rev1 "working revision")
1542 (or rev2 "workfile"))))
d7b60083
ER
1543 ;; Set coding system based on the first file. It's a kluge,
1544 ;; but the only way to set it for each file included would
1545 ;; be to call the back end separately for each file.
a7192ddb 1546 (coding-system-for-read
d7b60083
ER
1547 (if files (vc-coding-system-for-diff (car files)) 'undecided)))
1548 (vc-setup-buffer "*vc-diff*")
1d5b2149 1549 (message "%s" (car messages))
a7192ddb
SM
1550 ;; Many backends don't handle well the case of a file that has been
1551 ;; added but not yet committed to the repo (notably CVS and Subversion).
1552 ;; Do that work here so the backends don't have to futz with it. --ESR
1553 ;;
1554 ;; Actually most backends (including CVS) have options to control the
1555 ;; behavior since which one is better depends on the user and on the
1556 ;; situation). Worse yet: this code does not handle the case where
1557 ;; `file' is a directory which contains added files.
1558 ;; I made it conditional on vc-diff-added-files but it should probably
1559 ;; just be removed (or copied/moved to specific backends). --Stef.
1560 (when vc-diff-added-files
4968879c
MA
1561 (let ((filtered '())
1562 process-file-side-effects)
a7192ddb
SM
1563 (dolist (file files)
1564 (if (or (file-directory-p file)
1565 (not (string= (vc-working-revision file) "0")))
1566 (push file filtered)
1567 ;; This file is added but not yet committed;
004f9b3f 1568 ;; there is no repository version to diff against.
a7192ddb
SM
1569 (if (or rev1 rev2)
1570 (error "No revisions of %s exist" file)
1571 ;; We regard this as "changed".
1572 ;; Diff it against /dev/null.
1573 (apply 'vc-do-command "*vc-diff*"
1574 1 "diff" file
1575 (append (vc-switches nil 'diff) '("/dev/null"))))))
1576 (setq files (nreverse filtered))))
1577 (let ((vc-disable-async-diff (not async)))
ae67f2d0 1578 (vc-call-backend (car vc-fileset) 'diff files rev1 rev2 "*vc-diff*"))
d7b60083 1579 (set-buffer "*vc-diff*")
17f3909f
SM
1580 (if (and (zerop (buffer-size))
1581 (not (get-buffer-process (current-buffer))))
1582 ;; Treat this case specially so as not to pop the buffer.
1583 (progn
1d5b2149 1584 (message "%s" (cdr messages))
17f3909f 1585 nil)
e83d1fe8 1586 (diff-mode)
a2f043d3 1587 (set (make-local-variable 'diff-vc-backend) (car vc-fileset))
5af72a47
JL
1588 (set (make-local-variable 'revert-buffer-function)
1589 `(lambda (ignore-auto noconfirm)
1590 (vc-diff-internal ,async ',vc-fileset ,rev1 ,rev2 ,verbose)))
fe1919ab
DN
1591 ;; Make the *vc-diff* buffer read only, the diff-mode key
1592 ;; bindings are nicer for read only buffers. pcl-cvs does the
1593 ;; same thing.
1594 (setq buffer-read-only t)
1d5b2149
TTN
1595 (vc-exec-after `(vc-diff-finish ,(current-buffer) ',(when verbose
1596 messages)))
4befebc1
SM
1597 ;; Display the buffer, but at the end because it can change point.
1598 (pop-to-buffer (current-buffer))
17f3909f
SM
1599 ;; In the async case, we return t even if there are no differences
1600 ;; because we don't know that yet.
1601 t)))
594722a8 1602
17c15b81
SM
1603(defun vc-read-revision (prompt &optional files backend default initial-input)
1604 (cond
1605 ((null files)
1606 (let ((vc-fileset (vc-deduce-fileset t))) ;FIXME: why t? --Stef
1607 (setq files (cadr vc-fileset))
1608 (setq backend (car vc-fileset))))
1609 ((null backend) (setq backend (vc-backend (car files)))))
1610 (let ((completion-table
1611 (vc-call-backend backend 'revision-completion-table files)))
1612 (if completion-table
1613 (completing-read prompt completion-table
1614 nil nil initial-input nil default)
1615 (read-string prompt initial-input nil default))))
1616
637a8ae9 1617;;;###autoload
a7192ddb 1618(defun vc-version-diff (files rev1 rev2)
d7b60083 1619 "Report diffs between revisions of the fileset in the repository history."
0e362f54 1620 (interactive
de7a9afa 1621 (let* ((vc-fileset (vc-deduce-fileset t)) ;FIXME: why t? --Stef
6986e5c9 1622 (files (cadr vc-fileset))
a749e19d 1623 (backend (car vc-fileset))
d7b60083 1624 (first (car files))
d7b60083
ER
1625 (rev1-default nil)
1626 (rev2-default nil))
c0d66cb2 1627 (cond
ac3f4c6f 1628 ;; someday we may be able to do revision completion on non-singleton
d7b60083
ER
1629 ;; filesets, but not yet.
1630 ((/= (length files) 1)
1631 nil)
ac3f4c6f 1632 ;; if it's a directory, don't supply any revision default
d7b60083 1633 ((file-directory-p first)
c0d66cb2 1634 nil)
ac3f4c6f 1635 ;; if the file is not up-to-date, use working revision as older revision
d7b60083 1636 ((not (vc-up-to-date-p first))
ac3f4c6f
ER
1637 (setq rev1-default (vc-working-revision first)))
1638 ;; if the file is not locked, use last and previous revisions as defaults
c0d66cb2 1639 (t
a749e19d
SM
1640 (setq rev1-default (vc-call-backend backend 'previous-revision first
1641 (vc-working-revision first)))
b5446276 1642 (when (string= rev1-default "") (setq rev1-default nil))
ac3f4c6f 1643 (setq rev2-default (vc-working-revision first))))
c0d66cb2 1644 ;; construct argument list
4d83a657 1645 (let* ((rev1-prompt (if rev1-default
ac3f4c6f 1646 (concat "Older revision (default "
4d83a657 1647 rev1-default "): ")
ac3f4c6f
ER
1648 "Older revision: "))
1649 (rev2-prompt (concat "Newer revision (default "
4d83a657 1650 (or rev2-default "current source") "): "))
17c15b81
SM
1651 (rev1 (vc-read-revision rev1-prompt files backend rev1-default))
1652 (rev2 (vc-read-revision rev2-prompt files backend rev2-default)))
b5446276
DN
1653 (when (string= rev1 "") (setq rev1 nil))
1654 (when (string= rev2 "") (setq rev2 nil))
a7192ddb 1655 (list files rev1 rev2))))
86048828 1656 ;; All that was just so we could do argument completion!
ae67f2d0 1657 (when (and (not rev1) rev2)
5a0c3f56 1658 (error "Not a valid revision range"))
86048828
ER
1659 ;; Yes, it's painful to call (vc-deduce-fileset) again. Alas, the
1660 ;; placement rules for (interactive) don't actually leave us a choice.
ed6b0195 1661 (vc-diff-internal t (vc-deduce-fileset t) rev1 rev2
32226619 1662 (called-interactively-p 'interactive)))
d7b60083
ER
1663
1664;;;###autoload
a7192ddb 1665(defun vc-diff (historic &optional not-urgent)
ac3f4c6f 1666 "Display diffs between file revisions.
727c4443 1667Normally this compares the currently selected fileset with their
a7192ddb 1668working revisions. With a prefix argument HISTORIC, it reads two revision
727c4443
ER
1669designators specifying which revisions to compare.
1670
a7192ddb
SM
1671The optional argument NOT-URGENT non-nil means it is ok to say no to
1672saving the buffer."
1673 (interactive (list current-prefix-arg t))
1674 (if historic
1675 (call-interactively 'vc-version-diff)
ae67f2d0 1676 (when buffer-file-name (vc-buffer-sync not-urgent))
ed6b0195 1677 (vc-diff-internal t (vc-deduce-fileset t) nil nil
32226619 1678 (called-interactively-p 'interactive))))
2c87edc1 1679
32ba3abc
DN
1680;;;###autoload
1681(defun vc-root-diff (historic &optional not-urgent)
431af6a4
DN
1682 "Display diffs between VC-controlled whole tree revisions.
1683Normally, this compares the tree corresponding to the current
1684fileset with the working revision.
1685With a prefix argument HISTORIC, prompt for two revision
32ba3abc
DN
1686designators specifying which revisions to compare.
1687
1688The optional argument NOT-URGENT non-nil means it is ok to say no to
1689saving the buffer."
1690 (interactive (list current-prefix-arg t))
1691 (if historic
1692 ;; FIXME: this does not work right, `vc-version-diff' ends up
1693 ;; calling `vc-deduce-fileset' to find the files to diff, and
1694 ;; that's not what we want here, we want the diff for the VC root dir.
1695 (call-interactively 'vc-version-diff)
1696 (when buffer-file-name (vc-buffer-sync not-urgent))
a2f043d3 1697 (let ((backend (vc-deduce-backend))
32ba3abc
DN
1698 rootdir working-revision)
1699 (unless backend
1700 (error "Buffer is not version controlled"))
1701 (setq rootdir (vc-call-backend backend 'root default-directory))
1702 (setq working-revision (vc-working-revision rootdir))
7ec69e2b
DN
1703 ;; VC diff for the root directory produces output that is
1704 ;; relative to it. Bind default-directory to the root directory
1705 ;; here, this way the *vc-diff* buffer is setup correctly, so
1706 ;; relative file names work.
1707 (let ((default-directory rootdir))
1708 (vc-diff-internal
1709 t (list backend (list rootdir) working-revision) nil nil
1710 (called-interactively-p 'interactive))))))
32ba3abc 1711
f1818994 1712;;;###autoload
ac3f4c6f
ER
1713(defun vc-revision-other-window (rev)
1714 "Visit revision REV of the current file in another window.
1715If the current file is named `F', the revision is named `F.~REV~'.
6f1ecae4 1716If `F.~REV~' already exists, use it instead of checking it out again."
4d83a657
SM
1717 (interactive
1718 (save-current-buffer
1719 (vc-ensure-vc-buffer)
17c15b81
SM
1720 (list
1721 (vc-read-revision "Revision to visit (default is working revision): "
1722 (list buffer-file-name)))))
b6909007 1723 (vc-ensure-vc-buffer)
5e011cb2 1724 (let* ((file buffer-file-name)
ac3f4c6f
ER
1725 (revision (if (string-equal rev "")
1726 (vc-working-revision file)
ac0aae44 1727 rev)))
ac3f4c6f 1728 (switch-to-buffer-other-window (vc-find-revision file revision))))
ac0aae44 1729
04ec0963
DN
1730(defun vc-find-revision (file revision &optional backend)
1731 "Read REVISION of FILE into a buffer and return the buffer.
1732Use BACKEND as the VC backend if specified."
ac3f4c6f 1733 (let ((automatic-backup (vc-version-backup-file-name file revision))
fd8160f7 1734 (filebuf (or (get-file-buffer file) (current-buffer)))
ac3f4c6f 1735 (filename (vc-version-backup-file-name file revision 'manual)))
fd8160f7 1736 (unless (file-exists-p filename)
10b48cc4 1737 (if (file-exists-p automatic-backup)
fd8160f7
SM
1738 (rename-file automatic-backup filename nil)
1739 (message "Checking out %s..." filename)
1740 (with-current-buffer filebuf
1741 (let ((failed t))
1742 (unwind-protect
1743 (let ((coding-system-for-read 'no-conversion)
1744 (coding-system-for-write 'no-conversion))
1745 (with-temp-file filename
1746 (let ((outbuf (current-buffer)))
1747 ;; Change buffer to get local value of
1748 ;; vc-checkout-switches.
1749 (with-current-buffer filebuf
04ec0963
DN
1750 (if backend
1751 (vc-call-backend backend 'find-revision file revision outbuf)
1752 (vc-call find-revision file revision outbuf)))))
fd8160f7 1753 (setq failed nil))
48b43130
DN
1754 (when (and failed (file-exists-p filename))
1755 (delete-file filename))))
fd8160f7
SM
1756 (vc-mode-line file))
1757 (message "Checking out %s...done" filename)))
48b43130
DN
1758 (let ((result-buf (find-file-noselect filename)))
1759 (with-current-buffer result-buf
83f1f73b 1760 ;; Set the parent buffer so that things like
48b43130 1761 ;; C-x v g, C-x v l, ... etc work.
25a4ea6d 1762 (set (make-local-variable 'vc-parent-buffer) filebuf))
48b43130 1763 result-buf)))
fd8160f7 1764
594722a8
ER
1765;; Header-insertion code
1766
637a8ae9 1767;;;###autoload
594722a8 1768(defun vc-insert-headers ()
6f1ecae4 1769 "Insert headers into a file for use with a version control system.
b524ce9f 1770Headers desired are inserted at point, and are pulled from
0e362f54 1771the variable `vc-BACKEND-header'."
594722a8 1772 (interactive)
b6909007 1773 (vc-ensure-vc-buffer)
594722a8
ER
1774 (save-excursion
1775 (save-restriction
1776 (widen)
b5446276
DN
1777 (when (or (not (vc-check-headers))
1778 (y-or-n-p "Version headers already exist. Insert another set? "))
1779 (let* ((delims (cdr (assq major-mode vc-comment-alist)))
1780 (comment-start-vc (or (car delims) comment-start "#"))
1781 (comment-end-vc (or (car (cdr delims)) comment-end ""))
1782 (hdsym (vc-make-backend-sym (vc-backend buffer-file-name)
1783 'header))
1784 (hdstrings (and (boundp hdsym) (symbol-value hdsym))))
1785 (dolist (s hdstrings)
1786 (insert comment-start-vc "\t" s "\t"
1787 comment-end-vc "\n"))
1788 (when vc-static-header-alist
1789 (dolist (f vc-static-header-alist)
1790 (when (string-match (car f) buffer-file-name)
1791 (insert (format (cdr f) (car hdstrings)))))))))))
594722a8 1792
0e362f54 1793(defun vc-clear-headers (&optional file)
099bd78a 1794 "Clear all version headers in the current buffer (or FILE).
6f1ecae4 1795The headers are reset to their non-expanded form."
0e362f54
GM
1796 (let* ((filename (or file buffer-file-name))
1797 (visited (find-buffer-visiting filename))
1798 (backend (vc-backend filename)))
1799 (when (vc-find-backend-function backend 'clear-headers)
6f41eeb5 1800 (if visited
0e362f54
GM
1801 (let ((context (vc-buffer-context)))
1802 ;; save-excursion may be able to relocate point and mark
1803 ;; properly. If it fails, vc-restore-buffer-context
1804 ;; will give it a second try.
1805 (save-excursion
1806 (vc-call-backend backend 'clear-headers))
1807 (vc-restore-buffer-context context))
7849e179 1808 (set-buffer (find-file-noselect filename))
0e362f54
GM
1809 (vc-call-backend backend 'clear-headers)
1810 (kill-buffer filename)))))
c8de1d91 1811
9b64a7f0
ER
1812(defun vc-modify-change-comment (files rev oldcomment)
1813 "Edit the comment associated with the given files and revision."
5ac92c5f
GM
1814 ;; Less of a kluge than it looks like; log-view mode only passes
1815 ;; this function a singleton list. Arguments left in this form in
1816 ;; case the more general operation ever becomes meaningful.
1817 (let ((backend (vc-responsible-backend (car files))))
1818 (vc-start-logentry
e97a42c1 1819 files oldcomment t
5ac92c5f
GM
1820 "Enter a replacement change comment."
1821 "*VC-log*"
1822 (lambda () (vc-call-backend backend 'log-edit-mode))
e97a42c1
SM
1823 (lexical-let ((rev rev))
1824 (lambda (files comment)
1825 (vc-call-backend backend
1826 'modify-change-comment files rev comment))))))
9b64a7f0 1827
b6909007 1828;;;###autoload
3d92f44e 1829(defun vc-merge ()
2c3160c5
CY
1830 "Perform a version control merge operation.
1831On a distributed version control system, this runs a \"merge\"
1832operation to incorporate changes from another branch onto the
3d92f44e 1833current branch, prompting for an argument list.
2c3160c5
CY
1834
1835On a non-distributed version control system, this merges changes
1836between two revisions into the current fileset. This asks for
1837two revisions to merge from in the minibuffer. If the first
1838revision is a branch number, then merge all changes from that
1839branch. If the first revision is empty, merge the most recent
1840changes from the current branch."
3d92f44e 1841 (interactive)
2c3160c5
CY
1842 (let* ((vc-fileset (vc-deduce-fileset t))
1843 (backend (car vc-fileset))
1844 (files (cadr vc-fileset)))
0e362f54 1845 (cond
2c3160c5
CY
1846 ;; If a branch-merge operation is defined, use it.
1847 ((vc-find-backend-function backend 'merge-branch)
3d92f44e 1848 (vc-call-backend backend 'merge-branch))
2c3160c5
CY
1849 ;; Otherwise, do a per-file merge.
1850 ((vc-find-backend-function backend 'merge)
1851 (vc-buffer-sync)
1852 (dolist (file files)
1853 (let* ((state (vc-state file))
1854 first-revision second-revision status)
1855 (cond
1856 ((stringp state) ;; Locking VCses only
1857 (error "File %s is locked by %s" file state))
1858 ((not (vc-editable-p file))
1859 (vc-checkout file t)))
1860 (setq first-revision
1861 (vc-read-revision
1862 (concat "Merge " file
1863 "from branch or revision "
1864 "(default news on current branch): ")
1865 (list file)
1866 backend))
1867 (cond
1868 ((string= first-revision "")
1869 (setq status (vc-call-backend backend 'merge-news file)))
1870 (t
1871 (if (not (vc-branch-p first-revision))
1872 (setq second-revision
1873 (vc-read-revision
1874 "Second revision: "
1875 (list file) backend nil
1876 ;; FIXME: This is CVS/RCS/SCCS specific.
1877 (concat (vc-branch-part first-revision) ".")))
1878 ;; We want to merge an entire branch. Set revisions
1879 ;; accordingly, so that vc-BACKEND-merge understands us.
1880 (setq second-revision first-revision)
1881 ;; first-revision must be the starting point of the branch
1882 (setq first-revision (vc-branch-part first-revision)))
1883 (setq status (vc-call-backend backend 'merge file
1884 first-revision second-revision))))
1885 (vc-maybe-resolve-conflicts file status "WORKFILE" "MERGE SOURCE"))))
1886 (t
1887 (error "Sorry, merging is not implemented for %s" backend)))))
1888
0e362f54
GM
1889
1890(defun vc-maybe-resolve-conflicts (file status &optional name-A name-B)
1891 (vc-resynch-buffer file t (not (buffer-modified-p)))
1892 (if (zerop status) (message "Merge successful")
28e4e2b4 1893 (smerge-mode 1)
8dc87047 1894 (message "File contains conflicts.")))
ccb141e8
AS
1895
1896;;;###autoload
1168d6c2 1897(defalias 'vc-resolve-conflicts 'smerge-ediff)
3b574573 1898
e97a42c1
SM
1899;; TODO: This is OK but maybe we could integrate it better.
1900;; E.g. it could be run semi-automatically (via a prompt?) when saving a file
1901;; that was conflicted (i.e. upon mark-resolved).
1902;; FIXME: should we add an "other-window" version? Or maybe we should
1903;; hook it inside find-file so it automatically works for
1904;; find-file-other-window as well. E.g. find-file could use a new
1905;; `default-next-file' variable for its default file (M-n), and
1906;; we could then set it upon mark-resolve, so C-x C-s C-x C-f M-n would
1907;; automatically offer the next conflicted file.
1908(defun vc-find-conflicted-file ()
1909 "Visit the next conflicted file in the current project."
1910 (interactive)
1911 (let* ((backend (or (if buffer-file-name (vc-backend buffer-file-name))
1912 (vc-responsible-backend default-directory)
1913 (error "No VC backend")))
1914 (files (vc-call-backend backend
1915 'conflicted-files default-directory)))
1916 ;; Don't try and visit the current file.
1917 (if (equal (car files) buffer-file-name) (pop files))
1918 (if (null files)
1919 (message "No more conflicted files")
1920 (find-file (pop files))
1921 (message "%s more conflicted files after this one"
1922 (if files (length files) "No")))))
1923
594722a8
ER
1924;; Named-configuration entry points
1925
370fded4 1926(defun vc-tag-precondition (dir)
6f1ecae4 1927 "Scan the tree below DIR, looking for files not up-to-date.
099bd78a 1928If any file is not up-to-date, return the name of the first such file.
370fded4 1929\(This means, neither tag creation nor retrieval is allowed.\)
099bd78a
SM
1930If one or more of the files are currently visited, return `visited'.
1931Otherwise, return nil."
503b5c85
RS
1932 (let ((status nil))
1933 (catch 'vc-locked-example
1934 (vc-file-tree-walk
0e362f54
GM
1935 dir
1936 (lambda (f)
1937 (if (not (vc-up-to-date-p f)) (throw 'vc-locked-example f)
b5446276 1938 (when (get-file-buffer f) (setq status 'visited)))))
503b5c85 1939 status)))
594722a8 1940
637a8ae9 1941;;;###autoload
370fded4
ER
1942(defun vc-create-tag (dir name branchp)
1943 "Descending recursively from DIR, make a tag called NAME.
ac3f4c6f
ER
1944For each registered file, the working revision becomes part of
1945the named configuration. If the prefix argument BRANCHP is
370fded4 1946given, the tag is made as a new branch and the files are
ac3f4c6f 1947checked out in that new branch."
0e362f54 1948 (interactive
5f4f2ae4
DN
1949 (let ((granularity
1950 (vc-call-backend (vc-responsible-backend default-directory)
1951 'revision-granularity)))
1952 (list
1953 (if (eq granularity 'repository)
1954 ;; For VC's that do not work at file level, it's pointless
1955 ;; to ask for a directory, branches are created at repository level.
1956 default-directory
1957 (read-file-name "Directory: " default-directory default-directory t))
1958 (read-string (if current-prefix-arg "New branch name: " "New tag name: "))
1959 current-prefix-arg)))
370fded4 1960 (message "Making %s... " (if branchp "branch" "tag"))
b5446276 1961 (when (file-directory-p dir) (setq dir (file-name-as-directory dir)))
0e362f54 1962 (vc-call-backend (vc-responsible-backend dir)
370fded4 1963 'create-tag dir name branchp)
5f4f2ae4 1964 (vc-resynch-buffer dir t t t)
370fded4 1965 (message "Making %s... done" (if branchp "branch" "tag")))
0e362f54 1966
637a8ae9 1967;;;###autoload
370fded4
ER
1968(defun vc-retrieve-tag (dir name)
1969 "Descending recursively from DIR, retrieve the tag called NAME.
ac3f4c6f 1970If NAME is empty, it refers to the latest revisions.
099bd78a
SM
1971If locking is used for the files in DIR, then there must not be any
1972locked files at or below DIR (but if NAME is empty, locked files are
1973allowed and simply skipped)."
0e362f54 1974 (interactive
5f4f2ae4
DN
1975 (let ((granularity
1976 (vc-call-backend (vc-responsible-backend default-directory)
1977 'revision-granularity)))
1978 (list
1979 (if (eq granularity 'repository)
1980 ;; For VC's that do not work at file level, it's pointless
1981 ;; to ask for a directory, branches are created at repository level.
1982 default-directory
1983 (read-file-name "Directory: " default-directory default-directory t))
1984 (read-string "Tag name to retrieve (default latest revisions): "))))
0e362f54
GM
1985 (let ((update (yes-or-no-p "Update any affected buffers? "))
1986 (msg (if (or (not name) (string= name ""))
1987 (format "Updating %s... " (abbreviate-file-name dir))
370fded4 1988 (format "Retrieving tag into %s... "
0e362f54 1989 (abbreviate-file-name dir)))))
8a26c165 1990 (message "%s" msg)
0e362f54 1991 (vc-call-backend (vc-responsible-backend dir)
370fded4 1992 'retrieve-tag dir name update)
5f4f2ae4 1993 (vc-resynch-buffer dir t t t)
8a26c165 1994 (message "%s" (concat msg "done"))))
0e362f54 1995
5f4f2ae4 1996
594722a8
ER
1997;; Miscellaneous other entry points
1998
32ba3abc
DN
1999;; FIXME: this should be a defcustom
2000;; FIXME: maybe add another choice:
2001;; `root-directory' (or somesuch), which would mean show a short log
2002;; for the root directory.
2003(defvar vc-log-short-style '(directory)
2004 "Whether or not to show a short log.
2005If it contains `directory' then if the fileset contains a directory show a short log.
2006If it contains `file' then show short logs for files.
2007Not all VC backends support short logs!")
2008
d6e82452
GM
2009(defvar log-view-vc-fileset)
2010
31527c56
DN
2011(defun vc-print-log-setup-buttons (working-revision is-start-revision limit pl-return)
2012 (when (and limit (not (eq 'limit-unsupported pl-return))
2013 (not is-start-revision))
2014 (goto-char (point-max))
2015 (lexical-let ((working-revision working-revision)
2016 (limit limit))
2017 (widget-create 'push-button
2018 :notify (lambda (&rest ignore)
2019 (vc-print-log-internal
2020 log-view-vc-backend log-view-vc-fileset
2021 working-revision nil (* 2 limit)))
2022 :help-echo "Show the log again, and double the number of log entries shown"
2023 "Show 2X entries")
2024 (widget-insert " ")
2025 (widget-create 'push-button
2026 :notify (lambda (&rest ignore)
2027 (vc-print-log-internal
2028 log-view-vc-backend log-view-vc-fileset
2029 working-revision nil nil))
2030 :help-echo "Show the log again, showing all entries"
2031 "Show unlimited entries"))
2032 (widget-setup)))
2033
eb708e66 2034(defun vc-print-log-internal (backend files working-revision
662c5698 2035 &optional is-start-revision limit)
d6a62b0d
DN
2036 ;; Don't switch to the output buffer before running the command,
2037 ;; so that any buffer-local settings in the vc-controlled
2038 ;; buffer can be accessed by the command.
32ba3abc 2039 (let ((dir-present nil)
48b27575 2040 (vc-short-log nil)
31527c56
DN
2041 (buffer-name "*vc-change-log*")
2042 type
48b27575 2043 pl-return)
32ba3abc
DN
2044 (dolist (file files)
2045 (when (file-directory-p file)
2046 (setq dir-present t)))
2047 (setq vc-short-log
2048 (not (null (if dir-present
2049 (memq 'directory vc-log-short-style)
2050 (memq 'file vc-log-short-style)))))
31527c56
DN
2051 (setq type (if vc-short-log 'short 'long))
2052 (lexical-let
2053 ((working-revision working-revision)
82fb8701 2054 (backend backend)
31527c56
DN
2055 (limit limit)
2056 (shortlog vc-short-log)
82fb8701 2057 (files files)
31527c56
DN
2058 (is-start-revision is-start-revision))
2059 (vc-log-internal-common
2060 backend buffer-name files type
2061 (lambda (bk buf type-arg files-arg)
2062 (vc-call-backend bk 'print-log files-arg buf
2063 shortlog (when is-start-revision working-revision) limit))
2064 (lambda (bk files-arg ret)
2065 (vc-print-log-setup-buttons working-revision
2066 is-start-revision limit ret))
2067 (lambda (bk)
82fb8701
DN
2068 (vc-call-backend bk 'show-log-entry working-revision))
2069 (lambda (ignore-auto noconfirm)
2070 (vc-print-log-internal backend files working-revision is-start-revision limit))))))
31527c56
DN
2071
2072(defvar vc-log-view-type nil
2073 "Set this to differentiate the different types of logs.")
2074(put 'vc-log-view-type 'permanent-local t)
2075
2076(defun vc-log-internal-common (backend
2077 buffer-name
2078 files
2079 type
2080 backend-func
2081 setup-buttons-func
82fb8701
DN
2082 goto-location-func
2083 rev-buff-func)
31527c56
DN
2084 (let (retval)
2085 (with-current-buffer (get-buffer-create buffer-name)
2086 (set (make-local-variable 'vc-log-view-type) type))
2087 (setq retval (funcall backend-func backend buffer-name type files))
2088 (pop-to-buffer buffer-name)
c767b665
SM
2089 (let ((inhibit-read-only t))
2090 ;; log-view-mode used to be called with inhibit-read-only bound
2091 ;; to t, so let's keep doing it, just in case.
31527c56
DN
2092 (vc-call-backend backend 'log-view-mode)
2093 (set (make-local-variable 'log-view-vc-backend) backend)
82fb8701
DN
2094 (set (make-local-variable 'log-view-vc-fileset) files)
2095 (set (make-local-variable 'revert-buffer-function)
2096 rev-buff-func))
c767b665
SM
2097 (vc-exec-after
2098 `(let ((inhibit-read-only t))
31527c56 2099 (funcall ',setup-buttons-func ',backend ',files ',retval)
32ba3abc 2100 (shrink-window-if-larger-than-buffer)
31527c56 2101 (funcall ',goto-location-func ',backend)
32ba3abc
DN
2102 (setq vc-sentinel-movepoint (point))
2103 (set-buffer-modified-p nil)))))
d6a62b0d 2104
31527c56
DN
2105(defun vc-incoming-outgoing-internal (backend remote-location buffer-name type)
2106 (vc-log-internal-common
2107 backend buffer-name nil type
2108 (lexical-let
2109 ((remote-location remote-location))
2110 (lambda (bk buf type-arg files)
2111 (vc-call-backend bk type-arg buf remote-location)))
2112 (lambda (bk files-arg ret))
2113 (lambda (bk)
82fb8701
DN
2114 (goto-char (point-min)))
2115 (lexical-let
2116 ((backend backend)
2117 (remote-location remote-location)
2118 (buffer-name buffer-name)
2119 (type type))
2120 (lambda (ignore-auto noconfirm)
2121 (vc-incoming-outgoing-internal backend remote-location buffer-name type)))))
31527c56 2122
637a8ae9 2123;;;###autoload
6616006b 2124(defun vc-print-log (&optional working-revision limit)
d7b60083 2125 "List the change log of the current fileset in a window.
9aa2c576
CY
2126If WORKING-REVISION is non-nil, leave point at that revision.
2127If LIMIT is non-nil, it should be a number specifying the maximum
2128number of revisions to show; the default is `vc-log-show-limit'.
2129
2130When called interactively with a prefix argument, prompt for
2131WORKING-REVISION and LIMIT."
6616006b
DN
2132 (interactive
2133 (cond
2134 (current-prefix-arg
2135 (let ((rev (read-from-minibuffer "Log from revision (default: last revision): " nil
2136 nil nil nil))
2137 (lim (string-to-number
2138 (read-from-minibuffer
2139 "Limit display (unlimited: 0): "
2140 (format "%s" vc-log-show-limit)
2141 nil nil nil))))
2142 (when (string= rev "") (setq rev nil))
2143 (when (<= lim 0) (setq lim nil))
2144 (list rev lim)))
2145 (t
46e5c897 2146 (list nil (when (> vc-log-show-limit 0) vc-log-show-limit)))))
de7a9afa 2147 (let* ((vc-fileset (vc-deduce-fileset t)) ;FIXME: Why t? --Stef
ae67f2d0 2148 (backend (car vc-fileset))
6986e5c9 2149 (files (cadr vc-fileset))
ac3f4c6f 2150 (working-revision (or working-revision (vc-working-revision (car files)))))
662c5698 2151 (vc-print-log-internal backend files working-revision nil limit)))
594722a8 2152
32ba3abc 2153;;;###autoload
6616006b 2154(defun vc-print-root-log (&optional limit)
9aa2c576
CY
2155 "List the change log for the current VC controlled tree in a window.
2156If LIMIT is non-nil, it should be a number specifying the maximum
2157number of revisions to show; the default is `vc-log-show-limit'.
2158When called interactively with a prefix argument, prompt for LIMIT."
6616006b
DN
2159 (interactive
2160 (cond
2161 (current-prefix-arg
2162 (let ((lim (string-to-number
2163 (read-from-minibuffer
2164 "Limit display (unlimited: 0): "
2165 (format "%s" vc-log-show-limit)
2166 nil nil nil))))
2167 (when (<= lim 0) (setq lim nil))
2168 (list lim)))
2169 (t
46e5c897 2170 (list (when (> vc-log-show-limit 0) vc-log-show-limit)))))
a2f043d3 2171 (let ((backend (vc-deduce-backend))
32ba3abc
DN
2172 rootdir working-revision)
2173 (unless backend
2174 (error "Buffer is not version controlled"))
2175 (setq rootdir (vc-call-backend backend 'root default-directory))
2176 (setq working-revision (vc-working-revision rootdir))
662c5698 2177 (vc-print-log-internal backend (list rootdir) working-revision nil limit)))
32ba3abc 2178
31527c56
DN
2179;;;###autoload
2180(defun vc-log-incoming (&optional remote-location)
82fb8701
DN
2181 "Show a log of changes that will be received with a pull operation from REMOTE-LOCATION.
2182When called interactively with a prefix argument, prompt for REMOTE-LOCATION.."
2183 (interactive
2184 (when current-prefix-arg
2185 (list (read-string "Remote location (empty for default): "))))
a2f043d3 2186 (let ((backend (vc-deduce-backend))
31527c56
DN
2187 rootdir working-revision)
2188 (unless backend
2189 (error "Buffer is not version controlled"))
2190 (vc-incoming-outgoing-internal backend remote-location "*vc-incoming*" 'log-incoming)))
2191
2192;;;###autoload
2193(defun vc-log-outgoing (&optional remote-location)
82fb8701
DN
2194 "Show a log of changes that will be sent with a push operation to REMOTE-LOCATION.
2195When called interactively with a prefix argument, prompt for REMOTE-LOCATION."
2196 (interactive
2197 (when current-prefix-arg
2198 (list (read-string "Remote location (empty for default): "))))
a2f043d3 2199 (let ((backend (vc-deduce-backend))
31527c56
DN
2200 rootdir working-revision)
2201 (unless backend
2202 (error "Buffer is not version controlled"))
2203 (vc-incoming-outgoing-internal backend remote-location "*vc-outgoing*" 'log-outgoing)))
2204
637a8ae9 2205;;;###autoload
e4d26892 2206(defun vc-revert ()
d7b60083 2207 "Revert working copies of the selected fileset to their repository contents.
9c95ac44 2208This asks for confirmation if the buffer contents are not identical
ac3f4c6f 2209to the working revision (except for keyword expansion)."
594722a8 2210 (interactive)
ae67f2d0 2211 (let* ((vc-fileset (vc-deduce-fileset))
6986e5c9 2212 (files (cadr vc-fileset)))
d7b60083
ER
2213 ;; If any of the files is visited by the current buffer, make
2214 ;; sure buffer is saved. If the user says `no', abort since
2215 ;; we cannot show the changes and ask for confirmation to
2216 ;; discard them.
b5446276
DN
2217 (when (or (not files) (memq (buffer-file-name) files))
2218 (vc-buffer-sync nil))
d7b60083 2219 (dolist (file files)
a7192ddb 2220 (let ((buf (get-file-buffer file)))
b5446276 2221 (when (and buf (buffer-modified-p buf))
5a0c3f56 2222 (error "Please kill or save all modified buffers before reverting")))
b5446276
DN
2223 (when (vc-up-to-date-p file)
2224 (unless (yes-or-no-p (format "%s seems up-to-date. Revert anyway? " file))
2225 (error "Revert canceled"))))
ae67f2d0 2226 (when (vc-diff-internal vc-allow-async-revert vc-fileset nil nil)
904f8793
CY
2227 (unless (yes-or-no-p
2228 (format "Discard changes in %s? "
d6e82452
GM
2229 (let ((str (vc-delistify files))
2230 (nfiles (length files)))
904f8793
CY
2231 (if (< (length str) 50)
2232 str
d6e82452
GM
2233 (format "%d file%s" nfiles
2234 (if (= nfiles 1) "" "s"))))))
b5446276
DN
2235 (error "Revert canceled"))
2236 (delete-windows-on "*vc-diff*")
2237 (kill-buffer "*vc-diff*"))
d7b60083 2238 (dolist (file files)
b5446276
DN
2239 (message "Reverting %s..." (vc-delistify files))
2240 (vc-revert-file file)
2241 (message "Reverting %s...done" (vc-delistify files)))))
594722a8 2242
637a8ae9 2243;;;###autoload
d7b60083
ER
2244(defun vc-rollback ()
2245 "Roll back (remove) the most recent changeset committed to the repository.
2246This may be either a file-level or a repository-level operation,
2247depending on the underlying version-control system."
2248 (interactive)
ae67f2d0 2249 (let* ((vc-fileset (vc-deduce-fileset))
ae67f2d0 2250 (backend (car vc-fileset))
6986e5c9 2251 (files (cadr vc-fileset))
d7b60083
ER
2252 (granularity (vc-call-backend backend 'revision-granularity)))
2253 (unless (vc-find-backend-function backend 'rollback)
2254 (error "Rollback is not supported in %s" backend))
b5446276
DN
2255 (when (and (not (eq granularity 'repository)) (/= (length files) 1))
2256 (error "Rollback requires a singleton fileset or repository versioning"))
a749e19d
SM
2257 ;; FIXME: latest-on-branch-p should take the fileset.
2258 (when (not (vc-call-backend backend 'latest-on-branch-p (car files)))
5a0c3f56 2259 (error "Rollback is only possible at the tip revision"))
d7b60083
ER
2260 ;; If any of the files is visited by the current buffer, make
2261 ;; sure buffer is saved. If the user says `no', abort since
2262 ;; we cannot show the changes and ask for confirmation to
2263 ;; discard them.
b5446276
DN
2264 (when (or (not files) (memq (buffer-file-name) files))
2265 (vc-buffer-sync nil))
d7b60083 2266 (dolist (file files)
b5446276 2267 (when (buffer-modified-p (get-file-buffer file))
5a0c3f56 2268 (error "Please kill or save all modified buffers before rollback"))
b5446276 2269 (when (not (vc-up-to-date-p file))
5a0c3f56 2270 (error "Please revert all modified workfiles before rollback")))
d7b60083
ER
2271 ;; Accumulate changes associated with the fileset
2272 (vc-setup-buffer "*vc-diff*")
2273 (not-modified)
2274 (message "Finding changes...")
ac3f4c6f 2275 (let* ((tip (vc-working-revision (car files)))
a749e19d
SM
2276 ;; FIXME: `previous-revision' should take the fileset.
2277 (previous (vc-call-backend backend 'previous-revision
2278 (car files) tip)))
ae67f2d0 2279 (vc-diff-internal nil vc-fileset previous tip))
a7192ddb 2280 ;; Display changes
d7b60083
ER
2281 (unless (yes-or-no-p "Discard these revisions? ")
2282 (error "Rollback canceled"))
2283 (delete-windows-on "*vc-diff*")
2284 (kill-buffer"*vc-diff*")
2285 ;; Do the actual reversions
2286 (message "Rolling back %s..." (vc-delistify files))
2287 (with-vc-properties
2288 files
2289 (vc-call-backend backend 'rollback files)
2290 `((vc-state . ,'up-to-date)
2291 (vc-checkout-time . , (nth 5 (file-attributes file)))
ac3f4c6f 2292 (vc-working-revision . nil)))
a7192ddb 2293 (dolist (f files) (vc-resynch-buffer f t t))
d7b60083 2294 (message "Rolling back %s...done" (vc-delistify files))))
0e362f54 2295
2765044b
DN
2296;;;###autoload
2297(define-obsolete-function-alias 'vc-revert-buffer 'vc-revert "23.1")
2298
2299;;;###autoload
659114fd 2300(defun vc-pull (&optional arg)
2c3160c5
CY
2301 "Update the current fileset or branch.
2302On a distributed version control system, this runs a \"pull\"
2303operation to update the current branch, prompting for an argument
2304list if required. Optional prefix ARG forces a prompt.
2305
2306On a non-distributed version control system, update the current
2307fileset to the tip revisions. For each unchanged and unlocked
2308file, this simply replaces the work file with the latest revision
2309on its branch. If the file contains changes, any changes in the
2310tip revision are merged into the working file."
2311 (interactive "P")
2312 (let* ((vc-fileset (vc-deduce-fileset t))
86048828 2313 (backend (car vc-fileset))
6986e5c9 2314 (files (cadr vc-fileset)))
2c3160c5
CY
2315 (cond
2316 ;; If a pull operation is defined, use it.
2317 ((vc-find-backend-function backend 'pull)
2318 (vc-call-backend backend 'pull arg))
2319 ;; If VCS has `merge-news' functionality (CVS and SVN), use it.
2320 ((vc-find-backend-function backend 'merge-news)
2321 (save-some-buffers ; save buffers visiting files
2322 nil (lambda ()
2323 (and (buffer-modified-p)
2324 (let ((file (buffer-file-name)))
2325 (and file (member file files))))))
2326 (dolist (file files)
2327 (if (vc-up-to-date-p file)
2328 (vc-checkout file nil t)
2329 (vc-maybe-resolve-conflicts
2330 file (vc-call-backend backend 'merge-news file)))))
2331 ;; For a locking VCS, check out each file.
2332 ((eq (vc-checkout-model backend files) 'locking)
2333 (dolist (file files)
2334 (if (vc-up-to-date-p file)
2335 (vc-checkout file nil t))))
2336 (t
2337 (error "VC update is unsupported for `%s'" backend)))))
2338
2339;;;###autoload
659114fd 2340(defalias 'vc-update 'vc-pull)
2765044b
DN
2341
2342(defun vc-version-backup-file (file &optional rev)
2343 "Return name of backup file for revision REV of FILE.
2344If version backups should be used for FILE, and there exists
a7192ddb 2345such a backup for REV or the working revision of file, return
0d0e9356 2346its name; otherwise return nil."
2765044b
DN
2347 (when (vc-call make-version-backups-p file)
2348 (let ((backup-file (vc-version-backup-file-name file rev)))
2349 (if (file-exists-p backup-file)
2350 backup-file
2351 ;; there is no automatic backup, but maybe the user made one manually
2352 (setq backup-file (vc-version-backup-file-name file rev 'manual))
b5446276
DN
2353 (when (file-exists-p backup-file)
2354 backup-file)))))
2765044b
DN
2355
2356(defun vc-revert-file (file)
ac3f4c6f 2357 "Revert FILE back to the repository working revision it was based on."
2765044b 2358 (with-vc-properties
d7b60083 2359 (list file)
2765044b
DN
2360 (let ((backup-file (vc-version-backup-file file)))
2361 (when backup-file
2362 (copy-file backup-file file 'ok-if-already-exists 'keep-date)
2363 (vc-delete-automatic-version-backups file))
2364 (vc-call revert file backup-file))
2365 `((vc-state . up-to-date)
2366 (vc-checkout-time . ,(nth 5 (file-attributes file)))))
2367 (vc-resynch-buffer file t t))
2368
76e5906d 2369;;;###autoload
1d502d5a 2370(defun vc-switch-backend (file backend)
7849e179 2371 "Make BACKEND the current version control system for FILE.
1d502d5a
AS
2372FILE must already be registered in BACKEND. The change is not
2373permanent, only for the current session. This function only changes
7849e179
SM
2374VC's perspective on FILE, it does not register or unregister it.
2375By default, this command cycles through the registered backends.
2376To get a prompt, use a prefix argument."
2377 (interactive
1d502d5a 2378 (list
94ca88e3
AS
2379 (or buffer-file-name
2380 (error "There is no version-controlled file in this buffer"))
3daebe67 2381 (let ((crt-bk (vc-backend buffer-file-name))
7849e179 2382 (backends nil))
3daebe67 2383 (unless crt-bk
d7b60083
ER
2384 (error "File %s is not under version control" buffer-file-name))
2385 ;; Find the registered backends.
3daebe67
DN
2386 (dolist (crt vc-handled-backends)
2387 (when (and (vc-call-backend crt 'registered buffer-file-name)
2388 (not (eq crt-bk crt)))
2389 (push crt backends)))
d7b60083 2390 ;; Find the next backend.
3daebe67
DN
2391 (let ((def (car backends))
2392 (others backends))
d7b60083
ER
2393 (cond
2394 ((null others) (error "No other backend to switch to"))
2395 (current-prefix-arg
2396 (intern
2397 (upcase
2398 (completing-read
2399 (format "Switch to backend [%s]: " def)
2400 (mapcar (lambda (b) (list (downcase (symbol-name b)))) backends)
2401 nil t nil nil (downcase (symbol-name def))))))
3daebe67 2402 (t def))))))
ceec5a0c 2403 (unless (eq backend (vc-backend file))
ceec5a0c
SM
2404 (vc-file-clearprops file)
2405 (vc-file-setprop file 'vc-backend backend)
2406 ;; Force recomputation of the state
a3255400
SM
2407 (unless (vc-call-backend backend 'registered file)
2408 (vc-file-clearprops file)
2409 (error "%s is not registered in %s" file backend))
ceec5a0c 2410 (vc-mode-line file)))
1d502d5a 2411
21b50296 2412;;;###autoload
1d502d5a 2413(defun vc-transfer-file (file new-backend)
ceec5a0c 2414 "Transfer FILE to another version control system NEW-BACKEND.
1d502d5a 2415If NEW-BACKEND has a higher precedence than FILE's current backend
ceec5a0c 2416\(i.e. it comes earlier in `vc-handled-backends'), then register FILE in
ac3f4c6f 2417NEW-BACKEND, using the revision number from the current backend as the
1d502d5a
AS
2418base level. If NEW-BACKEND has a lower precedence than the current
2419backend, then commit all changes that were made under the current
2420backend to NEW-BACKEND, and unregister FILE from the current backend.
2421\(If FILE is not yet registered under NEW-BACKEND, register it.)"
72cfc5fb
AS
2422 (let* ((old-backend (vc-backend file))
2423 (edited (memq (vc-state file) '(edited needs-merge)))
2424 (registered (vc-call-backend new-backend 'registered file))
2425 (move
2426 (and registered ; Never move if not registered in new-backend yet.
2427 ;; move if new-backend comes later in vc-handled-backends
2428 (or (memq new-backend (memq old-backend vc-handled-backends))
ffda0460 2429 (y-or-n-p "Final transfer? "))))
72cfc5fb 2430 (comment nil))
ae67f2d0
DN
2431 (when (eq old-backend new-backend)
2432 (error "%s is the current backend of %s" new-backend file))
72cfc5fb
AS
2433 (if registered
2434 (set-file-modes file (logior (file-modes file) 128))
2435 ;; `registered' might have switched under us.
2436 (vc-switch-backend file old-backend)
ac3f4c6f 2437 (let* ((rev (vc-working-revision file))
c1b1b393 2438 (modified-file (and edited (make-temp-file file)))
ffda0460 2439 (unmodified-file (and modified-file (vc-version-backup-file file))))
72cfc5fb
AS
2440 ;; Go back to the base unmodified file.
2441 (unwind-protect
2442 (progn
ffda0460 2443 (when modified-file
c1b1b393 2444 (copy-file file modified-file 'ok-if-already-exists)
ffda0460
AS
2445 ;; If we have a local copy of the unmodified file, handle that
2446 ;; here and not in vc-revert-file because we don't want to
2447 ;; delete that copy -- it is still useful for OLD-BACKEND.
2448 (if unmodified-file
b4e4e3a8
SM
2449 (copy-file unmodified-file file
2450 'ok-if-already-exists 'keep-date)
004f9b3f 2451 (when (y-or-n-p "Get base revision from repository? ")
ae67f2d0 2452 (vc-revert-file file))))
72cfc5fb 2453 (vc-call-backend new-backend 'receive-file file rev))
ffda0460 2454 (when modified-file
72cfc5fb 2455 (vc-switch-backend file new-backend)
70e2f6c7 2456 (unless (eq (vc-checkout-model new-backend (list file)) 'implicit)
72cfc5fb 2457 (vc-checkout file t nil))
ffda0460
AS
2458 (rename-file modified-file file 'ok-if-already-exists)
2459 (vc-file-setprop file 'vc-checkout-time nil)))))
72cfc5fb
AS
2460 (when move
2461 (vc-switch-backend file old-backend)
a749e19d
SM
2462 (setq comment (vc-call-backend old-backend 'comment-history file))
2463 (vc-call-backend old-backend 'unregister file))
72cfc5fb
AS
2464 (vc-switch-backend file new-backend)
2465 (when (or move edited)
1d502d5a 2466 (vc-file-setprop file 'vc-state 'edited)
77bf3f54 2467 (vc-mode-line file new-backend)
01cf1a52 2468 (vc-checkin file new-backend nil comment (stringp comment)))))
1d502d5a 2469
0e362f54
GM
2470(defun vc-rename-master (oldmaster newfile templates)
2471 "Rename OLDMASTER to be the master file for NEWFILE based on TEMPLATES."
2472 (let* ((dir (file-name-directory (expand-file-name oldmaster)))
2473 (newdir (or (file-name-directory newfile) ""))
2474 (newbase (file-name-nondirectory newfile))
2475 (masters
2476 ;; List of potential master files for `newfile'
2477 (mapcar
2478 (lambda (s) (vc-possible-master s newdir newbase))
2479 templates)))
b5446276
DN
2480 (when (or (file-symlink-p oldmaster)
2481 (file-symlink-p (file-name-directory oldmaster)))
2482 (error "This is unsafe in the presence of symbolic links"))
0e362f54
GM
2483 (rename-file
2484 oldmaster
2485 (catch 'found
2486 ;; If possible, keep the master file in the same directory.
b4e4e3a8 2487 (dolist (f masters)
ae67f2d0
DN
2488 (when (and f (string= (file-name-directory (expand-file-name f)) dir))
2489 (throw 'found f)))
0e362f54 2490 ;; If not, just use the first possible place.
b4e4e3a8
SM
2491 (dolist (f masters)
2492 (and f (or (not (setq dir (file-name-directory f)))
2493 (file-directory-p dir))
2494 (throw 'found f)))
0e362f54 2495 (error "New file lacks a version control directory")))))
594722a8 2496
97355c38 2497;;;###autoload
a36319a4
SM
2498(defun vc-delete-file (file)
2499 "Delete file and mark it as such in the version control system."
2500 (interactive "fVC delete file: ")
484c3092 2501 (setq file (expand-file-name file))
c6e44350
AS
2502 (let ((buf (get-file-buffer file))
2503 (backend (vc-backend file)))
2504 (unless backend
86a65190 2505 (error "File %s is not under version control"
c6e44350 2506 (file-name-nondirectory file)))
a36319a4 2507 (unless (vc-find-backend-function backend 'delete-file)
c6e44350 2508 (error "Deleting files under %s is not supported in VC" backend))
b5446276 2509 (when (and buf (buffer-modified-p buf))
a84615c7
SS
2510 (error "Please save or undo your changes before deleting %s" file))
2511 (let ((state (vc-state file)))
2512 (when (eq state 'edited)
2513 (error "Please commit or undo your changes before deleting %s" file))
2514 (when (eq state 'conflict)
2515 (error "Please resolve the conflicts before deleting %s" file)))
ce5a3ac0 2516 (unless (y-or-n-p (format "Really want to delete %s? "
a36319a4
SM
2517 (file-name-nondirectory file)))
2518 (error "Abort!"))
775237d3
SS
2519 (unless (or (file-directory-p file) (null make-backup-files)
2520 (not (file-exists-p file)))
a36319a4
SM
2521 (with-current-buffer (or buf (find-file-noselect file))
2522 (let ((backup-inhibited nil))
ee91bfdf 2523 (backup-buffer))))
05fae1be
DN
2524 ;; Bind `default-directory' so that the command that the backend
2525 ;; runs to remove the file is invoked in the correct context.
2526 (let ((default-directory (file-name-directory file)))
2527 (vc-call-backend backend 'delete-file file))
a36319a4 2528 ;; If the backend hasn't deleted the file itself, let's do it for him.
b5446276 2529 (when (file-exists-p file) (delete-file file))
484c3092
DN
2530 ;; Forget what VC knew about the file.
2531 (vc-file-clearprops file)
64e5a32f
DN
2532 ;; Make sure the buffer is deleted and the *vc-dir* buffers are
2533 ;; updated after this.
2534 (vc-resynch-buffer file nil t)))
a36319a4 2535
29fc1ce9 2536;;;###autoload
594722a8 2537(defun vc-rename-file (old new)
004f9b3f 2538 "Rename file OLD to NEW in both work area and repository."
34291cd2 2539 (interactive "fVC rename file: \nFRename to: ")
260c15b4
SS
2540 ;; in CL I would have said (setq new (merge-pathnames new old))
2541 (let ((old-base (file-name-nondirectory old)))
2542 (when (and (not (string= "" old-base))
2543 (string= "" (file-name-nondirectory new)))
2544 (setq new (concat new old-base))))
a36319a4 2545 (let ((oldbuf (get-file-buffer old)))
b5446276
DN
2546 (when (and oldbuf (buffer-modified-p oldbuf))
2547 (error "Please save files before moving them"))
2548 (when (get-file-buffer new)
2549 (error "Already editing new file name"))
2550 (when (file-exists-p new)
2551 (error "New file already exists"))
86a65190 2552 (let ((state (vc-state old)))
a36319a4
SM
2553 (unless (memq state '(up-to-date edited))
2554 (error "Please %s files before moving them"
2555 (if (stringp state) "check in" "update"))))
2556 (vc-call rename-file old new)
b4e4e3a8 2557 (vc-file-clearprops old)
0e362f54 2558 ;; Move the actual file (unless the backend did it already)
b5446276 2559 (when (file-exists-p old) (rename-file old new))
0e362f54
GM
2560 ;; ?? Renaming a file might change its contents due to keyword expansion.
2561 ;; We should really check out a new copy if the old copy was precisely equal
ac3f4c6f 2562 ;; to some checked-in revision. However, testing for this is tricky....
b5446276
DN
2563 (when oldbuf
2564 (with-current-buffer oldbuf
2565 (let ((buffer-read-only buffer-read-only))
2566 (set-visited-file-name new))
77bf3f54 2567 (vc-mode-line new (vc-backend new))
b5446276 2568 (set-buffer-modified-p nil)))))
0e362f54 2569
637a8ae9 2570;;;###autoload
f35ecf88 2571(defun vc-update-change-log (&rest args)
0e362f54 2572 "Find change log file and add entries from recent version control logs.
d68e6990 2573Normally, find log entries for all registered files in the default
0e362f54 2574directory.
d68e6990 2575
099bd78a 2576With prefix arg of \\[universal-argument], only find log entries for the current buffer's file.
d68e6990
RS
2577
2578With any numeric prefix arg, find log entries for all currently visited
2579files that are under version control. This puts all the entries in the
2580log for the default directory, which may not be appropriate.
2581
099bd78a 2582From a program, any ARGS are assumed to be filenames for which
0e362f54 2583log entries should be gathered."
67242a23
RM
2584 (interactive
2585 (cond ((consp current-prefix-arg) ;C-u
2586 (list buffer-file-name))
2587 (current-prefix-arg ;Numeric argument.
2588 (let ((files nil)
2589 (buffers (buffer-list))
2590 file)
2591 (while buffers
2592 (setq file (buffer-file-name (car buffers)))
f3c61d82 2593 (and file (vc-backend file)
4b40fdea 2594 (setq files (cons file files)))
67242a23 2595 (setq buffers (cdr buffers)))
4b40fdea
PE
2596 files))
2597 (t
0e362f54
GM
2598 ;; Don't supply any filenames to backend; this means
2599 ;; it should find all relevant files relative to
2600 ;; the default-directory.
73a9679c 2601 nil)))
0e362f54
GM
2602 (vc-call-backend (vc-responsible-backend default-directory)
2603 'update-changelog args))
2604
2765044b
DN
2605;; functions that operate on RCS revision numbers. This code should
2606;; also be moved into the backends. It stays for now, however, since
2607;; it is used in code below.
2765044b
DN
2608(defun vc-branch-p (rev)
2609 "Return t if REV is a branch revision."
2610 (not (eq nil (string-match "\\`[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*\\'" rev))))
2611
2612;;;###autoload
2613(defun vc-branch-part (rev)
2614 "Return the branch part of a revision number REV."
2615 (let ((index (string-match "\\.[0-9]+\\'" rev)))
b5446276
DN
2616 (when index
2617 (substring rev 0 index))))
2765044b 2618
1912f6cf
GM
2619(define-obsolete-function-alias
2620 'vc-default-previous-version 'vc-default-previous-revision "23.1")
2621
2765044b
DN
2622(defun vc-default-responsible-p (backend file)
2623 "Indicate whether BACKEND is reponsible for FILE.
2624The default is to return nil always."
2625 nil)
2626
2627(defun vc-default-could-register (backend file)
2628 "Return non-nil if BACKEND could be used to register FILE.
2629The default implementation returns t for all files."
2630 t)
2631
2632(defun vc-default-latest-on-branch-p (backend file)
2633 "Return non-nil if FILE is the latest on its branch.
2634This default implementation always returns non-nil, which means that
ac3f4c6f 2635editing non-current revisions is not supported by default."
2765044b
DN
2636 t)
2637
ac3f4c6f 2638(defun vc-default-init-revision (backend) vc-default-init-revision)
2765044b 2639
ac3f4c6f
ER
2640(defun vc-default-find-revision (backend file rev buffer)
2641 "Provide the new `find-revision' op based on the old `checkout' op.
2765044b 2642This is only for compatibility with old backends. They should be updated
ac3f4c6f 2643to provide the `find-revision' operation instead."
2765044b
DN
2644 (let ((tmpfile (make-temp-file (expand-file-name file))))
2645 (unwind-protect
2646 (progn
2647 (vc-call-backend backend 'checkout file nil rev tmpfile)
2648 (with-current-buffer buffer
2649 (insert-file-contents-literally tmpfile)))
2650 (delete-file tmpfile))))
2651
2765044b
DN
2652(defun vc-default-rename-file (backend old new)
2653 (condition-case nil
2654 (add-name-to-file old new)
2655 (error (rename-file old new)))
2656 (vc-delete-file old)
2657 (with-current-buffer (find-file-noselect new)
2658 (vc-register)))
2659
17f3909f 2660(defalias 'vc-default-check-headers 'ignore)
2765044b 2661
5ac92c5f
GM
2662(declare-function log-edit-mode "log-edit" ())
2663
09158997
DN
2664(defun vc-default-log-edit-mode (backend) (log-edit-mode))
2665
2765044b
DN
2666(defun vc-default-log-view-mode (backend) (log-view-mode))
2667
2668(defun vc-default-show-log-entry (backend rev)
2669 (with-no-warnings
2670 (log-view-goto-rev rev)))
2671
2672(defun vc-default-comment-history (backend file)
2673 "Return a string with all log entries stored in BACKEND for FILE."
7fbb4797
DN
2674 (when (vc-find-backend-function backend 'print-log)
2675 (with-current-buffer "*vc*"
a749e19d 2676 (vc-call-backend backend 'print-log (list file))
7fbb4797 2677 (buffer-string))))
2765044b 2678
2765044b
DN
2679(defun vc-default-receive-file (backend file rev)
2680 "Let BACKEND receive FILE from another version control system."
24703c3c 2681 (vc-call-backend backend 'register (list file) rev ""))
2765044b 2682
370fded4 2683(defun vc-default-retrieve-tag (backend dir name update)
2765044b
DN
2684 (if (string= name "")
2685 (progn
2686 (vc-file-tree-walk
2687 dir
2688 (lambda (f) (and
2689 (vc-up-to-date-p f)
2690 (vc-error-occurred
a749e19d 2691 (vc-call-backend backend 'checkout f nil "")
b5446276 2692 (when update (vc-resynch-buffer f t t)))))))
370fded4 2693 (let ((result (vc-tag-precondition dir)))
2765044b
DN
2694 (if (stringp result)
2695 (error "File %s is locked" result)
2696 (setq update (and (eq result 'visited) update))
2697 (vc-file-tree-walk
2698 dir
2699 (lambda (f) (vc-error-occurred
a749e19d 2700 (vc-call-backend backend 'checkout f nil name)
b5446276 2701 (when update (vc-resynch-buffer f t t)))))))))
2765044b
DN
2702
2703(defun vc-default-revert (backend file contents-done)
2704 (unless contents-done
ac3f4c6f 2705 (let ((rev (vc-working-revision file))
2765044b
DN
2706 (file-buffer (or (get-file-buffer file) (current-buffer))))
2707 (message "Checking out %s..." file)
2708 (let ((failed t)
2709 (backup-name (car (find-backup-file-name file))))
2710 (when backup-name
2711 (copy-file file backup-name 'ok-if-already-exists 'keep-date)
2712 (unless (file-writable-p file)
2713 (set-file-modes file (logior (file-modes file) 128))))
2714 (unwind-protect
2715 (let ((coding-system-for-read 'no-conversion)
2716 (coding-system-for-write 'no-conversion))
2717 (with-temp-file file
2718 (let ((outbuf (current-buffer)))
2719 ;; Change buffer to get local value of vc-checkout-switches.
2720 (with-current-buffer file-buffer
2721 (let ((default-directory (file-name-directory file)))
a749e19d
SM
2722 (vc-call-backend backend 'find-revision
2723 file rev outbuf)))))
2765044b
DN
2724 (setq failed nil))
2725 (when backup-name
2726 (if failed
2727 (rename-file backup-name file 'ok-if-already-exists)
2728 (and (not vc-make-backup-files) (delete-file backup-name))))))
2729 (message "Checking out %s...done" file))))
2730
17f3909f 2731(defalias 'vc-default-revision-completion-table 'ignore)
f41d99b0 2732(defalias 'vc-default-mark-resolved 'ignore)
2765044b 2733
fb0ac090
AJ
2734(defun vc-default-dir-status-files (backend dir files default-state update-function)
2735 (funcall update-function
2736 (mapcar (lambda (file) (list file default-state)) files)))
2737
2765044b
DN
2738(defun vc-check-headers ()
2739 "Check if the current file has any headers in it."
2740 (interactive)
2741 (vc-call-backend (vc-backend buffer-file-name) 'check-headers))
2742
7d2d9482 2743\f
594722a8 2744
b1ddeeb7
ER
2745;; These things should probably be generally available
2746
f731e2f9
DN
2747(defun vc-string-prefix-p (prefix string)
2748 (let ((lpref (length prefix)))
2749 (and (>= (length string) lpref)
2750 (eq t (compare-strings prefix nil nil string nil lpref)))))
2751
b1ddeeb7
ER
2752(defun vc-file-tree-walk (dirname func &rest args)
2753 "Walk recursively through DIRNAME.
2754Invoke FUNC f ARGS on each VC-managed file f underneath it."
2755 (vc-file-tree-walk-internal (expand-file-name dirname) func args)
2756 (message "Traversing directory %s...done" dirname))
2757
2758(defun vc-file-tree-walk-internal (file func args)
2759 (if (not (file-directory-p file))
2760 (when (vc-backend file) (apply func file args))
2761 (message "Traversing directory %s..." (abbreviate-file-name file))
2762 (let ((dir (file-name-as-directory file)))
2763 (mapcar
2764 (lambda (f) (or
2765 (string-equal f ".")
2766 (string-equal f "..")
2767 (member f vc-directory-exclusion-list)
2768 (let ((dirf (expand-file-name f dir)))
2769 (or
2770 (file-symlink-p dirf) ;; Avoid possible loops.
2771 (vc-file-tree-walk-internal dirf func args)))))
2772 (directory-files dir)))))
2773
594722a8
ER
2774(provide 'vc)
2775
594722a8 2776;;; vc.el ends here