;;; vc-svn.el --- non-resident support for Subversion version-control
-;; Copyright (C) 2003, 2004, 2005, 2006, 2007 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>
;; Sync'd with Subversion's vc-svn.el as of revision 5801. but this version
;; has been extensively modified since to handle filesets.
-;;; Bugs:
-
-;; - VC-dired is (really) slow.
-
;;; Code:
(eval-when-compile
;; an `error' by vc-do-command.
(error nil))))
(when (eq 0 status)
- (vc-svn-parse-status file))))))
+ (not (memq (vc-svn-parse-status file)
+ '(ignored unregistered))))))))
(defun vc-svn-state (file &optional localp)
"SVN-specific version of `vc-state'."
(vc-svn-state file 'local))
(defun vc-svn-dir-state (dir &optional localp)
- "Find the SVN state of all files in DIR."
+ "Find the SVN state of all files in DIR and its subdirectories."
(setq localp (or localp (vc-stay-local-p dir)))
(let ((default-directory dir))
;; Don't specify DIR in this command, the default-directory is
;; enough. Otherwise it might fail with remote repositories.
(with-temp-buffer
+ (buffer-disable-undo) ;; Because these buffers can get huge
(vc-svn-command t 0 nil "status" (if localp "-v" "-u"))
(vc-svn-parse-status))))
(cond ((eq svn-state 'edited)
(if (equal (vc-working-revision file) "0")
"(added)" "(modified)"))
- ((eq svn-state 'needs-patch) "(patch)")
- ((eq svn-state 'needs-merge) "(merge)"))))
+ (t
+ ;; fall back to the default VC representation
+ (vc-default-dired-state-info 'SVN file)))))
+
(defun vc-svn-previous-revision (file rev)
(let ((newrev (1- (string-to-number rev))))
(error "Couldn't analyze svn update result")))
(message "Merging changes into %s...done" file))))
+(defun vc-svn-modify-change-comment (files rev comment)
+ "Modify the change comments for a specified REV.
+You must have ssh access to the repository host, and the directory Emacs
+uses locally for temp files must also be writeable by you on that host."
+ (vc-do-command nil 0 "svn" nil "info")
+ (set-buffer "*vc*")
+ (goto-char (point-min))
+ (unless (re-search-forward "Repository Root: svn\\+ssh://\\([^/]+\\)\\(/.*\\)" nil t)
+ (error "Repository information is unavailable."))
+ (let* ((tempfile (make-temp-file user-mail-address))
+ (host (match-string 1))
+ (directory (match-string 2))
+ (remotefile (concat host ":" tempfile)))
+ (with-temp-buffer
+ (insert comment)
+ (write-region (point-min) (point-max) tempfile))
+ (unless (vc-do-command nil 0 "scp" nil "-q" tempfile remotefile)
+ (error "Copy of comment to %s failed" remotefile))
+ (unless (vc-do-command nil 0 "ssh" nil
+ "-q" host
+ (format "svnadmin setlog --bypass-hooks %s -r %s %s; rm %s"
+ directory rev tempfile tempfile))
+ (error "Log edit failed"))
+ ))
;;;
;;; History functions
(vc-setup-buffer buffer)
(let ((inhibit-read-only t))
(goto-char (point-min))
- ;; Add a line to tell log-view-mode what file this is.
- ;; FIXME if there are multiple files, log-view-current-file
- ;; breaks. It's trivial to adapt log-view-file-re for the
- ;; changed prefix, but less trivial to make
- ;; log-view-current-file actually do the right thing in the
- ;; multiple file case.
- (insert (format "Working file%s: "
- (if (= (length files) 1)
- ""
- "s"))
- (vc-delistify (mapcar 'file-relative-name files)) "\n"))
- (vc-svn-command
- buffer
- (if (and (= (length files) 1) (vc-stay-local-p (car files)) (fboundp 'start-process)) 'async 0)
- files "log"
- ;; By default Subversion only shows the log upto the working revision,
- ;; whereas we also want the log of the subsequent commits. At least
- ;; that's what the vc-cvs.el code does.
- "-rHEAD:0")))
+ (if files
+ (dolist (file files)
+ (insert "Working file: " file "\n")
+ (vc-svn-command
+ buffer
+ 'async
+ ;; (if (and (= (length files) 1) (vc-stay-local-p file)) 'async 0)
+ (list file)
+ "log"
+ ;; By default Subversion only shows the log up to the
+ ;; working revision, whereas we also want the log of the
+ ;; subsequent commits. At least that's what the
+ ;; vc-cvs.el code does.
+ "-rHEAD:0"))
+ ;; Dump log for the entire directory.
+ (vc-svn-command buffer 0 nil "log" "-rHEAD:0")))))
(defun vc-svn-wash-log ()
"Remove all non-comment information from log output."
(list "-x" (mapconcat 'identity (vc-switches nil 'diff) " "))))
(async (and (not vc-disable-async-diff)
(vc-stay-local-p files)
- (or oldvers newvers) ; Svn diffs those locally.
- (fboundp 'start-process))))
+ (or oldvers newvers)))) ; Svn diffs those locally.
(apply 'vc-svn-command buffer
(if async 'async 0)
files "diff"
(re-search-forward "^<<<<<<< " nil t))
;; There are conflict markers.
(progn
- (smerge-mode 1)
+ (smerge-start-session)
(add-hook 'after-save-hook 'vc-svn-resolve-when-done nil t))
;; There are no conflict markers. This is problematic: maybe it means
;; the conflict has been resolved and we should immediately call "svn
(let (file status)
(goto-char (point-min))
(while (re-search-forward
- ;; Ignore the files with status in [IX?].
- "^[ ACDGMR!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([-0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\) +" nil t)
+ ;; Ignore the files with status X.
+ "^\\(\\?\\|[ 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
(expand-file-name
(buffer-substring (point) (line-end-position)))))
(setq status (char-after (line-beginning-position)))
- (unless (eq status ??)
+ (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))
;; If the file was actually copied, (match-string 2) is "-".
(vc-file-setprop file 'vc-working-revision "0")
(vc-file-setprop file 'vc-checkout-time 0)
- 'edited)
+ 'added)
((memq status '(?M ?C))
(if (eq (char-after (match-beginning 1)) ?*)
'needs-merge
'edited))
+ ((eq status ?I)
+ (vc-file-setprop file 'vc-state 'ignored))
+ ((eq status ?R)
+ (vc-file-setprop file 'vc-state 'removed))
(t 'edited)))))
(if filename (vc-file-getprop filename 'vc-state))))