comparison lisp/vc.el @ 11605:36b1eb58d0c9

(vc-next-action-on-file): Add missing let-binding. (vc-default-backend, vc-keep-workfiles, vc-consult-headers): (vc-mistrust-permissions, vc-path): Vars moved to vc-hooks.el. (vc-match-substring, vc-lock-file, vc-parse-buffer, vc-master-info): (vc-log-info, vc-consult-rcs-headers, vc-fetch-properties): (vc-backend-subdirectory-name, vc-locking-user, vc-true-locking-user): (vc-latest-version, vc-your-latest-version, vc-branch-version): (vc-workfile-version): Functions moved to vc-hooks.el. (vc-trunk-p, vc-minor-revision, vc-branch-part): Functions moved here from vc-hooks.el.
author Karl Heuer <kwzh@gnu.org>
date Wed, 26 Apr 1995 21:47:35 +0000
parents d6d53a54da18
children 41178eac8f3d
comparison
equal deleted inserted replaced
11604:401afae906eb 11605:36b1eb58d0c9
75 (cons '(vc-parent-buffer vc-parent-buffer-name) 75 (cons '(vc-parent-buffer vc-parent-buffer-name)
76 minor-mode-alist))) 76 minor-mode-alist)))
77 77
78 ;; General customization 78 ;; General customization
79 79
80 (defvar vc-default-back-end nil
81 "*Back-end actually used by this interface; may be SCCS or RCS.
82 The value is only computed when needed to avoid an expensive search.")
83 (defvar vc-suppress-confirm nil 80 (defvar vc-suppress-confirm nil
84 "*If non-nil, treat user as expert; suppress yes-no prompts on some things.") 81 "*If non-nil, treat user as expert; suppress yes-no prompts on some things.")
85 (defvar vc-keep-workfiles t
86 "*If non-nil, don't delete working files after registering changes.
87 If the back-end is CVS, workfiles are always kept, regardless of the
88 value of this flag.")
89 (defvar vc-initial-comment nil 82 (defvar vc-initial-comment nil
90 "*Prompt for initial comment when a file is registered.") 83 "*Prompt for initial comment when a file is registered.")
91 (defvar vc-command-messages nil 84 (defvar vc-command-messages nil
92 "*Display run messages from back-end commands.") 85 "*Display run messages from back-end commands.")
93 (defvar vc-consult-headers t
94 "*Identify work files by searching for version headers.")
95 (defvar vc-mistrust-permissions nil
96 "*Don't assume that permissions and ownership track version-control status.")
97 (defvar vc-checkin-switches nil 86 (defvar vc-checkin-switches nil
98 "*Extra switches passed to the checkin program by \\[vc-checkin].") 87 "*Extra switches passed to the checkin program by \\[vc-checkin].")
99 (defvar vc-checkout-switches nil 88 (defvar vc-checkout-switches nil
100 "*Extra switches passed to the checkout program by \\[vc-checkout].") 89 "*Extra switches passed to the checkout program by \\[vc-checkout].")
101 (defvar vc-path
102 (if (file-directory-p "/usr/sccs")
103 '("/usr/sccs")
104 nil)
105 "*List of extra directories to search for version control commands.")
106 (defvar vc-directory-exclusion-list '("SCCS" "RCS") 90 (defvar vc-directory-exclusion-list '("SCCS" "RCS")
107 "*Directory names ignored by functions that recursively walk file trees.") 91 "*Directory names ignored by functions that recursively walk file trees.")
108 92
109 (defconst vc-maximum-comment-ring-size 32 93 (defconst vc-maximum-comment-ring-size 32
110 "Maximum number of saved comments in the comment ring.") 94 "Maximum number of saved comments in the comment ring.")
199 (interactive) 183 (interactive)
200 (fillarray vc-file-prop-obarray nil) 184 (fillarray vc-file-prop-obarray nil)
201 ;; Note: there is potential for minor lossage here if there is an open 185 ;; Note: there is potential for minor lossage here if there is an open
202 ;; log buffer with a nonzero local value of vc-comment-ring-index. 186 ;; log buffer with a nonzero local value of vc-comment-ring-index.
203 (setq vc-comment-ring nil)) 187 (setq vc-comment-ring nil))
188
189 ;;; functions that operate on RCS revision numbers
190
191 ;; vc-occurences and vc-branch-p moved to vc-hooks.el
192
193 (defun vc-trunk-p (rev)
194 ;; return t if REV is a revision on the trunk
195 (not (eq nil (string-match "\\`[0-9]+\\.[0-9]+\\'" rev))))
196
197 (defun vc-minor-revision (rev)
198 ;; return the minor revision number of REV,
199 ;; i.e. the number after the last dot.
200 (substring rev (1+ (string-match "\\.[0-9]+\\'" rev))))
201
202 (defun vc-branch-part (rev)
203 ;; return the branch part of a revision number REV
204 (substring rev 0 (string-match "\\.[0-9]+\\'" rev)))
204 205
205 ;; Random helper functions 206 ;; Random helper functions
206 207
207 (defun vc-registration-error (file) 208 (defun vc-registration-error (file)
208 (if file 209 (if file
296 297
297 (defmacro vc-backend-dispatch (f s r c) 298 (defmacro vc-backend-dispatch (f s r c)
298 "Execute FORM1, FORM2 or FORM3 depending whether we're using SCCS, RCS or CVS. 299 "Execute FORM1, FORM2 or FORM3 depending whether we're using SCCS, RCS or CVS.
299 If FORM3 is RCS, use FORM2 even if we are using CVS. (CVS shares some code 300 If FORM3 is RCS, use FORM2 even if we are using CVS. (CVS shares some code
300 with RCS)." 301 with RCS)."
301 (list 'let (list (list 'type (list 'vc-backend-deduce f))) 302 (list 'let (list (list 'type (list 'vc-backend f)))
302 (list 'cond 303 (list 'cond
303 (list (list 'eq 'type (quote 'SCCS)) s) ;; SCCS 304 (list (list 'eq 'type (quote 'SCCS)) s) ;; SCCS
304 (list (list 'eq 'type (quote 'RCS)) r) ;; RCS 305 (list (list 'eq 'type (quote 'RCS)) r) ;; RCS
305 (list (list 'eq 'type (quote 'CVS)) ;; CVS 306 (list (list 'eq 'type (quote 'CVS)) ;; CVS
306 (if (eq c 'RCS) r c)) 307 (if (eq c 'RCS) r c))
436 unchanged))))) 437 unchanged)))))
437 438
438 (defun vc-next-action-on-file (file verbose &optional comment) 439 (defun vc-next-action-on-file (file verbose &optional comment)
439 ;;; If comment is specified, it will be used as an admin or checkin comment. 440 ;;; If comment is specified, it will be used as an admin or checkin comment.
440 (let ((vc-file (vc-name file)) 441 (let ((vc-file (vc-name file))
441 (vc-type (vc-backend-deduce file)) 442 (vc-type (vc-backend file))
442 owner version) 443 owner version)
443 (cond 444 (cond
444 445
445 ;; if there is no master file corresponding, create one 446 ;; if there is no master file corresponding, create one
446 ((not vc-file) 447 ((not vc-file)
519 520
520 ;; CVS: Buffer is read-only. Make the file "locked", i.e. 521 ;; CVS: Buffer is read-only. Make the file "locked", i.e.
521 ;; make the buffer writable, and assert the user to be the locker 522 ;; make the buffer writable, and assert the user to be the locker
522 ((and (eq vc-type 'CVS) buffer-read-only) 523 ((and (eq vc-type 'CVS) buffer-read-only)
523 (if verbose 524 (if verbose
524 (progn 525 (let ((rev (read-string "Trunk version to move to: ")))
525 (setq rev (read-string "Trunk version to move to: "))
526 (if (not (string= rev "")) 526 (if (not (string= rev ""))
527 (vc-checkout file nil rev) 527 (vc-checkout file nil rev)
528 (vc-do-command 0 "cvs" file 'WORKFILE "update" "-A") 528 (vc-do-command 0 "cvs" file 'WORKFILE "update" "-A")
529 (vc-checkout file))) 529 (vc-checkout file)))
530 (setq buffer-read-only nil) 530 (setq buffer-read-only nil)
1054 (y-or-n-p "Version headers already exist. Insert another set? ")) 1054 (y-or-n-p "Version headers already exist. Insert another set? "))
1055 (progn 1055 (progn
1056 (let* ((delims (cdr (assq major-mode vc-comment-alist))) 1056 (let* ((delims (cdr (assq major-mode vc-comment-alist)))
1057 (comment-start-vc (or (car delims) comment-start "#")) 1057 (comment-start-vc (or (car delims) comment-start "#"))
1058 (comment-end-vc (or (car (cdr delims)) comment-end "")) 1058 (comment-end-vc (or (car (cdr delims)) comment-end ""))
1059 (hdstrings (cdr (assoc (vc-backend-deduce (buffer-file-name)) vc-header-alist)))) 1059 (hdstrings (cdr (assoc (vc-backend (buffer-file-name)) vc-header-alist))))
1060 (mapcar (function (lambda (s) 1060 (mapcar (function (lambda (s)
1061 (insert comment-start-vc "\t" s "\t" 1061 (insert comment-start-vc "\t" s "\t"
1062 comment-end-vc "\n"))) 1062 comment-end-vc "\n")))
1063 hdstrings) 1063 hdstrings)
1064 (if vc-static-header-alist 1064 (if vc-static-header-alist
1366 ;; have serious disadvantages. See the FAQ (available from think.com in 1366 ;; have serious disadvantages. See the FAQ (available from think.com in
1367 ;; pub/cvs/). I'd rather send the user an error, than do something he might 1367 ;; pub/cvs/). I'd rather send the user an error, than do something he might
1368 ;; consider to be wrong. When the famous, long-awaited rename database is 1368 ;; consider to be wrong. When the famous, long-awaited rename database is
1369 ;; implemented things might change for the better. This is unlikely to occur 1369 ;; implemented things might change for the better. This is unlikely to occur
1370 ;; until CVS 2.0 is released. --ceder 1994-01-23 21:27:51 1370 ;; until CVS 2.0 is released. --ceder 1994-01-23 21:27:51
1371 (if (eq (vc-backend-deduce old) 'CVS) 1371 (if (eq (vc-backend old) 'CVS)
1372 (error "Renaming files under CVS is dangerous and not supported in VC.")) 1372 (error "Renaming files under CVS is dangerous and not supported in VC."))
1373 (let ((oldbuf (get-file-buffer old))) 1373 (let ((oldbuf (get-file-buffer old)))
1374 (if (and oldbuf (buffer-modified-p oldbuf)) 1374 (if (and oldbuf (buffer-modified-p oldbuf))
1375 (error "Please save files before moving them")) 1375 (error "Please save files before moving them"))
1376 (if (get-file-buffer new) 1376 (if (get-file-buffer new)
1386 ;; This had FILE, I changed it to OLD. -- rms. 1386 ;; This had FILE, I changed it to OLD. -- rms.
1387 (file-symlink-p (vc-backend-subdirectory-name old))) 1387 (file-symlink-p (vc-backend-subdirectory-name old)))
1388 (error "This is not a safe thing to do in the presence of symbolic links")) 1388 (error "This is not a safe thing to do in the presence of symbolic links"))
1389 (rename-file 1389 (rename-file
1390 oldmaster 1390 oldmaster
1391 (let ((backend (vc-backend-deduce old)) 1391 (let ((backend (vc-backend old))
1392 (newdir (or (file-name-directory new) "")) 1392 (newdir (or (file-name-directory new) ""))
1393 (newbase (file-name-nondirectory new))) 1393 (newbase (file-name-nondirectory new)))
1394 (catch 'found 1394 (catch 'found
1395 (mapcar 1395 (mapcar
1396 (function 1396 (function
1436 (let ((files nil) 1436 (let ((files nil)
1437 (buffers (buffer-list)) 1437 (buffers (buffer-list))
1438 file) 1438 file)
1439 (while buffers 1439 (while buffers
1440 (setq file (buffer-file-name (car buffers))) 1440 (setq file (buffer-file-name (car buffers)))
1441 (and file (vc-backend-deduce file) 1441 (and file (vc-backend file)
1442 (setq files (cons file files))) 1442 (setq files (cons file files)))
1443 (setq buffers (cdr buffers))) 1443 (setq buffers (cdr buffers)))
1444 files)) 1444 files))
1445 (t 1445 (t
1446 (let ((RCS (concat default-directory "RCS"))) 1446 (let ((RCS (concat default-directory "RCS")))
1475 f 1475 f
1476 (concat odefault f))))) 1476 (concat odefault f)))))
1477 args)))) 1477 args))))
1478 "done" "failed")))) 1478 "done" "failed"))))
1479 1479
1480 ;; Functions for querying the master and lock files.
1481
1482 (defun vc-match-substring (bn)
1483 (buffer-substring (match-beginning bn) (match-end bn)))
1484
1485 (defun vc-parse-buffer (patterns &optional file properties)
1486 ;; Use PATTERNS to parse information out of the current buffer
1487 ;; by matching each regular expression in the list and returning \\1.
1488 ;; If a regexp has three tag brackets, assume the third is a date
1489 ;; field and we want the most recent entry matching the template.
1490 ;; If FILE and PROPERTIES are given, the latter must be a list of
1491 ;; properties of the same length as PATTERNS; each property is assigned
1492 ;; the corresponding value.
1493 (mapcar (function (lambda (p)
1494 (goto-char (point-min))
1495 (if (string-match "\\\\([^(]*\\\\([^(]*\\\\(" p)
1496 (let ((latest-date "") (latest-val))
1497 (while (re-search-forward p nil t)
1498 (let ((date (vc-match-substring 3)))
1499 (if (string< latest-date date)
1500 (progn
1501 (setq latest-date date)
1502 (setq latest-val
1503 (vc-match-substring 1))))))
1504 (if file
1505 (progn (vc-file-setprop file (car properties) latest-val)
1506 (setq properties (cdr properties))))
1507 latest-val)
1508 (let ((value nil))
1509 (if (re-search-forward p nil t)
1510 (setq value (vc-match-substring 1)))
1511 (if file
1512 (progn (vc-file-setprop file (car properties) value)
1513 (setq properties (cdr properties))))
1514 value))))
1515 patterns)
1516 )
1517
1518 (defun vc-master-info (file fields &optional rfile properties)
1519 ;; Search for information in a master file.
1520 (if (and file (file-exists-p file))
1521 (save-excursion
1522 (let ((buf))
1523 (setq buf (create-file-buffer file))
1524 (set-buffer buf))
1525 (erase-buffer)
1526 (insert-file-contents file)
1527 (set-buffer-modified-p nil)
1528 (auto-save-mode nil)
1529 (prog1
1530 (vc-parse-buffer fields rfile properties)
1531 (kill-buffer (current-buffer)))
1532 )
1533 (if rfile
1534 (mapcar
1535 (function (lambda (p) (vc-file-setprop rfile p nil)))
1536 properties))
1537 )
1538 )
1539
1540 (defun vc-log-info (command file last flags patterns &optional properties)
1541 ;; Search for information in log program output.
1542 ;; If there is a string `\X' in any of the PATTERNS, replace
1543 ;; it with a regexp to search for a branch revision.
1544 (if (and file (file-exists-p file))
1545 (save-excursion
1546 ;; Don't switch to the *vc* buffer before running vc-do-command,
1547 ;; because that would change its default-directory.
1548 (apply 'vc-do-command 0 command file last flags)
1549 (set-buffer (get-buffer "*vc*"))
1550 (set-buffer-modified-p nil)
1551 (let ((branch
1552 (car (vc-parse-buffer (list "^branch:[ \t]+\\([0-9.]+\\)$")))))
1553 (setq patterns
1554 (mapcar
1555 (function
1556 (lambda (p)
1557 (if (string-match "\\\\X" p)
1558 (if branch
1559 (cond ((vc-branch-p branch)
1560 (concat
1561 (substring p 0 (match-beginning 0))
1562 (regexp-quote branch)
1563 "\\.[0-9]+"
1564 (substring p (match-end 0))))
1565 (t
1566 (concat
1567 (substring p 0 (match-beginning 0))
1568 (regexp-quote branch)
1569 (substring p (match-end 0)))))
1570 ;; if there is no current branch,
1571 ;; return a completely different regexp,
1572 ;; which searches for the *head*
1573 "^head:[ \t]+\\([0-9.]+\\)$")
1574 p)))
1575 patterns)))
1576 (prog1
1577 (vc-parse-buffer patterns file properties)
1578 (kill-buffer (current-buffer))
1579 )
1580 )
1581 (if file
1582 (mapcar
1583 (function (lambda (p) (vc-file-setprop file p nil)))
1584 properties))
1585 )
1586 )
1587
1588 (defun vc-locking-user (file)
1589 "Return the name of the person currently holding a lock on FILE.
1590 Return nil if there is no such person.
1591 Under CVS, a file is considered locked if it has been modified since it
1592 was checked out. Under CVS, this will sometimes return the uid of
1593 the owner of the file (as a number) instead of a string."
1594 ;; The property is cached. If it is non-nil, it is simply returned.
1595 ;; The other routines clear it when the locking state changes.
1596 (setq file (expand-file-name file));; ??? Work around bug in 19.0.4
1597 (cond
1598 ((vc-file-getprop file 'vc-locking-user))
1599 ((eq (vc-backend-deduce file) 'CVS)
1600 (if (vc-workfile-unchanged-p file)
1601 nil
1602 ;; The expression below should return the username of the owner
1603 ;; of the file. It doesn't. It returns the username if it is
1604 ;; you, or otherwise the UID of the owner of the file. The
1605 ;; return value from this function is only used by
1606 ;; vc-dired-reformat-line, and it does the proper thing if a UID
1607 ;; is returned.
1608 ;;
1609 ;; The *proper* way to fix this would be to implement a built-in
1610 ;; function in Emacs, say, (username UID), that returns the
1611 ;; username of a given UID.
1612 ;;
1613 ;; The result of this hack is that vc-directory will print the
1614 ;; name of the owner of the file for any files that are
1615 ;; modified.
1616 (let ((uid (nth 2 (file-attributes file))))
1617 (if (= uid (user-uid))
1618 (vc-file-setprop file 'vc-locking-user (user-login-name))
1619 (vc-file-setprop file 'vc-locking-user uid)))))
1620 (t
1621 (if (and (eq (vc-backend-deduce file) 'RCS)
1622 (eq (vc-consult-rcs-headers file) 'rev-and-lock))
1623 (vc-file-getprop file 'vc-locking-user)
1624 (if (or (not vc-keep-workfiles)
1625 (eq vc-mistrust-permissions 't)
1626 (and vc-mistrust-permissions
1627 (funcall vc-mistrust-permissions (vc-backend-subdirectory-name
1628 file))))
1629 (vc-file-setprop file 'vc-locking-user (vc-true-locking-user file))
1630 ;; This implementation assumes that any file which is under version
1631 ;; control and has -rw-r--r-- is locked by its owner. This is true
1632 ;; for both RCS and SCCS, which keep unlocked files at -r--r--r--.
1633 ;; We have to be careful not to exclude files with execute bits on;
1634 ;; scripts can be under version control too. Also, we must ignore
1635 ;; the group-read and other-read bits, since paranoid users turn them off.
1636 ;; This hack wins because calls to the very expensive vc-fetch-properties
1637 ;; function only have to be made if (a) the file is locked by someone
1638 ;; other than the current user, or (b) some untoward manipulation
1639 ;; behind vc's back has changed the owner or the `group' or `other'
1640 ;; write bits.
1641 (let ((attributes (file-attributes file)))
1642 (cond ((string-match ".r-..-..-." (nth 8 attributes))
1643 nil)
1644 ((and (= (nth 2 attributes) (user-uid))
1645 (string-match ".rw..-..-." (nth 8 attributes)))
1646 (vc-file-setprop file 'vc-locking-user (user-login-name)))
1647 (t
1648 (vc-file-setprop file 'vc-locking-user
1649 (vc-true-locking-user file))))))))))
1650
1651 (defun vc-true-locking-user (file)
1652 ;; The slow but reliable version
1653 (vc-fetch-properties file)
1654 (vc-file-getprop file 'vc-locking-user))
1655
1656 (defun vc-latest-version (file)
1657 ;; Return version level of the latest version of FILE
1658 (vc-fetch-properties file)
1659 (vc-file-getprop file 'vc-latest-version))
1660
1661 (defun vc-your-latest-version (file)
1662 ;; Return version level of the latest version of FILE checked in by you
1663 (vc-fetch-properties file)
1664 (vc-file-getprop file 'vc-your-latest-version))
1665
1666 (defun vc-branch-version (file)
1667 ;; Return version level of the highest revision on the default branch
1668 ;; If there is no default branch, return the highest version number
1669 ;; on the trunk.
1670 ;; This property is defined for RCS only.
1671 (vc-fetch-properties file)
1672 (vc-file-getprop file 'vc-branch-version))
1673
1674 (defun vc-workfile-version (file)
1675 ;; Return version level of the current workfile FILE
1676 ;; This is attempted by first looking at the RCS keywords.
1677 ;; If there are no keywords in the working file,
1678 ;; vc-branch-version is taken.
1679 ;; Note that this value is cached, that is, it is only
1680 ;; looked up if it is nil.
1681 ;; For SCCS, this property is equivalent to vc-latest-version.
1682 (cond ((vc-file-getprop file 'vc-workfile-version))
1683 (t (vc-backend-dispatch file
1684 (vc-latest-version file) ;; SCCS
1685 (if (vc-consult-rcs-headers file) ;; RCS
1686 (vc-file-getprop file 'vc-workfile-version)
1687 (let ((rev (cond ((vc-branch-version file))
1688 ((vc-latest-version file)))))
1689 (vc-file-setprop file 'vc-workfile-version rev)
1690 rev))
1691 (if (vc-consult-rcs-headers file) ;; CVS
1692 (vc-file-getprop file 'vc-workfile-version)
1693 (vc-find-cvs-master (file-name-directory file)
1694 (file-name-nondirectory file))
1695 (vc-file-getprop file 'vc-workfile-version))))))
1696
1697 (defun vc-consult-rcs-headers (file)
1698 ;; Search for RCS headers in FILE, and set properties
1699 ;; accordingly. This function can be disabled by setting
1700 ;; vc-consult-headers to nil.
1701 ;; Returns: nil if no headers were found
1702 ;; (or if the feature is disabled,
1703 ;; or if there is currently no buffer
1704 ;; visiting FILE)
1705 ;; 'rev if a workfile revision was found
1706 ;; 'rev-and-lock if revision and lock info was found
1707 (cond
1708 ((or (not vc-consult-headers)
1709 (not (get-file-buffer file)) nil))
1710 ((save-excursion
1711 (set-buffer (get-file-buffer file))
1712 (goto-char (point-min))
1713 (cond
1714 ;; search for $Id or $Header
1715 ;; -------------------------
1716 ((re-search-forward "\\$\\(Id\\|Header\\): [^ ]+ \\([0-9.]+\\) "
1717 nil t)
1718 ;; if found, store the revision number ...
1719 (let ((rev (buffer-substring (match-beginning 2)
1720 (match-end 2))))
1721 ;; ... and check for the locking state
1722 (if (re-search-forward
1723 (concat "\\=[0-9]+/[0-9]+/[0-9]+ " ; date
1724 "[0-9]+:[0-9]+:[0-9]+ " ; time
1725 "[^ ]+ [^ ]+ ") ; author & state
1726 nil t)
1727 (cond
1728 ;; unlocked revision
1729 ((looking-at "\\$")
1730 (vc-file-setprop file 'vc-workfile-version rev)
1731 (vc-file-setprop file 'vc-locking-user nil)
1732 (vc-file-setprop file 'vc-locked-version nil)
1733 'rev-and-lock)
1734 ;; revision is locked by some user
1735 ((looking-at "\\([^ ]+\\) \\$")
1736 (vc-file-setprop file 'vc-workfile-version rev)
1737 (vc-file-setprop file 'vc-locking-user
1738 (buffer-substring (match-beginning 1)
1739 (match-end 1)))
1740 (vc-file-setprop file 'vc-locked-version rev)
1741 'rev-and-lock)
1742 ;; everything else: false
1743 (nil))
1744 ;; unexpected information in
1745 ;; keyword string --> quit
1746 nil)))
1747 ;; search for $Revision
1748 ;; --------------------
1749 ((re-search-forward (concat "\\$"
1750 "Revision: \\([0-9.]+\\) \\$")
1751 nil t)
1752 ;; if found, store the revision number ...
1753 (let ((rev (buffer-substring (match-beginning 1)
1754 (match-end 1))))
1755 ;; and see if there's any lock information
1756 (goto-char (point-min))
1757 (if (re-search-forward (concat "\\$" "Locker:") nil t)
1758 (cond ((looking-at " \\([^ ]+\\) \\$")
1759 (vc-file-setprop file 'vc-workfile-version rev)
1760 (vc-file-setprop file 'vc-locking-user
1761 (buffer-substring (match-beginning 1)
1762 (match-end 1)))
1763 (vc-file-setprop file 'vc-locked-version rev)
1764 'rev-and-lock)
1765 ((looking-at " *\\$")
1766 (vc-file-setprop file 'vc-workfile-version rev)
1767 (vc-file-setprop file 'vc-locking-user nil)
1768 (vc-file-setprop file 'vc-locked-version nil)
1769 'rev-and-lock)
1770 (t
1771 (vc-file-setprop file 'vc-workfile-version rev)
1772 'rev-and-lock))
1773 (vc-file-setprop file 'vc-workfile-version rev)
1774 'rev)))
1775 ;; else: nothing found
1776 ;; -------------------
1777 (t nil))))))
1778
1779 ;; Collect back-end-dependent stuff here 1480 ;; Collect back-end-dependent stuff here
1780
1781 (defun vc-lock-file (file)
1782 ;; Generate lock file name corresponding to FILE
1783 (let ((master (vc-name file)))
1784 (and
1785 master
1786 (string-match "\\(.*/\\)s\\.\\(.*\\)" master)
1787 (concat
1788 (substring master (match-beginning 1) (match-end 1))
1789 "p."
1790 (substring master (match-beginning 2) (match-end 2))))))
1791
1792
1793 (defun vc-fetch-properties (file)
1794 ;; Re-fetch some properties associated with the given file.
1795 ;; Currently these properties are:
1796 ;; vc-locking-user
1797 ;; vc-locked-version
1798 ;; vc-latest-version
1799 ;; vc-your-latest-version
1800 ;; vc-branch-version (RCS only)
1801 (vc-backend-dispatch
1802 file
1803 ;; SCCS
1804 (progn
1805 (vc-master-info (vc-lock-file file)
1806 (list
1807 "^[^ ]+ [^ ]+ \\([^ ]+\\)"
1808 "^\\([^ ]+\\)")
1809 file
1810 '(vc-locking-user vc-locked-version))
1811 (vc-master-info (vc-name file)
1812 (list
1813 "^\001d D \\([^ ]+\\)"
1814 (concat "^\001d D \\([^ ]+\\) .* "
1815 (regexp-quote (user-login-name)) " ")
1816 )
1817 file
1818 '(vc-latest-version vc-your-latest-version))
1819 )
1820 ;; RCS
1821 (vc-log-info "rlog" file 'MASTER nil
1822 (list
1823 "^locks: strict\n\t\\([^:]+\\)"
1824 "^locks: strict\n\t[^:]+: \\(.+\\)"
1825 "^revision[\t ]+\\([0-9.]+\\)\\(\n\\|[ \t].*\n\\)date: \\([ /0-9:]+\\);"
1826 (concat
1827 "^revision[\t ]+\\([0-9.]+\\)\\(\n\\|[ \t].*\n\\)date: \\([ /0-9:]+\\); *author: "
1828 (regexp-quote (user-login-name))
1829 ";")
1830
1831 ;; special regexp to search for branch revision:
1832 ;; \X will be replaced by vc-log-info (see there)
1833 "^revision[\t ]+\\(\\X\\)\\(\n\\|[ \t].*\n\\)date: \\([ /0-9:]+\\);")
1834
1835 '(vc-locking-user
1836 vc-locked-version
1837 vc-latest-version
1838 vc-your-latest-version
1839 vc-branch-version))
1840 ;; CVS
1841 ;; Only fetch vc-latest-version here, all other properties are
1842 ;; computed elsehow.
1843 (vc-log-info
1844 "cvs" file 'WORKFILE '("status")
1845 ;; CVS 1.3 says "RCS Version:", other releases "RCS Revision:",
1846 ;; and CVS 1.4a1 says "Repository revision:". The regexp below
1847 ;; matches much more, but because of the way vc-log-info is
1848 ;; implemented it is impossible to use additional groups.
1849 '("R[eC][pS][ositry]* [VRr]e[rv][si][is]i?on:[\t ]+\\([0-9.]+\\)")
1850 '(vc-latest-version))
1851 ))
1852
1853 (defun vc-backend-subdirectory-name (&optional file)
1854 ;; Where the master and lock files for the current directory are kept
1855 (symbol-name
1856 (or
1857 (and file (vc-backend-deduce file))
1858 vc-default-back-end
1859 (setq vc-default-back-end (if (vc-find-binary "rcs") 'RCS 'SCCS)))))
1860 1481
1861 (defun vc-backend-admin (file &optional rev comment) 1482 (defun vc-backend-admin (file &optional rev comment)
1862 ;; Register a file into the version-control system 1483 ;; Register a file into the version-control system
1863 ;; Automatically retrieves a read-only version of the file with 1484 ;; Automatically retrieves a read-only version of the file with
1864 ;; keywords expanded if vc-keep-workfiles is non-nil, otherwise 1485 ;; keywords expanded if vc-keep-workfiles is non-nil, otherwise
2182 ) 1803 )
2183 1804
2184 (defun vc-backend-diff (file &optional oldvers newvers cmp) 1805 (defun vc-backend-diff (file &optional oldvers newvers cmp)
2185 ;; Get a difference report between two versions of FILE. 1806 ;; Get a difference report between two versions of FILE.
2186 ;; Get only a brief comparison report if CMP, a difference report otherwise. 1807 ;; Get only a brief comparison report if CMP, a difference report otherwise.
2187 (let ((backend (vc-backend-deduce file))) 1808 (let ((backend (vc-backend file)))
2188 (cond 1809 (cond
2189 ((eq backend 'SCCS) 1810 ((eq backend 'SCCS)
2190 (setq oldvers (vc-lookup-triple file oldvers)) 1811 (setq oldvers (vc-lookup-triple file oldvers))
2191 (setq newvers (vc-lookup-triple file newvers))) 1812 (setq newvers (vc-lookup-triple file newvers)))
2192 ((eq backend 'RCS) 1813 ((eq backend 'RCS)