1 |
;;; vc-cvs.el --- non-resident support for CVS version-control |
;;; vc-cvs.el --- non-resident support for CVS version-control |
2 |
|
|
3 |
;; Copyright (C) 1995,98,99,2000,2001 Free Software Foundation, Inc. |
;; Copyright (C) 1995,98,99,2000,2001,2002 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Author: FSF (see vc.el for full credits) |
;; Author: FSF (see vc.el for full credits) |
6 |
;; Maintainer: Andre Spiegel <spiegel@gnu.org> |
;; Maintainer: Andre Spiegel <spiegel@gnu.org> |
120 |
((eq type 'symbolic-name) \"Sticky\"))) |
((eq type 'symbolic-name) \"Sticky\"))) |
121 |
|
|
122 |
Here's an example that will abbreviate to the first character only, |
Here's an example that will abbreviate to the first character only, |
123 |
any text before the first occurence of `-' for sticky symbolic tags. |
any text before the first occurrence of `-' for sticky symbolic tags. |
124 |
If the sticky tag is a revision number, the word \"Sticky\" is |
If the sticky tag is a revision number, the word \"Sticky\" is |
125 |
displayed. Date and time is displayed for sticky dates. |
displayed. Date and time is displayed for sticky dates. |
126 |
|
|
158 |
;;;###autoload (defun vc-cvs-registered (f) |
;;;###autoload (defun vc-cvs-registered (f) |
159 |
;;;###autoload (when (file-readable-p (expand-file-name |
;;;###autoload (when (file-readable-p (expand-file-name |
160 |
;;;###autoload "CVS/Entries" (file-name-directory f))) |
;;;###autoload "CVS/Entries" (file-name-directory f))) |
161 |
;;;###autoload (require 'vc-cvs) |
;;;###autoload (load "vc-cvs") |
162 |
;;;###autoload (vc-cvs-registered f))) |
;;;###autoload (vc-cvs-registered f))) |
163 |
|
|
164 |
(defun vc-cvs-registered (file) |
(defun vc-cvs-registered (file) |
207 |
|
|
208 |
(defun vc-cvs-dir-state (dir) |
(defun vc-cvs-dir-state (dir) |
209 |
"Find the CVS state of all files in DIR." |
"Find the CVS state of all files in DIR." |
210 |
(if (vc-cvs-stay-local-p dir) |
;; if DIR is not under CVS control, don't do anything |
211 |
(vc-cvs-dir-state-heuristic dir) |
(if (file-readable-p (expand-file-name "CVS/Entries" dir)) |
212 |
(let ((default-directory dir)) |
(if (vc-cvs-stay-local-p dir) |
213 |
;; Don't specify DIR in this command, the default-directory is |
(vc-cvs-dir-state-heuristic dir) |
214 |
;; enough. Otherwise it might fail with remote repositories. |
(let ((default-directory dir)) |
215 |
(with-temp-buffer |
;; Don't specify DIR in this command, the default-directory is |
216 |
(vc-cvs-command t 0 nil "status" "-l") |
;; enough. Otherwise it might fail with remote repositories. |
217 |
(goto-char (point-min)) |
(with-temp-buffer |
218 |
(while (re-search-forward "^=+\n\\([^=\n].*\n\\|\n\\)+" nil t) |
(vc-do-command t 0 "cvs" nil "status" "-l") |
219 |
(narrow-to-region (match-beginning 0) (match-end 0)) |
(goto-char (point-min)) |
220 |
(vc-cvs-parse-status) |
(while (re-search-forward "^=+\n\\([^=\n].*\n\\|\n\\)+" nil t) |
221 |
(goto-char (point-max)) |
(narrow-to-region (match-beginning 0) (match-end 0)) |
222 |
(widen)))))) |
(vc-cvs-parse-status) |
223 |
|
(goto-char (point-max)) |
224 |
|
(widen))))))) |
225 |
|
|
226 |
(defun vc-cvs-workfile-version (file) |
(defun vc-cvs-workfile-version (file) |
227 |
"CVS-specific version of `vc-workfile-version'." |
"CVS-specific version of `vc-workfile-version'." |
370 |
(if (and rev (not (vc-cvs-valid-symbolic-tag-name-p rev))) |
(if (and rev (not (vc-cvs-valid-symbolic-tag-name-p rev))) |
371 |
(vc-cvs-command nil 0 file "update" "-A")))) |
(vc-cvs-command nil 0 file "update" "-A")))) |
372 |
|
|
373 |
|
(defun vc-cvs-find-version (file rev buffer) |
374 |
|
(apply 'vc-cvs-command |
375 |
|
buffer 0 file |
376 |
|
"-Q" ; suppress diagnostic output |
377 |
|
"update" |
378 |
|
(and rev (not (string= rev "")) |
379 |
|
(concat "-r" rev)) |
380 |
|
"-p" |
381 |
|
(if (stringp vc-checkout-switches) |
382 |
|
(list vc-checkout-switches) |
383 |
|
vc-checkout-switches))) |
384 |
|
|
385 |
(defun vc-cvs-checkout (file &optional editable rev workfile) |
(defun vc-cvs-checkout (file &optional editable rev workfile) |
386 |
"Retrieve a revision of FILE into a WORKFILE. |
"Retrieve a revision of FILE into a WORKFILE. |
387 |
EDITABLE non-nil means that the file should be writable. |
EDITABLE non-nil means that the file should be writable. |
423 |
(current-buffer) 0 file |
(current-buffer) 0 file |
424 |
"-Q" ; suppress diagnostic output |
"-Q" ; suppress diagnostic output |
425 |
"update" |
"update" |
426 |
(and rev (not (string= rev "")) |
(and (stringp rev) |
427 |
|
(not (string= rev "")) |
428 |
(concat "-r" rev)) |
(concat "-r" rev)) |
429 |
"-p" |
"-p" |
430 |
switches))) |
switches))) |
441 |
(if (and (file-exists-p file) (not rev)) |
(if (and (file-exists-p file) (not rev)) |
442 |
;; If no revision was specified, just make the file writable |
;; If no revision was specified, just make the file writable |
443 |
;; if necessary (using `cvs-edit' if requested). |
;; if necessary (using `cvs-edit' if requested). |
444 |
(and editable (not (eq (vc-cvs-checkout-model file) 'implicit)) |
(and editable (not (eq (vc-cvs-checkout-model file) 'implicit)) |
445 |
(if vc-cvs-use-edit |
(if vc-cvs-use-edit |
446 |
(vc-cvs-command nil 0 file "edit") |
(vc-cvs-command nil 0 file "edit") |
447 |
(set-file-modes file (logior (file-modes file) 128)) |
(set-file-modes file (logior (file-modes file) 128)) |
448 |
(if file-buffer (toggle-read-only -1)))) |
(if file-buffer (toggle-read-only -1)))) |
449 |
;; Check out a particular version (or recreate the file). |
;; Check out a particular version (or recreate the file). |
450 |
(vc-file-setprop file 'vc-workfile-version nil) |
(vc-file-setprop file 'vc-workfile-version nil) |
451 |
(apply 'vc-cvs-command nil 0 file |
(apply 'vc-cvs-command nil 0 file |
452 |
(and editable |
(and editable |
453 |
(or (not (file-exists-p file)) |
(or (not (file-exists-p file)) |
454 |
(not (eq (vc-cvs-checkout-model file) |
(not (eq (vc-cvs-checkout-model file) |
457 |
"update" |
"update" |
458 |
;; default for verbose checkout: clear the sticky tag so |
;; default for verbose checkout: clear the sticky tag so |
459 |
;; that the actual update will get the head of the trunk |
;; that the actual update will get the head of the trunk |
460 |
(if (or (not rev) (string= rev "")) |
(if (or (not rev) (eq rev t) (string= rev "")) |
461 |
"-A" |
"-A" |
462 |
(concat "-r" rev)) |
(concat "-r" rev)) |
463 |
switches)))) |
switches)))) |
464 |
(vc-mode-line file) |
(vc-mode-line file) |
465 |
(message "Checking out %s...done" filename))))) |
(message "Checking out %s...done" filename))))) |
466 |
|
|
552 |
(if (and (vc-cvs-stay-local-p file) (fboundp 'start-process)) 'async 0) |
(if (and (vc-cvs-stay-local-p file) (fboundp 'start-process)) 'async 0) |
553 |
file "log")) |
file "log")) |
554 |
|
|
|
(defun vc-cvs-show-log-entry (version) |
|
|
(when (re-search-forward |
|
|
;; also match some context, for safety |
|
|
(concat "----\nrevision " version |
|
|
"\\(\tlocked by:.*\n\\|\n\\)date: ") nil t) |
|
|
;; set the display window so that |
|
|
;; the whole log entry is displayed |
|
|
(let (start end lines) |
|
|
(beginning-of-line) (forward-line -1) (setq start (point)) |
|
|
(if (not (re-search-forward "^----*\nrevision" nil t)) |
|
|
(setq end (point-max)) |
|
|
(beginning-of-line) (forward-line -1) (setq end (point))) |
|
|
(setq lines (count-lines start end)) |
|
|
(cond |
|
|
;; if the global information and this log entry fit |
|
|
;; into the window, display from the beginning |
|
|
((< (count-lines (point-min) end) (window-height)) |
|
|
(goto-char (point-min)) |
|
|
(recenter 0) |
|
|
(goto-char start)) |
|
|
;; if the whole entry fits into the window, |
|
|
;; display it centered |
|
|
((< (1+ lines) (window-height)) |
|
|
(goto-char start) |
|
|
(recenter (1- (- (/ (window-height) 2) (/ lines 2))))) |
|
|
;; otherwise (the entry is too large for the window), |
|
|
;; display from the start |
|
|
(t |
|
|
(goto-char start) |
|
|
(recenter 0)))))) |
|
|
|
|
555 |
(defun vc-cvs-diff (file &optional oldvers newvers) |
(defun vc-cvs-diff (file &optional oldvers newvers) |
556 |
"Get a difference report using CVS between two versions of FILE." |
"Get a difference report using CVS between two versions of FILE." |
557 |
(let (options status (diff-switches-list (vc-diff-switches-list 'CVS))) |
(let (options status (diff-switches-list (vc-diff-switches-list 'CVS))) |
819 |
(unwind-protect |
(unwind-protect |
820 |
(progn |
(progn |
821 |
(cond |
(cond |
822 |
;; Sticky Date tag. Convert to to a proper date value (`encode-time') |
;; Sticky Date tag. Convert to a proper date value (`encode-time') |
823 |
((eq type 'date) |
((eq type 'date) |
824 |
(string-match |
(string-match |
825 |
"\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)" |
"\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)" |
872 |
(concat "/[^/]+" |
(concat "/[^/]+" |
873 |
;; revision |
;; revision |
874 |
"/\\([^/]*\\)" |
"/\\([^/]*\\)" |
875 |
;; timestamp |
;; timestamp and optional conflict field |
876 |
"/\\([^/]*\\)" |
"/\\([^/]*\\)/" |
|
;; optional conflict field |
|
|
"\\(+[^/]*\\)?/" |
|
877 |
;; options |
;; options |
878 |
"\\([^/]*\\)/" |
"\\([^/]*\\)/" |
879 |
;; sticky tag |
;; sticky tag |
881 |
"\\(.*\\)")) ;Sticky tag |
"\\(.*\\)")) ;Sticky tag |
882 |
(vc-file-setprop file 'vc-workfile-version (match-string 1)) |
(vc-file-setprop file 'vc-workfile-version (match-string 1)) |
883 |
(vc-file-setprop file 'vc-cvs-sticky-tag |
(vc-file-setprop file 'vc-cvs-sticky-tag |
884 |
(vc-cvs-parse-sticky-tag (match-string 5) (match-string 6))) |
(vc-cvs-parse-sticky-tag (match-string 4) (match-string 5))) |
885 |
;; compare checkout time and modification time |
;; compare checkout time and modification time |
886 |
(let ((mtime (nth 5 (file-attributes file))) |
(let ((mtime (nth 5 (file-attributes file)))) |
887 |
(system-time-locale "C")) |
(require 'parse-time) |
888 |
(cond ((equal (format-time-string "%c" mtime 'utc) (match-string 2)) |
(let ((parsed-time |
889 |
(vc-file-setprop file 'vc-checkout-time mtime) |
(parse-time-string (concat (match-string 2) " +0000")))) |
890 |
(if set-state (vc-file-setprop file 'vc-state 'up-to-date))) |
(cond ((and (not (string-match "\\+" (match-string 2))) |
891 |
(t |
(car parsed-time) |
892 |
(vc-file-setprop file 'vc-checkout-time 0) |
(equal mtime (apply 'encode-time parsed-time))) |
893 |
(if set-state (vc-file-setprop file 'vc-state 'edited)))))))) |
(vc-file-setprop file 'vc-checkout-time mtime) |
894 |
|
(if set-state (vc-file-setprop file 'vc-state 'up-to-date))) |
895 |
|
(t |
896 |
|
(vc-file-setprop file 'vc-checkout-time 0) |
897 |
|
(if set-state (vc-file-setprop file 'vc-state 'edited))))))))) |
898 |
|
|
899 |
(provide 'vc-cvs) |
(provide 'vc-cvs) |
900 |
|
|