vc-mcvs.el 22 KB

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