comparison lisp/vc-mcvs.el @ 50952:1731748fbe8c

(vc-mcvs-command): Filter output of `status'. (vc-mcvs-state, vc-mcvs-dir-state, vc-mcvs-print-log, vc-mcvs-diff): Change dir so that the filtered output of `mcvs makes sense. (vc-mcvs-mode-line-string): Handle the case where CVS is desync'd. (vc-mcvs-diff-tree): Don't bother with the local-diff code. (vc-mcvs-create-snapshot): Use `branch' and `switch'.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Sun, 11 May 2003 23:55:07 +0000
parents dc235df7e226
children 575459cc44fb
comparison
equal deleted inserted replaced
50951:75cc899eee26 50952:1731748fbe8c
48 ;; - C-x v g 48 ;; - C-x v g
49 ;; - M-x vc-rename-file RET 49 ;; - M-x vc-rename-file RET
50 50
51 ;;; Bugs: 51 ;;; Bugs:
52 52
53 ;; - VC-dired doesn't work. 53 ;; - Retrieving snapshots doesn't filter `cvs update' output and thus
54 ;; parses bogus filenames. Don't know if it harms.
54 55
55 ;;; Code: 56 ;;; Code:
56 57
57 (eval-when-compile (require 'vc)) 58 (eval-when-compile (require 'vc))
58 (require 'vc-cvs) 59 (require 'vc-cvs)
183 ;; we don't have a more precise state already available. 184 ;; we don't have a more precise state already available.
184 (if (memq state '(up-to-date edited)) 185 (if (memq state '(up-to-date edited))
185 (vc-mcvs-state-heuristic file) 186 (vc-mcvs-state-heuristic file)
186 state)) 187 state))
187 (with-temp-buffer 188 (with-temp-buffer
188 (cd (file-name-directory file)) 189 (setq default-directory (vc-mcvs-root file))
189 (vc-mcvs-command t 0 file "status") 190 (vc-mcvs-command t 0 file "status")
190 (vc-cvs-parse-status t)))) 191 (vc-cvs-parse-status t))))
191 192
192 193
193 (defalias 'vc-mcvs-state-heuristic 'vc-cvs-state-heuristic) 194 (defalias 'vc-mcvs-state-heuristic 'vc-cvs-state-heuristic)
200 (vc-mcvs-dir-state-heuristic dir) 201 (vc-mcvs-dir-state-heuristic dir)
201 (let ((default-directory dir)) 202 (let ((default-directory dir))
202 ;; Don't specify DIR in this command, the default-directory is 203 ;; Don't specify DIR in this command, the default-directory is
203 ;; enough. Otherwise it might fail with remote repositories. 204 ;; enough. Otherwise it might fail with remote repositories.
204 (with-temp-buffer 205 (with-temp-buffer
206 (setq default-directory (vc-mcvs-root dir))
205 (vc-mcvs-command t 0 nil "status" "-l") 207 (vc-mcvs-command t 0 nil "status" "-l")
206 (goto-char (point-min)) 208 (goto-char (point-min))
207 (while (re-search-forward "^=+\n\\([^=\n].*\n\\|\n\\)+" nil t) 209 (while (re-search-forward "^=+\n\\([^=\n].*\n\\|\n\\)+" nil t)
208 (narrow-to-region (match-beginning 0) (match-end 0)) 210 (narrow-to-region (match-beginning 0) (match-end 0))
209 (vc-cvs-parse-status) 211 (vc-cvs-parse-status)
214 216
215 (defalias 'vc-mcvs-checkout-model 'vc-cvs-checkout-model) 217 (defalias 'vc-mcvs-checkout-model 'vc-cvs-checkout-model)
216 218
217 (defun vc-mcvs-mode-line-string (file) 219 (defun vc-mcvs-mode-line-string (file)
218 (let ((s (vc-mcvs-cvs mode-line-string file))) 220 (let ((s (vc-mcvs-cvs mode-line-string file)))
219 (if s (concat "M" s)))) 221 (when s
222 (if (and (not (memq (vc-state file) '(up-to-date needs-patch)))
223 (string-match "\\`CVS-" s))
224 ;; The CVS file is not in sync, so we need to adjust the state.
225 (concat "MCVS:" (substring s 4))
226 (concat "M" s)))))
220 227
221 ;;; 228 ;;;
222 ;;; State-changing functions 229 ;;; State-changing functions
223 ;;; 230 ;;;
224 231
282 (unless (or (not rev) (vc-mcvs-valid-version-number-p rev)) 289 (unless (or (not rev) (vc-mcvs-valid-version-number-p rev))
283 (if (not (vc-mcvs-valid-symbolic-tag-name-p rev)) 290 (if (not (vc-mcvs-valid-symbolic-tag-name-p rev))
284 (error "%s is not a valid symbolic tag name" rev) 291 (error "%s is not a valid symbolic tag name" rev)
285 ;; If the input revision is a valid symbolic tag name, we create it 292 ;; If the input revision is a valid symbolic tag name, we create it
286 ;; as a branch, commit and switch to it. 293 ;; as a branch, commit and switch to it.
294 ;; This file-specific form of branching is deprecated.
295 ;; We can't use `mcvs branch' and `mcvs switch' because they cannot
296 ;; be applied just to this one file.
287 (apply 'vc-mcvs-command nil 0 file "tag" "-b" (list rev)) 297 (apply 'vc-mcvs-command nil 0 file "tag" "-b" (list rev))
288 (apply 'vc-mcvs-command nil 0 file "update" "-r" (list rev)) 298 (apply 'vc-mcvs-command nil 0 file "update" "-r" (list rev))
289 (vc-file-setprop file 'vc-mcvs-sticky-tag rev) 299 (vc-file-setprop file 'vc-mcvs-sticky-tag rev)
290 (setq rev nil))) 300 (setq rev nil)))
291 ;; This commit might cvs-commit several files (e.g. MAP and TYPES) 301 ;; This commit might cvs-commit several files (e.g. MAP and TYPES)
438 ;;; History functions 448 ;;; History functions
439 ;;; 449 ;;;
440 450
441 (defun vc-mcvs-print-log (file) 451 (defun vc-mcvs-print-log (file)
442 "Get change log associated with FILE." 452 "Get change log associated with FILE."
443 (vc-mcvs-command 453 (let ((default-directory (vc-mcvs-root file)))
444 nil 454 ;; Run the command from the root dir so that `mcvs filt' returns
445 (if (and (vc-stay-local-p file) (fboundp 'start-process)) 'async 0) 455 ;; valid relative names.
446 file "log")) 456 (vc-mcvs-command
457 nil
458 (if (and (vc-stay-local-p file) (fboundp 'start-process)) 'async 0)
459 file "log")))
447 460
448 (defun vc-mcvs-diff (file &optional oldvers newvers) 461 (defun vc-mcvs-diff (file &optional oldvers newvers)
449 "Get a difference report using Meta-CVS between two versions of FILE." 462 "Get a difference report using Meta-CVS between two versions of FILE."
450 (if (string= (vc-workfile-version file) "0") 463 (if (string= (vc-workfile-version file) "0")
451 ;; This file is added but not yet committed; there is no master file. 464 ;; This file is added but not yet committed; there is no master file.
458 1 "diff" file 471 1 "diff" file
459 (append (vc-switches nil 'diff) '("/dev/null"))) 472 (append (vc-switches nil 'diff) '("/dev/null")))
460 ;; Even if it's empty, it's locally modified. 473 ;; Even if it's empty, it's locally modified.
461 1) 474 1)
462 (let* ((async (and (vc-stay-local-p file) (fboundp 'start-process))) 475 (let* ((async (and (vc-stay-local-p file) (fboundp 'start-process)))
476 ;; Run the command from the root dir so that `mcvs filt' returns
477 ;; valid relative names.
478 (default-directory (vc-mcvs-root file))
463 (status 479 (status
464 (apply 'vc-mcvs-command "*vc-diff*" 480 (apply 'vc-mcvs-command "*vc-diff*"
465 (if async 'async 1) 481 (if async 'async 1)
466 file "diff" 482 file "diff"
467 (and oldvers (concat "-r" oldvers)) 483 (and oldvers (concat "-r" oldvers))
470 (if async 1 status)))) ; async diff, pessimistic assumption. 486 (if async 1 status)))) ; async diff, pessimistic assumption.
471 487
472 (defun vc-mcvs-diff-tree (dir &optional rev1 rev2) 488 (defun vc-mcvs-diff-tree (dir &optional rev1 rev2)
473 "Diff all files at and below DIR." 489 "Diff all files at and below DIR."
474 (with-current-buffer "*vc-diff*" 490 (with-current-buffer "*vc-diff*"
475 (setq default-directory dir) 491 ;; Run the command from the root dir so that `mcvs filt' returns
476 (if (vc-stay-local-p dir) 492 ;; valid relative names.
477 ;; local diff: do it filewise, and only for files that are modified 493 (setq default-directory (vc-mcvs-root dir))
478 (vc-file-tree-walk 494 ;; cvs diff: use a single call for the entire tree
479 dir 495 (let ((coding-system-for-read (or coding-system-for-read 'undecided)))
480 (lambda (f) 496 (apply 'vc-mcvs-command "*vc-diff*" 1 dir "diff"
481 (vc-exec-after 497 (and rev1 (concat "-r" rev1))
482 `(let ((coding-system-for-read (vc-coding-system-for-diff ',f))) 498 (and rev2 (concat "-r" rev2))
483 ;; possible optimization: fetch the state of all files 499 (vc-switches 'MCVS 'diff)))))
484 ;; in the tree via vc-mcvs-dir-state-heuristic
485 (unless (vc-up-to-date-p ',f)
486 (message "Looking at %s" ',f)
487 (vc-diff-internal ',f ',rev1 ',rev2))))))
488 ;; cvs diff: use a single call for the entire tree
489 (let ((coding-system-for-read
490 (or coding-system-for-read 'undecided)))
491 (apply 'vc-mcvs-command "*vc-diff*" 1 nil "diff"
492 (and rev1 (concat "-r" rev1))
493 (and rev2 (concat "-r" rev2))
494 (vc-switches 'MCVS 'diff))))))
495 500
496 (defun vc-mcvs-annotate-command (file buffer &optional version) 501 (defun vc-mcvs-annotate-command (file buffer &optional version)
497 "Execute \"mcvs annotate\" on FILE, inserting the contents in BUFFER. 502 "Execute \"mcvs annotate\" on FILE, inserting the contents in BUFFER.
498 Optional arg VERSION is a version to annotate from." 503 Optional arg VERSION is a version to annotate from."
499 (vc-mcvs-command 504 (vc-mcvs-command
510 515
511 (defun vc-mcvs-create-snapshot (dir name branchp) 516 (defun vc-mcvs-create-snapshot (dir name branchp)
512 "Assign to DIR's current version a given NAME. 517 "Assign to DIR's current version a given NAME.
513 If BRANCHP is non-nil, the name is created as a branch (and the current 518 If BRANCHP is non-nil, the name is created as a branch (and the current
514 workspace is immediately moved to that new branch)." 519 workspace is immediately moved to that new branch)."
515 (vc-mcvs-command nil 0 dir "tag" "-c" (if branchp "-b") name) 520 (if (not branchp)
516 (when branchp (vc-mcvs-command nil 0 dir "update" "-r" name))) 521 (vc-mcvs-command nil 0 dir "tag" "-c" name)
522 (vc-mcvs-command nil 0 dir "branch" name)
523 (vc-mcvs-command nil 0 dir "switch" name)))
517 524
518 (defun vc-mcvs-retrieve-snapshot (dir name update) 525 (defun vc-mcvs-retrieve-snapshot (dir name update)
519 "Retrieve a snapshot at and below DIR. 526 "Retrieve a snapshot at and below DIR.
520 NAME is the name of the snapshot; if it is empty, do a `cvs update'. 527 NAME is the name of the snapshot; if it is empty, do a `cvs update'.
521 If UPDATE is non-nil, then update (resynch) any affected buffers." 528 If UPDATE is non-nil, then update (resynch) any affected buffers."
567 574
568 (defun vc-mcvs-command (buffer okstatus file &rest flags) 575 (defun vc-mcvs-command (buffer okstatus file &rest flags)
569 "A wrapper around `vc-do-command' for use in vc-mcvs.el. 576 "A wrapper around `vc-do-command' for use in vc-mcvs.el.
570 The difference to vc-do-command is that this function always invokes `mcvs', 577 The difference to vc-do-command is that this function always invokes `mcvs',
571 and that it passes `vc-mcvs-global-switches' to it before FLAGS." 578 and that it passes `vc-mcvs-global-switches' to it before FLAGS."
572 (let ((args (append '("--error-continue") 579 (let ((args (append '("--error-terminate")
573 (if (stringp vc-mcvs-global-switches) 580 (if (stringp vc-mcvs-global-switches)
574 (cons vc-mcvs-global-switches flags) 581 (cons vc-mcvs-global-switches flags)
575 (append vc-mcvs-global-switches 582 (append vc-mcvs-global-switches flags)))))
576 flags))))) 583 (if (not (member (car flags) '("diff" "log" "status")))
577 (if (member (car flags) '("diff" "log")) 584 ;; No need to filter: do it the easy way.
578 ;; We need to filter the output. 585 (apply 'vc-do-command buffer okstatus "mcvs" file args)
579 (vc-do-command buffer okstatus "sh" nil "-c" 586 ;; We need to filter the output.
580 (concat "mcvs " 587 ;; The output of the filter uses filenames relative to the root,
581 (mapconcat 588 ;; so we need to change the default-directory.
582 'shell-quote-argument 589 (assert (equal default-directory (vc-mcvs-root file)))
583 (append (remq nil args) 590 (vc-do-command
584 (if file (list (file-relative-name file)))) 591 buffer okstatus "sh" nil "-c"
585 " ") 592 (concat "mcvs "
586 " | mcvs filt")) 593 (mapconcat
587 (apply 'vc-do-command buffer okstatus "mcvs" file args)))) 594 'shell-quote-argument
595 (append (remq nil args)
596 (if file (list (file-relative-name file))))
597 " ")
598 " | mcvs filt")))))
588 599
589 (defun vc-mcvs-repository-hostname (dirname) 600 (defun vc-mcvs-repository-hostname (dirname)
590 (vc-cvs-repository-hostname (vc-mcvs-root dirname))) 601 (vc-cvs-repository-hostname (vc-mcvs-root dirname)))
591 602
592 (defun vc-mcvs-dir-state-heuristic (dir) 603 (defun vc-mcvs-dir-state-heuristic (dir)