;; make sure that the file name is searched case-sensitively
(case-fold-search nil))
(if (file-readable-p (expand-file-name "CVS/Entries" dirname))
- (with-temp-buffer
- (vc-cvs-get-entries dirname)
- (goto-char (point-min))
- (cond
- ((re-search-forward
- (concat "^/" (regexp-quote basename) "/[^/]") nil t)
- (beginning-of-line)
- (vc-cvs-parse-entry file)
- t)
- (t nil)))
+ (or (string= basename "")
+ (with-temp-buffer
+ (vc-cvs-get-entries dirname)
+ (goto-char (point-min))
+ (cond ((re-search-forward
+ (concat "^/" (regexp-quote basename) "/[^/]") nil t)
+ (beginning-of-line)
+ (vc-cvs-parse-entry file)
+ t)
+ (t nil))))
nil)))
(defun vc-cvs-state (file)
(cond
((equal checkout-time lastmod) 'up-to-date)
((string= (vc-working-revision file) "0") 'added)
+ ((null checkout-time) 'unregistered)
(t 'edited))))
(defun vc-cvs-working-revision (file)
help-echo
(string
(let ((def-ml (vc-default-mode-line-string 'CVS file)))
- (setq help-echo
+ (setq help-echo
(get-text-property 0 'help-echo def-ml))
def-ml)))
- (propertize
+ (propertize
(if (zerop (length sticky-tag))
string
- (setq help-echo (format "%s on the '%s' branch"
+ (setq help-echo (format "%s on the '%s' branch"
help-echo sticky-tag))
(concat string "[" sticky-tag "]"))
'help-echo help-echo)))
(with-current-buffer (get-buffer "*vc*")
(goto-char (point-min))
(if (re-search-forward "conflicts during merge" nil t)
- (progn
+ (progn
(vc-file-setprop file 'vc-state 'conflict)
;; signal error
1)
(message "Merging changes into %s...done" file))))
(defun vc-cvs-modify-change-comment (files rev comment)
- "Modify the change comments for FILES on a specified REV.
+ "Modify the change comments for FILES on a specified REV.
Will fail unless you have administrative privileges on the repo."
(vc-cvs-command nil 0 files "admin" (concat "-m" rev ":" comment)))
(re-search-forward vc-cvs-annotate-first-line-re)
(delete-region (point-min) (1- (point)))))))
+(declare-function vc-annotate-convert-time "vc-annotate" (time))
+
(defun vc-cvs-annotate-current-time ()
"Return the current time, based at midnight of the current day, and
encoded as fractional days."
nil)))
;;;
-;;; Snapshot system
+;;; Tag system
;;;
-(defun vc-cvs-create-snapshot (dir name branchp)
+(defun vc-cvs-create-tag (dir name branchp)
"Assign to DIR's current revision a given NAME.
If BRANCHP is non-nil, the name is created as a branch (and the current
workspace is immediately moved to that new branch)."
(vc-cvs-command nil 0 dir "tag" "-c" (if branchp "-b") name)
(when branchp (vc-cvs-command nil 0 dir "update" "-r" name)))
-(defun vc-cvs-retrieve-snapshot (dir name update)
- "Retrieve a snapshot at and below DIR.
-NAME is the name of the snapshot; if it is empty, do a `cvs update'.
+(defun vc-cvs-retrieve-tag (dir name update)
+ "Retrieve a tag at and below DIR.
+NAME is the name of the tag; if it is empty, do a `cvs update'.
If UPDATE is non-nil, then update (resynch) any affected buffers."
(with-current-buffer (get-buffer-create "*vc*")
(let ((default-directory dir)
;;; Internal functions
;;;
-(defun vc-cvs-root (dir)
- (vc-find-root dir "CVS" t))
-
(defun vc-cvs-command (buffer okstatus files &rest flags)
"A wrapper around `vc-do-command' for use in vc-cvs.el.
The difference to vc-do-command is that this function always invokes `cvs',
(cond
((re-search-forward "\\=\\([^ \t]+\\)" nil t)
(setq file (expand-file-name (match-string 1)))
- (vc-file-setprop file 'vc-backend 'CVS)
- (if (not (re-search-forward "\\=[ \t]+Status: \\(.*\\)" nil t))
- (setq status "Unknown")
- (setq status (match-string 1)))
+ (setq status(if (re-search-forward "\\=[ \t]+Status: \\(.*\\)" nil t)
+ (match-string 1) "Unknown"))
(when (and full
(re-search-forward
"\\(RCS Version\\|RCS Revision\\|Repository revision\\):\
((string-match "Locally Added" status) 'added)
((string-match "Locally Removed" status) 'removed)
((string-match "File had conflicts " status) 'conflict)
+ ((string-match "Unknown" status) 'unregistered)
(t 'edited))))))))
(defun vc-cvs-after-dir-status (update-function)
(re-search-forward
"\\(^=+\n\\([^=c?\n].*\n\\|\n\\)+\\)\\|\\(\\(^?? .*\n\\)+\\)\\|\\(^cvs status: Examining .*\n\\)"
nil t)
- ;; XXX: get rid of narrowing here.
+ ;; FIXME: get rid of narrowing here.
(narrow-to-region (match-beginning 0) (match-end 0))
(goto-char (point-min))
;; The subdir
(setq subdir (expand-file-name (match-string 1))))
;; Unregistered files
(while (looking-at "? \\(.*\\)")
- (setq file (file-relative-name
+ (setq file (file-relative-name
(expand-file-name (match-string 1) subdir)))
(push (list file 'unregistered) result)
(forward-line 1))
;; A file entry.
- (when (re-search-forward "^File: " nil t)
- (when (setq missing (looking-at "no file "))
- (goto-char (match-end 0)))
- (cond
- ((re-search-forward "\\=\\([^ \t]+\\)" nil t)
- (setq file (file-relative-name
- (expand-file-name (match-string 1) subdir)))
- (if (not (re-search-forward "\\=[ \t]+Status: \\(.*\\)" nil t))
- (push (list file 'unregistered) result)
- (setq status-str (match-string 1))
- (setq status
- (cond
- ((string-match "Up-to-date" status-str) 'up-to-date)
- ((string-match "Locally Modified" status-str) 'edited)
- ((string-match "Needs Merge" status-str) 'needs-merge)
- ((string-match "Needs \\(Checkout\\|Patch\\)" status-str)
- (if missing 'missing 'needs-update))
- ((string-match "Locally Added" status-str) 'added)
- ((string-match "Locally Removed" status-str) 'removed)
- ((string-match "File had conflicts " status-str) 'conflict)
- (t 'edited)))
- (unless (eq status 'up-to-date)
- (push (list file status) result))))))
+ (when (re-search-forward "^File: \\(no file \\)?\\(.*[^ \t]\\)[ \t]+Status: \\(.*\\)" nil t)
+ (setq missing (match-string 1))
+ (setq file (file-relative-name
+ (expand-file-name (match-string 2) subdir)))
+ (setq status-str (match-string 3))
+ (setq status
+ (cond
+ ((string-match "Up-to-date" status-str) 'up-to-date)
+ ((string-match "Locally Modified" status-str) 'edited)
+ ((string-match "Needs Merge" status-str) 'needs-merge)
+ ((string-match "Needs \\(Checkout\\|Patch\\)" status-str)
+ (if missing 'missing 'needs-update))
+ ((string-match "Locally Added" status-str) 'added)
+ ((string-match "Locally Removed" status-str) 'removed)
+ ((string-match "File had conflicts " status-str) 'conflict)
+ ((string-match "Unknown" status-str) 'unregistered)
+ (t 'edited)))
+ (unless (eq status 'up-to-date)
+ (push (list file status) result)))
(goto-char (point-max))
(widen))
- (funcall update-function result))
+ (funcall update-function result))
;; Alternative implementation: use the "update" command instead of
;; the "status" command.
;; (let ((result nil)
;; (goto-char (point-min))
;; (while (not (eobp))
;; (if (looking-at "^[ACMPRU?] \\(.*\\)$")
- ;; (push (list (match-string 1)
- ;; (cdr (assoc (char-after) translation)))
+ ;; (push (list (match-string 1)
+ ;; (cdr (assoc (char-after) translation)))
;; result)
;; (cond
;; ((looking-at "cvs update: warning: \\(.*\\) was lost")
(defun vc-cvs-dir-status (dir update-function)
"Create a list of conses (file . state) for DIR."
- (vc-cvs-command (current-buffer) 'async dir "status")
+ (vc-cvs-command (current-buffer) 'async dir "-f" "status")
;; Alternative implementation: use the "update" command instead of
;; the "status" command.
;; (vc-cvs-command (current-buffer) 'async
(vc-exec-after
`(vc-cvs-after-dir-status (quote ,update-function))))
+(defun vc-cvs-dir-status-files (dir files default-state update-function)
+ "Create a list of conses (file . state) for DIR."
+ (apply 'vc-cvs-command (current-buffer) 'async dir "-f" "status" files)
+ (vc-exec-after
+ `(vc-cvs-after-dir-status (quote ,update-function))))
+
+(defun vc-cvs-file-to-string (file)
+ "Read the content of FILE and return it as a string."
+ (condition-case nil
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (buffer-substring (point) (point-max)))
+ (file-error nil)))
+
(defun vc-cvs-status-extra-headers (dir)
- (concat
- ;; FIXME: see how PCL-CVS gets the data to print all these
- (propertize "Module : " 'face 'font-lock-type-face)
- (propertize "ADD CODE TO PRINT THE MODULE\n"
- 'face 'font-lock-warning-face)
- (propertize "Repository : " 'face 'font-lock-type-face)
- (propertize "ADD CODE TO PRINT THE REPOSITORY\n"
- 'face 'font-lock-warning-face)
- (propertize "Branch : " 'face 'font-lock-type-face)
- (propertize "ADD CODE TO PRINT THE BRANCH NAME\n"
- 'face 'font-lock-warning-face)))
+ "Extract and represent per-directory properties of a CVS working copy."
+ (let ((repo
+ (condition-case nil
+ (with-temp-buffer
+ (insert-file-contents "CVS/Root")
+ (goto-char (point-min))
+ (and (looking-at ":ext:") (delete-char 5))
+ (buffer-substring (point) (1- (point-max))))
+ (file-error nil)))
+ (module
+ (condition-case nil
+ (with-temp-buffer
+ (insert-file-contents "CVS/Repository")
+ (goto-char (point-min))
+ (re-search-forward "[^/\n]*" nil t)
+ (concat (match-string 0) "\n"))
+ (file-error nil))))
+ (concat
+ (cond (module
+ (concat (propertize "Module : " 'face 'font-lock-type-face)
+ (propertize module 'face 'font-lock-variable-name-face)))
+ (t ""))
+ (cond (repo
+ (concat (propertize "Repository : " 'face 'font-lock-type-face)
+ (propertize repo 'face 'font-lock-variable-name-face)))
+ (t ""))
+ ;; In CVS, branch is a per-file property, not a per-directory property.
+ ;; We can't really do this here without making dangerous assumptions.
+ ;;(propertize "Branch: " 'face 'font-lock-type-face)
+ ;;(propertize "ADD CODE TO PRINT THE BRANCH NAME\n"
+ ;; 'face 'font-lock-warning-face)
+ )))
(defun vc-cvs-get-entries (dir)
"Insert the CVS/Entries file from below DIR into the current buffer.
(cond
;; entry for a "locally added" file (not yet committed)
((looking-at "/[^/]+/0/")
- (vc-file-setprop file 'vc-backend 'CVS)
(vc-file-setprop file 'vc-checkout-time 0)
(vc-file-setprop file 'vc-working-revision "0")
(if set-state (vc-file-setprop file 'vc-state 'added)))
;; sticky tag
"\\(.\\|\\)" ;Sticky tag type (date or tag name, could be empty)
"\\(.*\\)")) ;Sticky tag
- (vc-file-setprop file 'vc-backend 'CVS)
(vc-file-setprop file 'vc-working-revision (match-string 1))
(vc-file-setprop file 'vc-cvs-sticky-tag
(vc-cvs-parse-sticky-tag (match-string 4)
(setq table (lazy-completion-table
table (lambda () (vc-cvs-revision-table (car files)))))
table))
-
+
(provide 'vc-cvs)