⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vc-svn.el

📁 linux subdivision ying gai ke yi le ba
💻 EL
📖 第 1 页 / 共 2 页
字号:
;;;; vc-svn.el --- a VC backend for Subversion
;;;; Jim Blandy <jimb@red-bean.com> --- July 2002

;;; Writing this back end has shown up some problems in VC: bugs,
;;; shortcomings in the back end interface, and so on.  But I want to
;;; first produce code that Subversion users can use with an already
;;; released Emacs distribution.
;;;
;;; So for now we're working within the limitations of the released
;;; VC; once we've got something functional, then we can start writing
;;; VC patches.


;;; To make this file load on demand, put this file into a directory
;;; in `load-path', and add this line to a startup file:
;;;
;;;     (add-to-list 'vc-handled-backends 'SVN)


;;; To do here:
;;; Provide more of the optional VC backend functions: 
;;; - dir-state
;;; - merge across arbitrary revisions
;;;
;;; Maybe we want more info in mode-line-string.  Status of props?  Status 
;;; compared to what's in the repository (svn st -u) ? 
;;;
;;; 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?
;;;
;;; After manual merging, need some way to run `svn resolved'.  Perhaps
;;; we should just prompt for approval when somebody tries to commit a
;;; conflicted file?
;;;
;;; vc-svn ought to handle more gracefully an attempted commit that
;;; fails with "Transaction is out of date".  Probably the best
;;; approach is to ask "file is not up-to-date; do you want to merge
;;; now?"  I think vc-cvs does this.
;;;
;;; Perhaps show the "conflicted" marker in the modeline?
;;;
;;; If conflicted, before committing or merging, ask the user if they
;;; want to mark the file as resolved.
;;;
;;; Won't searching for strings in svn output cause trouble if the
;;; locale language is not English?
;;;
;;; After merging news, need to recheck our idea of which workfile
;;; version we have.  Reverting the file does this but we need to
;;; force it.  Note that this can be necessary even if the file has
;;; not changed.
;;;
;;; Does everything work properly if we're rolled back to an old
;;; revision?
;;;
;;; Perhaps need to implement vc-svn-latest-on-branch-p?


;;; To do in VC:
;;;
;;; Make sure vc's documentation for `workfile-unchanged-p' default
;;; function mentions that it must not run asynchronously, and the
;;; symptoms if it does.
;;; 
;;; Fix logic for finding log entries.
;;;
;;; Allow historical diff to choose an appropriate default previous
;;; revision number.  I think this entails moving vc-previous-revision
;;; et al into the back end.
;;;
;;; Should vc-BACKEND-checkout really have to set the workfile version
;;; itself?
;;;
;;; Fix smerge for svn conflict markers.
;;;
;;; We can have files which are not editable for reasons other than
;;; needing to be checked out.  For example, they might be a read-only
;;; view of an old revision opened with [C-x v ~].  (See vc-merge)
;;;
;;; Would be nice if there was a way to mark a file as
;;; just-checked-out, aside from updating the checkout-time property
;;; which in theory is not to be changed by backends.


(add-to-list 'vc-handled-backends 'SVN)

(defcustom vc-svn-program-name "svn"
  "*Name of Subversion client program, for use by Emacs's VC package."
  :type 'string
  :group 'vc
  :version "21.2.90.2")

(defcustom vc-svn-diff-switches nil
  "*A string or list of strings specifying extra switches for `svn diff' under VC."
  :type '(repeat string)
  :group 'vc
  :version "21.2.90.2")

(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-pop-up-error (&rest args)
  "Pop up the Subversion output buffer, and raise an error with ARGS."
  (pop-to-buffer " *Subversion Output*")
  (goto-char (point-min))
  (shrink-window-if-larger-than-buffer)
  (apply 'error args))


(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

    ;; We should call vc-do-command here, but Subversion exits with an
    ;; error status if FILE isn't under its control, and we want to
    ;; return that as nil, not display it to the user.  We can tell
    ;; vc-do-command to
    
    (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 (equal 0 status)) ; not zerop; status can be a string
          ;; 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")
                  (looking-at "\\(.*\n\\)*.*is not a versioned resource")
                  (looking-at "\\(.*\n\\)*.*: No such file or directory"))
              nil
            ;; Other errors we should actually report to the user.
            (vc-svn-pop-up-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.
Both LOCAL and CHANGED are strings, not numbers.
If we passed `svn status' the `-u' flag, then CHANGED could be a later
revision than LOCAL.
If the file is newly added, LOCAL is \"0\" and CHANGED is nil."
  (let ((state (vc-svn-parse-state-only)))
    (cond
     ((not state) nil)
     ;; A newly added file has no revision.
     ((looking-at "....\\s-+\\(\\*\\s-+\\)?[-0]\\s-+\\?")
      (list state "0" nil))
     ((looking-at "....\\s-+\\(\\*\\s-+\\)?\\([0-9]+\\)\\s-+\\([0-9]+\\)")
      (list state
            (match-string 2)
            (match-string 3)))
     ((looking-at "^I +") nil)       ;; An ignored file
     ((looking-at " \\{40\\}") nil)  ;; A file that is not in the wc nor svn?
     (t (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,
   ;;                     or does not exist.
   ((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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -