~ubuntu-branches/ubuntu/karmic/emacs-snapshot/karmic

« back to all changes in this revision

Viewing changes to lisp/obsolete/vc-mcvs.el

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2009-04-05 09:14:30 UTC
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: james.westby@ubuntu.com-20090405091430-nw07lynn2arotjbe
Tags: upstream-20090320
ImportĀ upstreamĀ versionĀ 20090320

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;; vc-mcvs.el --- VC backend for the Meta-CVS version-control system
 
2
 
 
3
;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
 
4
;;   Free Software Foundation, Inc.
 
5
 
 
6
;; Author:      FSF (see vc.el for full credits)
 
7
;; Maintainer:  None
 
8
 
 
9
;; This file is part of GNU Emacs.
 
10
 
 
11
;; GNU Emacs is free software: you can redistribute it and/or modify
 
12
;; it under the terms of the GNU General Public License as published by
 
13
;; the Free Software Foundation, either version 3 of the License, or
 
14
;; (at your option) any later version.
 
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
 
22
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
23
 
 
24
;;; Commentary:
 
25
 
 
26
;; ********** READ THIS! **********
 
27
;;
 
28
;; This file apparently does not work with the new (as of Emacs 23)
 
29
;; VC code.  Use at your own risk.  Please contact emacs-devel if you
 
30
;; can maintain this file and update it to work correctly.
 
31
;;
 
32
;; ********** READ THIS! **********
 
33
 
 
34
;; This file has been obsolete and unsupported since Emacs 23.1.
 
35
 
 
36
 
 
37
;; The home page of the Meta-CVS version control system is at
 
38
;;
 
39
;;      http://users.footprints.net/~kaz/mcvs.html
 
40
;;
 
41
;; This is derived from vc-cvs.el as follows:
 
42
;; - cp vc-cvs.el vc-mcvs.el
 
43
;; - Replace CVS/ with MCVS/CVS/
 
44
;; - Replace 'CVS with 'MCVS
 
45
;; - Replace -cvs- with -mcvs-
 
46
;; - Replace most of the rest of CVS to Meta-CVS
 
47
;;
 
48
;; Then of course started the hacking.  Only a small part of the code
 
49
;; has been touched and not much more than that was tested, so if
 
50
;; you bump into a bug, don't be surprised: just report it to me.
 
51
;;
 
52
;; What has been partly tested:
 
53
;; - C-x v v to start editing a file that was checked out with CVSREAD on.
 
54
;; - C-x v v to commit a file
 
55
;; - C-x v =
 
56
;; - C-x v l
 
57
;; - C-x v i
 
58
;; - C-x v g
 
59
;; - M-x vc-rename-file RET
 
60
 
 
61
;;; Bugs:
 
62
 
 
63
;; - Retrieving tags doesn't filter `cvs update' output and thus
 
64
;;   parses bogus filenames.  Don't know if it harms.
 
65
 
 
66
;;; Code:
 
67
 
 
68
(eval-when-compile (require 'vc))
 
69
(require 'vc-cvs)
 
70
 
 
71
;;;
 
72
;;; Customization options
 
73
;;;
 
74
 
 
75
(defcustom vc-mcvs-global-switches nil
 
76
  "Global switches to pass to any Meta-CVS command."
 
77
  :type '(choice (const :tag "None" nil)
 
78
                 (string :tag "Argument String")
 
79
                 (repeat :tag "Argument List" :value ("") string))
 
80
  :version "22.1"
 
81
  :group 'vc)
 
82
 
 
83
(defcustom vc-mcvs-register-switches nil
 
84
  "Switches for registering a file into Meta-CVS.
 
85
A string or list of strings passed to the checkin program by
 
86
\\[vc-register].  If nil, use the value of `vc-register-switches'.
 
87
If t, use no switches."
 
88
  :type '(choice (const :tag "Unspecified" nil)
 
89
                 (const :tag "None" t)
 
90
                 (string :tag "Argument String")
 
91
                 (repeat :tag "Argument List" :value ("") string))
 
92
  :version "22.1"
 
93
  :group 'vc)
 
94
 
 
95
(defcustom vc-mcvs-diff-switches nil
 
96
  "String or list of strings specifying switches for Meta-CVS diff under VC.
 
97
If nil, use the value of `vc-diff-switches'.  If t, use no switches."
 
98
  :type '(choice (const :tag "Unspecified" nil)
 
99
                 (const :tag "None" t)
 
100
                 (string :tag "Argument String")
 
101
                 (repeat :tag "Argument List" :value ("") string))
 
102
  :version "22.1"
 
103
  :group 'vc)
 
104
 
 
105
(defcustom vc-mcvs-header (or (cdr (assoc 'MCVS vc-header-alist))
 
106
                              vc-cvs-header)
 
107
  "Header keywords to be inserted by `vc-insert-headers'."
 
108
  :version "22.1"
 
109
  :type '(repeat string)
 
110
  :group 'vc)
 
111
 
 
112
(defcustom vc-mcvs-use-edit vc-cvs-use-edit
 
113
  "Non-nil means to use `cvs edit' to \"check out\" a file.
 
114
This is only meaningful if you don't use the implicit checkout model
 
115
\(i.e. if you have $CVSREAD set)."
 
116
  :type 'boolean
 
117
  :version "22.1"
 
118
  :group 'vc)
 
119
 
 
120
;;; Properties of the backend
 
121
 
 
122
(defalias 'vc-mcvs-revision-granularity 'vc-cvs-revision-granularity)
 
123
(defalias 'vc-mcvs-checkout-model 'vc-cvs-checkout-model)
 
124
 
 
125
;;;
 
126
;;; State-querying functions
 
127
;;;
 
128
 
 
129
;;;###autoload (defun vc-mcvs-registered (file)
 
130
;;;###autoload   (if (vc-find-root file "MCVS/CVS")
 
131
;;;###autoload       (progn
 
132
;;;###autoload         (load "vc-mcvs")
 
133
;;;###autoload         (vc-mcvs-registered file))))
 
134
 
 
135
(defun vc-mcvs-root (file)
 
136
  "Return the root directory of a Meta-CVS project, if any."
 
137
  (or (vc-file-getprop file 'mcvs-root)
 
138
      (vc-file-setprop file 'mcvs-root (vc-find-root file "MCVS/CVS"))))
 
139
 
 
140
(defun vc-mcvs-read (file)
 
141
  (if (file-readable-p file)
 
142
      (with-temp-buffer
 
143
        (insert-file-contents file)
 
144
        (goto-char (point-min))
 
145
        (read (current-buffer)))))
 
146
 
 
147
(defun vc-mcvs-map-file (dir file)
 
148
  (let ((map (vc-mcvs-read (expand-file-name "MCVS/MAP" dir)))
 
149
        inode)
 
150
    (dolist (x map inode)
 
151
      (if (equal (nth 2 x) file) (setq inode (nth 1 x))))))
 
152
 
 
153
(defun vc-mcvs-registered (file)
 
154
  (let (root inode cvsfile)
 
155
    (when (and (setq root (vc-mcvs-root file))
 
156
               (setq inode (vc-mcvs-map-file
 
157
                            root (file-relative-name file root))))
 
158
      (vc-file-setprop file 'mcvs-inode inode)
 
159
      ;; Avoid calling `mcvs diff' in vc-workfile-unchanged-p.
 
160
      (vc-file-setprop file 'vc-checkout-time
 
161
                       (if (vc-cvs-registered
 
162
                            (setq cvsfile (expand-file-name inode root)))
 
163
                           (vc-file-getprop cvsfile 'vc-checkout-time)
 
164
                         ;; The file might not be registered yet because
 
165
                         ;; of lazy-adding.
 
166
                         0))
 
167
      t)))
 
168
 
 
169
(defun vc-mcvs-state (file)
 
170
  ;; This would assume the Meta-CVS sandbox is synchronized.
 
171
  ;; (vc-mcvs-cvs state file))
 
172
  "Meta-CVS-specific version of `vc-state'."
 
173
  (if (vc-stay-local-p file)
 
174
      (let ((state (vc-file-getprop file 'vc-state)))
 
175
        ;; If we should stay local, use the heuristic but only if
 
176
        ;; we don't have a more precise state already available.
 
177
        (if (memq state '(up-to-date edited))
 
178
            (vc-mcvs-state-heuristic file)
 
179
          state))
 
180
    (with-temp-buffer
 
181
      (setq default-directory (vc-mcvs-root file))
 
182
      (vc-mcvs-command t 0 file "status")
 
183
      (vc-cvs-parse-status t))))
 
184
 
 
185
 
 
186
(defalias 'vc-mcvs-state-heuristic 'vc-cvs-state-heuristic)
 
187
 
 
188
(defun vc-mcvs-working-revision (file)
 
189
  (vc-cvs-working-revision
 
190
   (expand-file-name (vc-file-getprop file 'mcvs-inode)
 
191
                     (vc-file-getprop file 'mcvs-root))))
 
192
 
 
193
;;;
 
194
;;; State-changing functions
 
195
;;;
 
196
 
 
197
(defun vc-mcvs-register (files &optional rev comment)
 
198
  "Register FILES into the Meta-CVS version-control system.
 
199
COMMENT can be used to provide an initial description of FILE.
 
200
Passes either `vc-mcvs-register-switches' or `vc-register-switches'
 
201
to the Meta-CVS command."
 
202
  ;; FIXME: multiple-file case should be made to work.
 
203
  (if (> (length files) 1) (error "Registering filesets is not yet supported."))
 
204
  (let* ((file (car files))
 
205
         (filename (file-name-nondirectory file))
 
206
         (extpos (string-match "\\." filename))
 
207
         (ext (if extpos (substring filename (1+ extpos))))
 
208
         (root (vc-mcvs-root file))
 
209
         (types-file (expand-file-name "MCVS/TYPES" root))
 
210
         (map-file (expand-file-name "MCVS/MAP" root))
 
211
         (types (vc-mcvs-read types-file)))
 
212
    ;; Make sure meta files like MCVS/MAP are not read-only (happens with
 
213
    ;; CVSREAD) since Meta-CVS doesn't pay attention to it at all and goes
 
214
    ;; belly-up.
 
215
    (unless (file-writable-p map-file)
 
216
      (vc-checkout map-file t))
 
217
    (unless (or (file-writable-p types-file) (not (file-exists-p types-file)))
 
218
      (vc-checkout types-file t))
 
219
    ;; Make sure the `mcvs add' will not fire up the CVSEDITOR
 
220
    ;; to add a rule for the given file's extension.
 
221
    (when (and ext (not (assoc ext types)))
 
222
      (let ((type (completing-read "Type to use (default): "
 
223
                                   '("default" "name-only" "keep-old"
 
224
                                     "binary" "value-only")
 
225
                                   nil t nil nil "default")))
 
226
        (push (list ext (make-symbol (upcase (concat ":" type)))) types)
 
227
        (setq types (sort types (lambda (x y) (string< (car x) (car y)))))
 
228
        (with-current-buffer (find-file-noselect types-file)
 
229
          (erase-buffer)
 
230
          (pp types (current-buffer))
 
231
          (save-buffer)
 
232
          (unless (get-buffer-window (current-buffer) t)
 
233
            (kill-buffer (current-buffer))))))
 
234
    ;; Now do the ADD.
 
235
    (prog1 (apply 'vc-mcvs-command nil 0 file
 
236
                  "add"
 
237
                  (and comment (string-match "[^\t\n ]" comment)
 
238
                       (concat "-m" comment))
 
239
                  (vc-switches 'MCVS 'register))
 
240
      ;; I'm not sure exactly why, but if we don't setup the inode and root
 
241
      ;; prop of the file, things break later on in vc-mode-line that
 
242
      ;; ends up calling vc-mcvs-working-revision.
 
243
      ;; We also need to set vc-checkout-time so that vc-workfile-unchanged-p
 
244
      ;; doesn't try to call `mcvs diff' on the file.
 
245
      (vc-mcvs-registered file))))
 
246
 
 
247
(defalias 'vc-mcvs-responsible-p 'vc-mcvs-root
 
248
  "Return non-nil if CVS thinks it is responsible for FILE.")
 
249
 
 
250
(defalias 'vc-cvs-could-register 'vc-cvs-responsible-p
 
251
  "Return non-nil if FILE could be registered in Meta-CVS.
 
252
This is only possible if Meta-CVS is responsible for FILE's directory.")
 
253
 
 
254
(defun vc-mcvs-checkin (files rev comment)
 
255
  "Meta-CVS-specific version of `vc-backend-checkin'."
 
256
  (unless (or (not rev) (vc-mcvs-valid-revision-number-p rev))
 
257
    (if (not (vc-mcvs-valid-symbolic-tag-name-p rev))
 
258
        (error "%s is not a valid symbolic tag name" rev)
 
259
      ;; If the input revision is a valid symbolic tag name, we create it
 
260
      ;; as a branch, commit and switch to it.
 
261
      ;; This file-specific form of branching is deprecated.
 
262
      ;; We can't use `mcvs branch' and `mcvs switch' because they cannot
 
263
      ;; be applied just to this one file.
 
264
      (apply 'vc-mcvs-command nil 0 files "tag" "-b" (list rev))
 
265
      (apply 'vc-mcvs-command nil 0 files "update" "-r" (list rev))
 
266
      (mapc (lambda (file) (vc-file-setprop file 'vc-mcvs-sticky-tag rev))
 
267
            files)
 
268
      (setq rev nil)))
 
269
  ;; This commit might cvs-commit several files (e.g. MAP and TYPES)
 
270
  ;; so using numbered revs here is dangerous and somewhat meaningless.
 
271
  (when rev (error "Cannot commit to a specific revision number"))
 
272
  (let ((status (apply 'vc-mcvs-command nil 1 files
 
273
                       "ci" "-m" comment
 
274
                       (vc-switches 'MCVS 'checkin))))
 
275
    (set-buffer "*vc*")
 
276
    (goto-char (point-min))
 
277
    (when (not (zerop status))
 
278
      ;; Check checkin problem.
 
279
      (cond
 
280
       ((re-search-forward "Up-to-date check failed" nil t)
 
281
        (mapc (lambda (file) (vc-file-setprop file 'vc-state 'needs-merge))
 
282
              files)
 
283
        (error "%s" (substitute-command-keys
 
284
                (concat "Up-to-date check failed: "
 
285
                        "type \\[vc-next-action] to merge in changes"))))
 
286
       (t
 
287
        (pop-to-buffer (current-buffer))
 
288
        (goto-char (point-min))
 
289
        (shrink-window-if-larger-than-buffer)
 
290
        (error "Check-in failed"))))
 
291
    ;; Single-file commit?  Then update the revision by parsing the buffer.
 
292
    ;; Otherwise we can't necessarily tell what goes with what; clear
 
293
    ;; its properties so they have to be refetched.
 
294
    (if (= (length files) 1)
 
295
        (vc-file-setprop
 
296
         (car files) 'vc-working-revision
 
297
         (vc-parse-buffer "^\\(new\\|initial\\) revision: \\([0-9.]+\\)" 2))
 
298
      (mapc (lambda (file) (vc-file-clearprops file)) files))
 
299
    ;; Anyway, forget the checkout model of the file, because we might have
 
300
    ;; guessed wrong when we found the file.  After commit, we can
 
301
    ;; tell it from the permissions of the file (see
 
302
    ;; vc-mcvs-checkout-model).
 
303
    (mapc (lambda (file) (vc-file-setprop file 'vc-checkout-model nil))
 
304
            files)
 
305
 
 
306
    ;; if this was an explicit check-in (does not include creation of
 
307
    ;; a branch), remove the sticky tag.
 
308
    (if (and rev (not (vc-mcvs-valid-symbolic-tag-name-p rev)))
 
309
        (vc-mcvs-command nil 0 files "update" "-A"))))
 
310
 
 
311
(defun vc-mcvs-find-revision (file rev buffer)
 
312
  (apply 'vc-mcvs-command
 
313
         buffer 0 file
 
314
         "-Q"                           ; suppress diagnostic output
 
315
         "update"
 
316
         (and rev (not (string= rev ""))
 
317
              (concat "-r" rev))
 
318
         "-p"
 
319
         (vc-switches 'MCVS 'checkout)))
 
320
 
 
321
(defun vc-mcvs-checkout (file &optional editable rev)
 
322
  (message "Checking out %s..." file)
 
323
  (with-current-buffer (or (get-file-buffer file) (current-buffer))
 
324
    (vc-mcvs-update file editable rev (vc-switches 'MCVS 'checkout)))
 
325
  (vc-mode-line file)
 
326
  (message "Checking out %s...done" file))
 
327
 
 
328
(defun vc-mcvs-update (file editable rev switches)
 
329
  (if (and (file-exists-p file) (not rev))
 
330
      ;; If no revision was specified, just make the file writable
 
331
      ;; if necessary (using `cvs-edit' if requested).
 
332
      (and editable (not (eq (vc-mcvs-checkout-model (list file)) 'implicit))
 
333
           (if vc-mcvs-use-edit
 
334
               (vc-mcvs-command nil 0 file "edit")
 
335
             (set-file-modes file (logior (file-modes file) 128))
 
336
             (if (equal file buffer-file-name) (toggle-read-only -1))))
 
337
    ;; Check out a particular revision (or recreate the file).
 
338
    (vc-file-setprop file 'vc-working-revision nil)
 
339
    (apply 'vc-mcvs-command nil 0 file
 
340
           (if editable "-w")
 
341
           "update"
 
342
           ;; default for verbose checkout: clear the sticky tag so
 
343
           ;; that the actual update will get the head of the trunk
 
344
           (if (or (not rev) (string= rev ""))
 
345
               "-A"
 
346
             (concat "-r" rev))
 
347
           switches)))
 
348
 
 
349
(defun vc-mcvs-rename-file (old new)
 
350
  (vc-mcvs-command nil 0 new "move" (file-relative-name old)))
 
351
 
 
352
(defun vc-mcvs-revert (file &optional contents-done)
 
353
  "Revert FILE to the working revision it was based on."
 
354
  (vc-default-revert 'MCVS file contents-done)
 
355
  (unless (eq (vc-mcvs-checkout-model (list file)) 'implicit)
 
356
    (if vc-mcvs-use-edit
 
357
        (vc-mcvs-command nil 0 file "unedit")
 
358
      ;; Make the file read-only by switching off all w-bits
 
359
      (set-file-modes file (logand (file-modes file) 3950)))))
 
360
 
 
361
(defun vc-mcvs-merge (file first-revision &optional second-revision)
 
362
  "Merge changes into current working copy of FILE.
 
363
The changes are between FIRST-REVISION and SECOND-REVISION."
 
364
  (vc-mcvs-command nil 0 file
 
365
                   "update" "-kk"
 
366
                   (concat "-j" first-revision)
 
367
                   (concat "-j" second-revision))
 
368
  (vc-file-setprop file 'vc-state 'edited)
 
369
  (with-current-buffer (get-buffer "*vc*")
 
370
    (goto-char (point-min))
 
371
    (if (re-search-forward "conflicts during merge" nil t)
 
372
        1                               ; signal error
 
373
      0)))                              ; signal success
 
374
 
 
375
(defun vc-mcvs-merge-news (file)
 
376
  "Merge in any new changes made to FILE."
 
377
  (message "Merging changes into %s..." file)
 
378
  ;; (vc-file-setprop file 'vc-working-revision nil)
 
379
  (vc-file-setprop file 'vc-checkout-time 0)
 
380
  (vc-mcvs-command nil 0 file "update")
 
381
  ;; Analyze the merge result reported by Meta-CVS, and set
 
382
  ;; file properties accordingly.
 
383
  (with-current-buffer (get-buffer "*vc*")
 
384
    (goto-char (point-min))
 
385
    ;; get new working revision
 
386
    (if (re-search-forward
 
387
         "^Merging differences between [0-9.]* and \\([0-9.]*\\) into" nil t)
 
388
        (vc-file-setprop file 'vc-working-revision (match-string 1))
 
389
      (vc-file-setprop file 'vc-working-revision nil))
 
390
    ;; get file status
 
391
    (prog1
 
392
        (if (eq (buffer-size) 0)
 
393
            0 ;; there were no news; indicate success
 
394
          (if (re-search-forward
 
395
               (concat "^\\([CMUP] \\)?"
 
396
                       ".*"
 
397
                       "\\( already contains the differences between \\)?")
 
398
               nil t)
 
399
              (cond
 
400
               ;; Merge successful, we are in sync with repository now
 
401
               ((or (match-string 2)
 
402
                    (string= (match-string 1) "U ")
 
403
                    (string= (match-string 1) "P "))
 
404
                (vc-file-setprop file 'vc-state 'up-to-date)
 
405
                (vc-file-setprop file 'vc-checkout-time
 
406
                                 (nth 5 (file-attributes file)))
 
407
                0);; indicate success to the caller
 
408
               ;; Merge successful, but our own changes are still in the file
 
409
               ((string= (match-string 1) "M ")
 
410
                (vc-file-setprop file 'vc-state 'edited)
 
411
                0);; indicate success to the caller
 
412
               ;; Conflicts detected!
 
413
               (t
 
414
                (vc-file-setprop file 'vc-state 'edited)
 
415
                1);; signal the error to the caller
 
416
               )
 
417
            (pop-to-buffer "*vc*")
 
418
            (error "Couldn't analyze mcvs update result")))
 
419
      (message "Merging changes into %s...done" file))))
 
420
 
 
421
(defun vc-mcvs-modify-change-comment (files rev comment)
 
422
  "Modify the change comments for FILES on a specified REV.
 
423
Will fail unless you have administrative privileges on the repo."
 
424
  (vc-mcvs-command nil 0 files "rcs" (concat "-m" comment ":" rev)))
 
425
 
 
426
 
 
427
;;;
 
428
;;; History functions
 
429
;;;
 
430
 
 
431
(defun vc-mcvs-print-log (files &optional buffer)
 
432
  "Get change log associated with FILES."
 
433
  (let ((default-directory (vc-mcvs-root (car files))))
 
434
    ;; Run the command from the root dir so that `mcvs filt' returns
 
435
    ;; valid relative names.
 
436
    (vc-mcvs-command
 
437
     buffer
 
438
     (if (vc-stay-local-p files) 'async 0)
 
439
     files "log")))
 
440
 
 
441
(defun vc-mcvs-diff (files &optional oldvers newvers buffer)
 
442
  "Get a difference report using Meta-CVS between two revisions of FILES."
 
443
    (let* ((async (and (not vc-disable-async-diff)
 
444
                       (vc-stay-local-p files)))
 
445
           ;; Run the command from the root dir so that `mcvs filt' returns
 
446
           ;; valid relative names.
 
447
           (default-directory (vc-mcvs-root (car files)))
 
448
           (status
 
449
            (apply 'vc-mcvs-command (or buffer "*vc-diff*")
 
450
                   (if async 'async 1)
 
451
                   files "diff"
 
452
                   (and oldvers (concat "-r" oldvers))
 
453
                   (and newvers (concat "-r" newvers))
 
454
                   (vc-switches 'MCVS 'diff))))
 
455
      (if async 1 status)))            ; async diff, pessimistic assumption.
 
456
 
 
457
(defun vc-mcvs-annotate-command (file buffer &optional revision)
 
458
  "Execute \"mcvs annotate\" on FILE, inserting the contents in BUFFER.
 
459
Optional arg REVISION is a revision to annotate from."
 
460
  (vc-mcvs-command
 
461
   buffer
 
462
   (if (vc-stay-local-p file) 'async 0)
 
463
   file "annotate" (if revision (concat "-r" revision)))
 
464
  (with-current-buffer buffer
 
465
    (goto-char (point-min))
 
466
    (re-search-forward "^[0-9]")
 
467
    (delete-region (point-min) (1- (point)))))
 
468
 
 
469
(defalias 'vc-mcvs-annotate-current-time 'vc-cvs-annotate-current-time)
 
470
(defalias 'vc-mcvs-annotate-time 'vc-cvs-annotate-time)
 
471
 
 
472
;;;
 
473
;;; Tag system
 
474
;;;
 
475
 
 
476
(defun vc-mcvs-create-tag (dir name branchp)
 
477
  "Assign to DIR's current revision a given NAME.
 
478
If BRANCHP is non-nil, the name is created as a branch (and the current
 
479
workspace is immediately moved to that new branch)."
 
480
  (if (not branchp)
 
481
      (vc-mcvs-command nil 0 dir "tag" "-c" name)
 
482
    (vc-mcvs-command nil 0 dir "branch" name)
 
483
    (vc-mcvs-command nil 0 dir "switch" name)))
 
484
 
 
485
(defun vc-mcvs-retrieve-tag (dir name update)
 
486
  "Retrieve a tag at and below DIR.
 
487
NAME is the name of the tag; if it is empty, do a `cvs update'.
 
488
If UPDATE is non-nil, then update (resynch) any affected buffers."
 
489
  (with-current-buffer (get-buffer-create "*vc*")
 
490
    (let ((default-directory dir)
 
491
          (sticky-tag))
 
492
      (erase-buffer)
 
493
      (if (or (not name) (string= name ""))
 
494
          (vc-mcvs-command t 0 nil "update")
 
495
        (vc-mcvs-command t 0 nil "update" "-r" name)
 
496
        (setq sticky-tag name))
 
497
      (when update
 
498
        (goto-char (point-min))
 
499
        (while (not (eobp))
 
500
          (if (looking-at "\\([CMUP]\\) \\(.*\\)")
 
501
              (let* ((file (expand-file-name (match-string 2) dir))
 
502
                     (state (match-string 1))
 
503
                     (buffer (find-buffer-visiting file)))
 
504
                (when buffer
 
505
                  (cond
 
506
                   ((or (string= state "U")
 
507
                        (string= state "P"))
 
508
                    (vc-file-setprop file 'vc-state 'up-to-date)
 
509
                    (vc-file-setprop file 'vc-working-revision nil)
 
510
                    (vc-file-setprop file 'vc-checkout-time
 
511
                                     (nth 5 (file-attributes file))))
 
512
                   ((or (string= state "M")
 
513
                        (string= state "C"))
 
514
                    (vc-file-setprop file 'vc-state 'edited)
 
515
                    (vc-file-setprop file 'vc-working-revision nil)
 
516
                    (vc-file-setprop file 'vc-checkout-time 0)))
 
517
                  (vc-file-setprop file 'vc-mcvs-sticky-tag sticky-tag)
 
518
                  (vc-resynch-buffer file t t))))
 
519
          (forward-line 1))))))
 
520
 
 
521
 
 
522
;;;
 
523
;;; Miscellaneous
 
524
;;;
 
525
 
 
526
(defalias 'vc-mcvs-make-version-backups-p 'vc-stay-local-p
 
527
  "Return non-nil if version backups should be made for FILE.")
 
528
(defalias 'vc-mcvs-check-headers 'vc-cvs-check-headers)
 
529
 
 
530
 
 
531
;;;
 
532
;;; Internal functions
 
533
;;;
 
534
 
 
535
(defun vc-mcvs-command (buffer okstatus file &rest flags)
 
536
  "A wrapper around `vc-do-command' for use in vc-mcvs.el.
 
537
The difference to vc-do-command is that this function always invokes `mcvs',
 
538
and that it passes `vc-mcvs-global-switches' to it before FLAGS."
 
539
  (let ((args (append '("--error-terminate")
 
540
                      (if (stringp vc-mcvs-global-switches)
 
541
                          (cons vc-mcvs-global-switches flags)
 
542
                        (append vc-mcvs-global-switches flags)))))
 
543
    (if (not (member (car flags) '("diff" "log" "status")))
 
544
        ;; No need to filter: do it the easy way.
 
545
        (apply 'vc-do-command (or buffer "*vc*") okstatus "mcvs" file args)
 
546
      ;; We need to filter the output.
 
547
      ;; The output of the filter uses filenames relative to the root,
 
548
      ;; so we need to change the default-directory.
 
549
      ;; (assert (equal default-directory (vc-mcvs-root file)))
 
550
      (vc-do-command
 
551
       (or buffer "*vc*") okstatus "sh" nil "-c"
 
552
       (concat "mcvs "
 
553
               (mapconcat
 
554
                'shell-quote-argument
 
555
                (append (remq nil args)
 
556
                        (if file (list (file-relative-name file))))
 
557
                " ")
 
558
               " | mcvs filt")))))
 
559
 
 
560
(defun vc-mcvs-repository-hostname (dirname)
 
561
  (vc-cvs-repository-hostname (vc-mcvs-root dirname)))
 
562
 
 
563
(defun vc-mcvs-dir-state-heuristic (dir)
 
564
  "Find the Meta-CVS state of all files in DIR, using only local information."
 
565
  (with-temp-buffer
 
566
    (vc-cvs-get-entries dir)
 
567
    (goto-char (point-min))
 
568
    (while (not (eobp))
 
569
      ;; Meta-MCVS-removed files are not taken under VC control.
 
570
      (when (looking-at "/\\([^/]*\\)/[^/-]")
 
571
        (let ((file (expand-file-name (match-string 1) dir)))
 
572
          (unless (vc-file-getprop file 'vc-state)
 
573
            (vc-cvs-parse-entry file t))))
 
574
      (forward-line 1))))
 
575
 
 
576
(defalias 'vc-mcvs-valid-symbolic-tag-name-p 'vc-cvs-valid-symbolic-tag-name-p)
 
577
(defalias 'vc-mcvs-valid-revision-number-p 'vc-cvs-valid-revision-number-p)
 
578
 
 
579
(provide 'vc-mcvs)
 
580
 
 
581
;; ********** READ THIS! **********
 
582
;;
 
583
;; This file apparently does not work with the new (as of Emacs 23)
 
584
;; VC code.  Use at your own risk.  Please contact emacs-devel if you
 
585
;; can maintain this file and update it to work correctly.
 
586
;;
 
587
;; ********** READ THIS! **********
 
588
 
 
589
;; arch-tag: a39c7c1c-5247-429d-88df-dd7187d2e704
 
590
;;; vc-mcvs.el ends here