;;; vc-svn.el --- non-resident support for Subversion version-control
-;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+;; Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: Stefan Monnier <monnier@gnu.org>
"SVN-specific state heuristic."
(vc-svn-state file 'local))
-(defun vc-svn-after-dir-status (callback)
+;; FIXME it would be better not to have the "remote" argument,
+;; but to distinguish the two output formats based on content.
+(defun vc-svn-after-dir-status (callback &optional remote)
(let ((state-map '((?A . added)
(?C . conflict)
(?D . removed)
(?? . unregistered)
;; This is what vc-svn-parse-status does.
(?~ . edited)))
+ (re (if remote "^\\(.\\)..... \\([ *]\\) +[-0-9]+ +\\(.*\\)$"
+ ;; Subexp 2 is a dummy in this case, so the numbers match.
+ "^\\(.\\)....\\(.\\) \\(.*\\)$"))
result)
(goto-char (point-min))
- (while (re-search-forward "^\\(.\\)..... \\(.*\\)$" nil t)
+ (while (re-search-forward re nil t)
(let ((state (cdr (assq (aref (match-string 1) 0) state-map)))
- (filename (match-string 2)))
+ (filename (match-string 3)))
+ (and remote (string-equal (match-string 2) "*")
+ ;; FIXME are there other possible combinations?
+ (cond ((eq state 'edited) (setq state 'needs-merge))
+ ((not state) (setq state 'needs-update))))
(when state
(setq result (cons (list filename state) result)))))
(funcall callback result)))
"Run 'svn status' for DIR and update BUFFER via CALLBACK.
CALLBACK is called as (CALLBACK RESULT BUFFER), where
RESULT is a list of conses (FILE . STATE) for directory DIR."
- (vc-svn-command (current-buffer) 'async nil "status")
+ ;; FIXME should this rather be all the files in dir?
+ (let* ((local (vc-stay-local-p dir))
+ (remote (and local (not (eq local 'only-file)))))
+ (vc-svn-command (current-buffer) 'async nil "status"
+ (if remote "-u"))
+ (vc-exec-after
+ `(vc-svn-after-dir-status (quote ,callback) ,remote))))
+
+(defun vc-svn-dir-status-files (dir files default-state callback)
+ (apply 'vc-svn-command (current-buffer) 'async nil "status" files)
(vc-exec-after
`(vc-svn-after-dir-status (quote ,callback))))
+(defun vc-svn-dir-extra-headers (dir)
+ "Generate extra status headers for a Subversion working copy."
+ (vc-svn-command "*vc*" 0 nil "info")
+ (let ((repo
+ (save-excursion
+ (and (progn
+ (set-buffer "*vc*")
+ (goto-char (point-min))
+ (re-search-forward "Repository Root: *\\(.*\\)" nil t))
+ (match-string 1)))))
+ (concat
+ (cond (repo
+ (concat
+ (propertize "Repository : " 'face 'font-lock-type-face)
+ (propertize repo 'face 'font-lock-variable-name-face)))
+ (t "")))))
+
(defun vc-svn-working-revision (file)
"SVN-specific version of `vc-working-revision'."
;; There is no need to consult RCS headers under SVN, because we
(progn
(unless (vc-do-command
"*vc*" 0 "svnadmin" nil
- "setlog" "--bypass-hooks" directory
+ "setlog" "--bypass-hooks" directory
"-r" rev (format "%s" tempfile))
(error "Log edit failed"))
(delete-file tempfile))
;;; History functions
;;;
+(defvar log-view-per-file-logs)
+
+(define-derived-mode vc-svn-log-view-mode log-view-mode "SVN-Log-View"
+ (require 'add-log)
+ (set (make-local-variable 'log-view-per-file-logs) nil))
+
(defun vc-svn-print-log (files &optional buffer)
"Get change log(s) associated with FILES."
(save-current-buffer
(defun vc-svn-diff (files &optional oldvers newvers buffer)
"Get a difference report using SVN between two revisions of fileset FILES."
(and oldvers
+ files
(catch 'no
(dolist (f files)
(or (equal oldvers (vc-working-revision f))
:type 'string
:group 'vc)
-(defun vc-svn-root (dir)
- (vc-find-root dir vc-svn-admin-directory t))
-
(defun vc-svn-command (buffer okstatus file-or-list &rest flags)
"A wrapper around `vc-do-command' for use in vc-svn.el.
The difference to vc-do-command is that this function always invokes `svn',
(goto-char (point-min))
(while (re-search-forward
;; Ignore the files with status X.
- "^\\(\\?\\|[ ACDGIMR!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([-0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\)\\) +" nil t)
+ "^\\(?:\\?\\|[ ACDGIMR!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([-0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\)\\) +" nil t)
;; If the username contains spaces, the output format is ambiguous,
;; so don't trust the output's filename unless we have to.
(setq file (or filename
(setq status (char-after (line-beginning-position)))
(if (eq status ??)
(vc-file-setprop file 'vc-state 'unregistered)
- ;; `vc-BACKEND-registered' must not set vc-backend,
- ;; which is instead set in vc-registered.
- (unless filename (vc-file-setprop file 'vc-backend 'SVN))
;; Use the last-modified revision, so that searching in vc-print-log
;; output works.
(vc-file-setprop file 'vc-working-revision (match-string 3))
((eq status ?R)
(vc-file-setprop file 'vc-state 'removed))
(t 'edited)))))
- (if filename (vc-file-getprop filename 'vc-state))))
+ (when filename (vc-file-getprop filename 'vc-state))))
(defun vc-svn-valid-symbolic-tag-name-p (tag)
"Return non-nil if TAG is a valid symbolic tag name."
;; Arbitrarily assume 10 commmits per day.
(/ (string-to-number rev) 10.0))
+(defvar vc-annotate-parent-rev)
+
(defun vc-svn-annotate-current-time ()
(vc-svn-annotate-time-of-rev vc-annotate-parent-rev))