[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Emacs VC support for Subversion

From: Jim Blandy <jimb_at_red-bean.com>
Date: 2002-07-12 03:00:06 CEST

Ben said he'd be happy just to have revision numbers in his modeline.
This is enough to do that, with ':' for locally modified files vs.
'-' for unmodified files, but not much else. :)

If anyone is interested, maybe this could find a place in the
Subversion tree!

;;;; vc-svn.el --- a VC backend for Subversion
;;;; Jim Blandy <jimb@red-bean.com> --- July 2002

;;; To do:
;;; Provide more of the optional VC backend functions:
;;; - vc-svn-dir-state
;;;
;;; Some are unnecessary; for example,
;;; `vc-BACKEND-workfile-unchanged-p' defaults to calling the full
;;; `vc-BACKEND-diff' function, which is actually fine for Subversion,
;;; since it has a copy of the base revision cached locally.
;;;
;;; VC passes the vc-svn-register function a COMMENT argument, which
;;; is like the file description in CVS and RCS. Could we store the
;;; COMMENT as a Subversion property? Would that show up in fancy DAV
;;; web folder displays, or would it just languish in obscurity, the
;;; way CVS and RCS descriptions do?

(add-value 'vc-handled-backends 'SVN)

(defvar vc-svn-program-name "svn"
  "*Name of Subversion client program, for use by Emacs's VC package.")

(defun vc-svn-registered (file)
  "Return true if FILE is registered under Subversion."
  ;; First, a quick false positive test: is there a `.svn/entries' file?
  (and (file-exists-p (expand-file-name ".svn/entries"
                                        (file-name-directory file)))
       (not (null (vc-svn-run-status file)))))

(put 'vc-svn-with-output-buffer 'lisp-indent-function 0)
(defmacro vc-svn-with-output-buffer (&rest body)
  "Save excursion, switch to buffer ` *Subversion Output*', and erase it."
  `(save-excursion
     ;; Let's not delete this buffer when we're done --- leave
     ;; it around for debugging.
     (set-buffer (get-buffer-create " *Subversion Output*"))
     (erase-buffer)
     ,@body))

(defun vc-svn-run-status (file &optional update)
  "Run `svn status -v' on FILE, and return the result.
If optional arg UPDATE is true, pass the `-u' flag to check against
the repository, across the network.
See `vc-svn-parse-status' for a description of the result."
  (vc-svn-with-output-buffer
    (let ((status (apply 'call-process vc-svn-program-name nil t nil
                         (append '("status" "-v")
                                 (if update '("-u") '())
                                 (list file)))))
      (goto-char (point-min))
      (if (not (zerop status))
          ;; If you ask for the status of a file that isn't even in a
          ;; Subversion-controlled directory, then Subversion exits with
          ;; this error.
          (if (or (looking-at "\\(.*\n\\)*.*is not a working copy directory")
                  (looking-at "\\(.*\n\\)*.*is not a versioned resource"))
              nil
            ;; Other errors we should actually report to the user.
            (display-buffer (current-buffer))
            (error "Error running Subversion to check status of `%s'"
                   (file-name-nondirectory file)))

        ;; Otherwise, we've got valid status output in the buffer, so
        ;; just parse that.
        (vc-svn-parse-status)))))

(defun vc-svn-parse-status ()
  "Parse the output from `svn status -v' at point.
We return nil for a file not under Subversion's control,
or (STATE LOCAL CHANGED) for files that are, where:
STATE is the file's VC state (see the documentation for `vc-state'),
LOCAL is the base revision in the working copy, and
CHANGED is the last revision in which it was changed. If we passed
  `svn status' the `-u' flag, then CHANGED might be greater than LOCAL."
  (let ((state (vc-svn-parse-state-only)))
    (and state
         (if (looking-at
              "\\S-+\\s-+\\(\\*\\s-+\\)?\\([0-9]+\\)\\s-+\\([0-9]+\\)")
             (list state
                   (string-to-number (match-string 2))
                   (string-to-number (match-string 3)))
           (error "Couldn't parse output from `svn status -v'")))))

(defun vc-svn-parse-state-only ()
  "Parse the output from `svn status -v' at point, and return a state.
The documentation for the function `vc-state' describes the possible values."
  (cond
   ;; Be careful --- some of the later clauses here could yield false
   ;; positives, if the clauses preceding them didn't screen those
   ;; out. Making a pattern more selective could break something.

   ;; nil The given file is not under version control.
   ((looking-at "\\?") nil)

   ;; 'needs-patch The file has not been edited by the
   ;; user, but there is a more recent version
   ;; on the current branch stored in the
   ;; master file.
   ((looking-at "_[_ ]..\\s-+\\*") 'needs-patch)

   ;; 'up-to-date The working file is unmodified with
   ;; respect to the latest version on the
   ;; current branch, and not locked.
   ((looking-at "_[_ ]") 'up-to-date)

   ;; 'needs-merge The file has been edited by the user,
   ;; and there is also a more recent version
   ;; on the current branch stored in the
   ;; master file. This state can only occur
   ;; if locking is not used for the file.
   ((looking-at "\\S-+\\s-+\\*") 'needs-merge)

   ;; 'edited The working file has been edited by the
   ;; user. If locking is used for the file,
   ;; this state means that the current
   ;; version is locked by the calling user.
   (t 'edited)))

(defun vc-svn-state (file)
  "Return the current version control state of FILE.
For a list of possible return values, see `vc-state'.
This function should do a full and reliable state computation; it is
usually called immediately after `C-x v v'. `vc-svn-state-heuristic'
provides a faster heuristic when visiting a file."
  (car (vc-svn-run-status file 'update)))

(defun vc-svn-state-heuristic (file)
  "Estimate the version control state of FILE at visiting time.
For a list of possible values, see the doc string of `vc-state'.
This is supposed to be considerably faster than `vc-svn-state'. It
just runs `svn status -v', without the `-u' flag, so it's a strictly
local operation."
  (car (vc-svn-run-status file)))

(defun vc-svn-workfile-version (file)
  "Return the current workfile version of FILE."
  (number-to-string (cadr (vc-svn-run-status file))))

(defun vc-svn-checkout-model (file)
  'implicit)

(provide 'vc-svn)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Jul 12 03:00:35 2002

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.