cvsdist e1e786
;;; psvn.el --- Subversion interface for emacs
f89e89
;; Copyright (C) 2002-2012 by Stefan Reichoer
cvsdist e1e786
c707a3
;; Author: Stefan Reichoer <stefan@xsteve.at>
f89e89
;; Note: This version is currently not under svn control
f89e89
;; For the revision date see svn-psvn-revision below
cvsdist e1e786
cvsdist e1e786
;; psvn.el is free software; you can redistribute it and/or modify
cvsdist e1e786
;; it under the terms of the GNU General Public License as published by
cvsdist e1e786
;; the Free Software Foundation; either version 2, or (at your option)
cvsdist e1e786
;; any later version.
cvsdist e1e786
cvsdist e1e786
;; psvn.el is distributed in the hope that it will be useful,
cvsdist e1e786
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
cvsdist e1e786
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
cvsdist e1e786
;; GNU General Public License for more details.
cvsdist e1e786
cvsdist e1e786
;; You should have received a copy of the GNU General Public License
cvsdist e1e786
;; along with GNU Emacs; see the file COPYING.  If not, write to
cvsdist e1e786
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
cvsdist e1e786
;; Boston, MA 02111-1307, USA.
cvsdist e1e786
cvsdist e1e786
;;; Commentary
cvsdist e1e786
cvsdist e1e786
;; psvn.el is tested with GNU Emacs 21.3 on windows, debian linux,
d9a7f5
;; freebsd5, red hat el4, ubuntu 11.10 with svn 1.6.12
c707a3
c707a3
;; psvn.el needs at least svn 1.1.0
c707a3
;; if you upgrade to a higher version, you need to do a fresh checkout
cvsdist e1e786
cvsdist e1e786
;; psvn.el is an interface for the revision control tool subversion
cvsdist e1e786
;; (see http://subversion.tigris.org)
cvsdist e1e786
;; psvn.el provides a similar interface for subversion as pcl-cvs for cvs.
cvsdist e1e786
;; At the moment the following commands are implemented:
699a1a
;;
cvsdist e1e786
;; M-x svn-status: run 'svn -status -v'
699a1a
;; M-x svn-examine (like pcl-cvs cvs-examine) is alias for svn-status
699a1a
;;
4b6e5a
;; and show the result in the svn-status-buffer-name buffer (normally: *svn-status*).
4b6e5a
;; If svn-status-verbose is set to nil, only "svn status" without "-v"
4b6e5a
;; is run. Currently you have to toggle this variable manually.
4b6e5a
;; This buffer uses svn-status mode in which the following keys are defined:
cvsdist e1e786
;; g     - svn-status-update:               run 'svn status -v'
4b6e5a
;; M-s   - svn-status-update:               run 'svn status -v'
cvsdist e1e786
;; C-u g - svn-status-update:               run 'svn status -vu'
cvsdist e1e786
;; =     - svn-status-show-svn-diff         run 'svn diff'
cvsdist e1e786
;; l     - svn-status-show-svn-log          run 'svn log'
cvsdist e1e786
;; i     - svn-status-info                  run 'svn info'
cvsdist e1e786
;; r     - svn-status-revert                run 'svn revert'
4b6e5a
;; X v   - svn-status-resolved              run 'svn resolved'
cvsdist e1e786
;; U     - svn-status-update-cmd            run 'svn update'
2e0edb
;; M-u   - svn-status-update-cmd            run 'svn update'
4b6e5a
;; c     - svn-status-commit                run 'svn commit'
cvsdist e1e786
;; a     - svn-status-add-file              run 'svn add --non-recursive'
cvsdist e1e786
;; A     - svn-status-add-file-recursively  run 'svn add'
cvsdist e1e786
;; +     - svn-status-make-directory        run 'svn mkdir'
cvsdist e1e786
;; R     - svn-status-mv                    run 'svn mv'
c707a3
;; C     - svn-status-cp                    run 'svn cp'
1cd9ea
;; D     - svn-status-rm                    run 'svn rm'
cvsdist e1e786
;; M-c   - svn-status-cleanup               run 'svn cleanup'
c707a3
;; k     - svn-status-lock                  run 'svn lock'
c707a3
;; K     - svn-status-unlock                run 'svn unlock'
cvsdist e1e786
;; b     - svn-status-blame                 run 'svn blame'
1cd9ea
;; X e   - svn-status-export                run 'svn export'
cvsdist e1e786
;; RET   - svn-status-find-file-or-examine-directory
cvsdist e1e786
;; ^     - svn-status-examine-parent
cvsdist e1e786
;; ~     - svn-status-get-specific-revision
cvsdist e1e786
;; E     - svn-status-ediff-with-revision
4b6e5a
;; X X   - svn-status-resolve-conflicts
1b1de0
;; S g   - svn-status-grep-files
1b1de0
;; S s   - svn-status-search-files
cvsdist e1e786
;; s     - svn-status-show-process-buffer
c707a3
;; h     - svn-status-pop-to-partner-buffer
cvsdist e1e786
;; e     - svn-status-toggle-edit-cmd-flag
cvsdist e1e786
;; ?     - svn-status-toggle-hide-unknown
cvsdist e1e786
;; _     - svn-status-toggle-hide-unmodified
f41b0b
;; z     - svn-status-toggle-hide-externals
cvsdist e1e786
;; m     - svn-status-set-user-mark
cvsdist e1e786
;; u     - svn-status-unset-user-mark
cvsdist e1e786
;; $     - svn-status-toggle-elide
c707a3
;; w     - svn-status-copy-current-line-info
cvsdist e1e786
;; DEL   - svn-status-unset-user-mark-backwards
cvsdist e1e786
;; * !   - svn-status-unset-all-usermarks
cvsdist e1e786
;; * ?   - svn-status-mark-unknown
cvsdist e1e786
;; * A   - svn-status-mark-added
cvsdist e1e786
;; * M   - svn-status-mark-modified
1b1de0
;; * P   - svn-status-mark-modified-properties
4b6e5a
;; * D   - svn-status-mark-deleted
4b6e5a
;; * *   - svn-status-mark-changed
c707a3
;; * .   - svn-status-mark-by-file-ext
c707a3
;; * %   - svn-status-mark-filename-regexp
1b1de0
;; * s   - svn-status-store-usermarks
1b1de0
;; * l   - svn-status-load-usermarks
cvsdist e1e786
;; .     - svn-status-goto-root-or-return
cvsdist e1e786
;; f     - svn-status-find-file
cvsdist e1e786
;; o     - svn-status-find-file-other-window
c707a3
;; C-o   - svn-status-find-file-other-window-noselect
cvsdist e1e786
;; v     - svn-status-view-file-other-window
cvsdist e1e786
;; I     - svn-status-parse-info
4b6e5a
;; V     - svn-status-svnversion
cvsdist e1e786
;; P l   - svn-status-property-list
cvsdist e1e786
;; P s   - svn-status-property-set
cvsdist e1e786
;; P d   - svn-status-property-delete
cvsdist e1e786
;; P e   - svn-status-property-edit-one-entry
cvsdist e1e786
;; P i   - svn-status-property-ignore-file
cvsdist e1e786
;; P I   - svn-status-property-ignore-file-extension
cvsdist e1e786
;; P C-i - svn-status-property-edit-svn-ignore
f41b0b
;; P X e - svn-status-property-edit-svn-externals
cvsdist e1e786
;; P k   - svn-status-property-set-keyword-list
c707a3
;; P K i - svn-status-property-set-keyword-id
c707a3
;; P K d - svn-status-property-set-keyword-date
cvsdist e1e786
;; P y   - svn-status-property-set-eol-style
4b6e5a
;; P x   - svn-status-property-set-executable
c707a3
;; P m   - svn-status-property-set-mime-type
c707a3
;; H     - svn-status-use-history
c707a3
;; x     - svn-status-update-buffer
cvsdist e1e786
;; q     - svn-status-bury-buffer
cvsdist e1e786
4b6e5a
;; C-x C-j - svn-status-dired-jump
4b6e5a
4b6e5a
;; The output in the buffer contains this header to ease reading
4b6e5a
;; of svn output:
4b6e5a
;;   FPH BASE CMTD Author   em File
4b6e5a
;; F = Filemark
4b6e5a
;; P = Property mark
4b6e5a
;; H = History mark
4b6e5a
;; BASE = local base revision
4b6e5a
;; CMTD = last committed revision
4b6e5a
;; Author = author of change
4b6e5a
;; em = "**" or "(Update Available)" [see `svn-status-short-mod-flag-p']
4b6e5a
;;      if file can be updated
4b6e5a
;; File = path/filename
4b6e5a
;;
4b6e5a
cvsdist e1e786
;; To use psvn.el put the following line in your .emacs:
cvsdist e1e786
;; (require 'psvn)
cvsdist e1e786
;; Start the svn interface with M-x svn-status
cvsdist e1e786
cvsdist e1e786
;; The latest version of psvn.el can be found at:
357017
;;   http://www.xsteve.at/prg/emacs/psvn.el
cvsdist e1e786
cvsdist e1e786
;; TODO:
cvsdist e1e786
;; * shortcut for svn propset svn:keywords "Date" psvn.el
cvsdist e1e786
;; * docstrings for the functions
cvsdist e1e786
;; * perhaps shortcuts for ranges, dates
cvsdist e1e786
;; * when editing the command line - offer help from the svn client
cvsdist e1e786
;; * finish svn-status-property-set
cvsdist e1e786
;; * Add repository browser
1cd9ea
;; * Get rid of all byte-compiler warnings
1cd9ea
;; * SVK working copy support
1cd9ea
;; * multiple independent buffers in svn-status-mode
1cd9ea
;; There are "TODO" comments in other parts of this file as well.
cvsdist e1e786
cvsdist e1e786
;; Overview over the implemented/not (yet) implemented svn sub-commands:
cvsdist e1e786
;; * add                       implemented
cvsdist e1e786
;; * blame                     implemented
cvsdist e1e786
;; * cat                       implemented
c707a3
;; * checkout (co)             implemented
cvsdist e1e786
;; * cleanup                   implemented
cvsdist e1e786
;; * commit (ci)               implemented
c707a3
;; * copy (cp)                 implemented
cvsdist e1e786
;; * delete (del, remove, rm)  implemented
cvsdist e1e786
;; * diff (di)                 implemented
1cd9ea
;; * export                    implemented
cvsdist e1e786
;; * help (?, h)
c707a3
;; * import                    used         (in svn-admin-create-trunk-directory)
cvsdist e1e786
;; * info                      implemented
699a1a
;; * list (ls)                 implemented
c707a3
;; * lock                      implemented
cvsdist e1e786
;; * log                       implemented
cvsdist e1e786
;; * merge
cvsdist e1e786
;; * mkdir                     implemented
cvsdist e1e786
;; * move (mv, rename, ren)    implemented
cvsdist e1e786
;; * propdel (pdel)            implemented
cvsdist e1e786
;; * propedit (pedit, pe)      not needed
c707a3
;; * propget (pget, pg)        used         (in svn-status-property-edit)
cvsdist e1e786
;; * proplist (plist, pl)      implemented
c707a3
;; * propset (pset, ps)        used         (in svn-prop-edit-do-it)
cvsdist e1e786
;; * resolved                  implemented
cvsdist e1e786
;; * revert                    implemented
cvsdist e1e786
;; * status (stat, st)         implemented
cvsdist e1e786
;; * switch (sw)
c707a3
;; * unlock                    implemented
cvsdist e1e786
;; * update (up)               implemented
cvsdist e1e786
cvsdist e1e786
;; For the not yet implemented commands you should use the command line
cvsdist e1e786
;; svn client. If there are user requests for any missing commands I will
cvsdist e1e786
;; probably implement them.
cvsdist e1e786
c707a3
;; There is also limited support for the web-based software project management and bug/issue tracking system trac
c707a3
;; Trac ticket links can be enabled in the *svn-log* buffers when using the following:
c707a3
;; (setq svn-log-link-handlers '(trac-ticket-short))
c707a3
1b1de0
;; ---------------------------
1b1de0
;; Frequently asked questions:
1b1de0
;; ---------------------------
1b1de0
1b1de0
;; Q1: I need support for user names with blanks/spaces
1b1de0
;; A1: Add the user names to svn-user-names-including-blanks and set the
1b1de0
;;     svn-pre-parse-status-hook.
1b1de0
;;     The problem is, that the user names and the file names from the svn status
1b1de0
;;     output can both contain blanks. Blanks in file names are supported.
1b1de0
;;     the svn-user-names-including-blanks list is used to replace the spaces
1b1de0
;;     in the user names with - to overcome this problem
1b1de0
1b1de0
;; Q2: My svn-update command it taking a really long time. How can I
1b1de0
;;     see what's going on?
1b1de0
;; A2: In the *svn-status* buffer press "s".
1b1de0
1b1de0
;; Q3: How do I enter a username and password?
1b1de0
;; A3: In the *svn-status* buffer press "s", switch to the
1b1de0
;;     *svn-process* buffer and press enter. You will be prompted for
1b1de0
;;     username and password.
1b1de0
1b1de0
;; Q4: What does "?", "M", and "C" in the first column of the
1b1de0
;;     *svn-status* buffer mean?
1b1de0
;; A4: "?" means the file(s) is not under Subversion control
1b1de0
;;     "M" means you have a locally modified file
1b1de0
;;     "C" means there is a conflict
1b1de0
;;     "@$&#!" means someone is saying nasty things to you
1b1de0
1b1de0
cvsdist e1e786
;; Comments / suggestions and bug reports are welcome!
cvsdist e1e786
1cd9ea
;; Development notes
1cd9ea
;; -----------------
1cd9ea
1cd9ea
;; "svn-" is the package prefix used in psvn.el.  There are also longer
1cd9ea
;; prefixes which clarify the code and help symbol completion, but they
1cd9ea
;; are not intended to prevent name clashes with other packages.  All
1cd9ea
;; interactive commands meant to be used only in a specific mode should
1cd9ea
;; have names beginning with the name of that mode: for example,
1cd9ea
;; "svn-status-add-file" in "svn-status-mode".  "psvn" should be used
1cd9ea
;; only in names of files, customization groups, and features.  If SVK
1cd9ea
;; support is ever added, it should use "svn-svk-" when no existing
1cd9ea
;; prefix is applicable.
1cd9ea
1cd9ea
;; Many of the variables marked as `risky-local-variable' are probably
1cd9ea
;; impossible to abuse, as the commands that read them are used only in
1cd9ea
;; buffers that are not visiting any files.  Better safe than sorry.
1cd9ea
cvsdist e1e786
;;; Code:
cvsdist e1e786
d9a7f5
(defconst svn-psvn-revision "2012-03-26, 21:23:49" "The revision date of psvn.")
f89e89
f89e89
4b6e5a
(require 'easymenu)
a73eb4
c707a3
(eval-when-compile (require 'dired))
c707a3
(eval-when-compile (require 'ediff-util))
1b1de0
(eval-when-compile (require 'ediff-wind))
f41b0b
(eval-when-compile (require 'vc-hooks))
c707a3
(eval-when-compile (require 'elp))
c707a3
(eval-when-compile (require 'pp))
c707a3
a73eb4
(condition-case nil
a73eb4
    (progn
a73eb4
      (require 'diff-mode))
a73eb4
  (error nil))
4b6e5a
699a1a
cvsdist e1e786
;;; user setable variables
2e0edb
(defcustom svn-status-verbose t
c707a3
  "*Add '-v' to svn status call.
c707a3
This can be toggled with \\[svn-status-toggle-svn-verbose-flag]."
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
2e0edb
(defcustom svn-log-edit-file-name "++svn-log++"
2e0edb
  "*Name of a saved log file.
2e0edb
This can be either absolute, or relative to the default directory
c707a3
of the `svn-log-edit-buffer-name' buffer."
2e0edb
  :type 'file
2e0edb
  :group 'psvn)
1cd9ea
(put 'svn-log-edit-file-name 'risky-local-variable t)
2e0edb
(defcustom svn-log-edit-insert-files-to-commit t
2e0edb
  "*Insert the filelist to commit in the *svn-log* buffer"
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
1b1de0
(defcustom svn-log-edit-show-diff-for-commit nil
1b1de0
  "*Show the diff being committed when you run `svn-status-commit.'."
1b1de0
  :type 'boolean
1b1de0
  :group 'psvn)
2e0edb
(defcustom svn-log-edit-use-log-edit-mode
2e0edb
  (and (condition-case nil (require 'log-edit) (error nil)) t)
2e0edb
  "*Use log-edit-mode as base for svn-log-edit-mode
2e0edb
This variable takes effect only when psvn.el is being loaded."
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
c707a3
(defcustom svn-log-edit-paragraph-start
c707a3
  "$\\|[ \t]*$\\|##.*$\\|\\*.*:.*$\\|[ \t]+(.+):.*$"
c707a3
  "*Value used for `paragraph-start' in `svn-log-edit-buffer-name' buffer."
c707a3
  :type 'regexp
c707a3
  :group 'psvn)
c707a3
(defcustom svn-log-edit-paragraph-separate "$\\|##.*$"
c707a3
  "*Value used for `paragraph-separate' in `svn-log-edit-buffer-name' buffer."
c707a3
  :type 'regexp
c707a3
  :group 'psvn)
2e0edb
(defcustom svn-status-hide-unknown nil
4b6e5a
  "*Hide unknown files in `svn-status-buffer-name' buffer.
2e0edb
This can be toggled with \\[svn-status-toggle-hide-unknown]."
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
2e0edb
(defcustom svn-status-hide-unmodified nil
4b6e5a
  "*Hide unmodified files in `svn-status-buffer-name' buffer.
2e0edb
This can be toggled with \\[svn-status-toggle-hide-unmodified]."
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
f41b0b
(defcustom svn-status-hide-externals nil
f41b0b
  "*Hide external files in `svn-status-buffer-name' buffer.
f41b0b
This can be toggled with \\[svn-status-toggle-hide-externals]."
f41b0b
  :type 'boolean
f41b0b
  :group 'psvn)
2e0edb
(defcustom svn-status-sort-status-buffer t
a73eb4
  "*Whether to sort the `svn-status-buffer-name' buffer.
a73eb4
c707a3
Setting this variable to nil speeds up \\[M-x svn-status], however the
a73eb4
listing may then become incorrect.
a73eb4
2e0edb
This can be toggled with \\[svn-status-toggle-sort-status-buffer]."
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
cvsdist e1e786
c707a3
(defcustom svn-status-ediff-delete-temporary-files nil
c707a3
  "*Whether to delete temporary ediff files. If set to ask, ask the user"
c707a3
  :type '(choice (const t)
c707a3
                 (const nil)
c707a3
                 (const ask))
c707a3
  :group 'psvn)
c707a3
c707a3
(defcustom svn-status-changelog-style 'changelog
c707a3
  "*The changelog style that is used for `svn-file-add-to-changelog'.
c707a3
Possible values are:
c707a3
 'changelog: use `add-change-log-entry-other-window'
c707a3
 'svn-dev: use commit messages that are used by the svn developers
c707a3
 a function: This function is called to add a new entry to the changelog file.
c707a3
"
c707a3
  :type '(set (const changelog)
c707a3
              (const svn-dev))
c707a3
  :group 'psvn)
c707a3
2e0edb
(defcustom svn-status-unmark-files-after-list '(commit revert)
cvsdist e1e786
  "*List of operations after which all user marks will be removed.
2e0edb
Possible values are: commit, revert."
2e0edb
  :type '(set (const commit)
2e0edb
              (const revert))
2e0edb
  :group 'psvn)
cvsdist e1e786
c707a3
(defcustom svn-status-preserve-window-configuration t
1cd9ea
  "*Try to preserve the window configuration."
1cd9ea
  :type 'boolean
1cd9ea
  :group 'psvn)
1cd9ea
c707a3
(defcustom svn-status-auto-revert-buffers t
c707a3
  "*Auto revert buffers that have changed on disk."
c707a3
  :type 'boolean
c707a3
  :group 'psvn)
c707a3
1b1de0
(defcustom svn-status-fancy-file-state-in-modeline t
1b1de0
  "*Show a color dot in the modeline that describes the state of the current file."
1b1de0
  :type 'boolean
1b1de0
  :group 'psvn)
1b1de0
f89e89
(defcustom svn-status-indentation 2
f89e89
  "*Indenation per directory level in the `svn-status-buffer-name' buffer."
f89e89
  :type 'integer
f89e89
  :group 'psvn)
f89e89
2e0edb
(defcustom svn-status-negate-meaning-of-arg-commands '()
4b6e5a
  "*List of operations that should use a negated meaning of the prefix argument.
2e0edb
The supported functions are `svn-status' and `svn-status-set-user-mark'."
2e0edb
  :type '(set (function-item svn-status)
2e0edb
              (function-item svn-status-set-user-mark))
2e0edb
  :group 'psvn)
4b6e5a
2e0edb
(defcustom svn-status-svn-executable "svn"
2e0edb
  "*The name of the svn executable.
2e0edb
This can be either absolute or looked up on `exec-path'."
2e0edb
  ;; Don't use (file :must-match t).  It doesn't know about `exec-path'.
2e0edb
  :type 'file
2e0edb
  :group 'psvn)
1cd9ea
(put 'svn-status-svn-executable 'risky-local-variable t)
1cd9ea
1cd9ea
(defcustom svn-status-default-export-directory "~/" "*The default directory that is suggested svn export."
1cd9ea
  :type 'file
1cd9ea
  :group 'psvn)
4b6e5a
c707a3
(defcustom svn-status-svn-environment-var-list '("LC_MESSAGES=C" "LC_ALL=")
4b6e5a
  "*A list of environment variables that should be set for that svn process.
1cd9ea
Each element is either a string \"VARIABLE=VALUE\" which will be added to
1cd9ea
the environment when svn is run, or just \"VARIABLE\" which causes that
1cd9ea
variable to be entirely removed from the environment.
4b6e5a
c707a3
The default setting is '(\"LC_MESSAGES=C\" \"LC_ALL=\"). This ensures that the svn command
c707a3
line client does not output localized strings. psvn.el relies on the english
c707a3
messages."
1cd9ea
  :type '(repeat string)
2e0edb
  :group 'psvn)
1cd9ea
(put 'svn-status-svn-environment-var-list 'risky-local-variable t)
4b6e5a
2e0edb
(defcustom svn-browse-url-function nil
4b6e5a
  ;; If the user hasn't changed `svn-browse-url-function', then changing
4b6e5a
  ;; `browse-url-browser-function' should affect psvn even after it has
4b6e5a
  ;; been loaded.
4b6e5a
  "Function to display a Subversion related WWW page in a browser.
4b6e5a
So far, this is used only for \"trac\" issue tracker integration.
4b6e5a
By default, this is nil, which means use `browse-url-browser-function'.
2e0edb
Any non-nil value overrides that variable, with the same syntax."
2e0edb
  ;; It would be nice to show the full list of browsers supported by
2e0edb
  ;; browse-url, but (custom-variable-type 'browse-url-browser-function)
2e0edb
  ;; returns just `function' if browse-url has not yet been loaded,
2e0edb
  ;; and there seems to be no easy way to autoload browse-url when
2e0edb
  ;; the custom-type of svn-browse-url-function is actually needed.
2e0edb
  ;; So I'll only offer enough choices to cover all supported types.
2e0edb
  :type `(choice (const :tag "Specified by `browse-url-browser-function'" nil)
2e0edb
                 (function :value browse-url-default-browser
2e0edb
                           ;; In XEmacs 21.4.17, the `function' widget matches
2e0edb
                           ;; all objects.  Constrain it here so that alists
2e0edb
                           ;; fall through to the next choice.  Accept either
2e0edb
                           ;; a symbol (fbound or not) or a lambda expression.
2e0edb
                           :match ,(lambda (widget value)
2e0edb
                                     (or (symbolp value) (functionp value))))
2e0edb
                 (svn-alist :tag "Regexp/function association list"
2e0edb
                            :key-type regexp :value-type function
2e0edb
                            :value (("." . browse-url-default-browser))))
2e0edb
  :link '(emacs-commentary-link "browse-url")
2e0edb
  :group 'psvn)
1cd9ea
;; (put 'svn-browse-url-function 'risky-local-variable t)
1cd9ea
;; already implied by "-function" suffix
4b6e5a
f41b0b
(defcustom svn-log-edit-header
f41b0b
  "## Lines starting with '## ' will be removed from the log message.\n"
f41b0b
  "*Header content of the *svn-log* buffer"
f41b0b
  :type 'string
f41b0b
  :group 'psvn)
f41b0b
2e0edb
(defcustom svn-status-window-alist
4b6e5a
  '((diff "*svn-diff*") (log "*svn-log*") (info t) (blame t) (proplist t) (update t))
4b6e5a
  "An alist to specify which windows should be used for svn command outputs.
4b6e5a
The following keys are supported: diff, log, info, blame, proplist, update.
4b6e5a
The following values can be given:
c707a3
nil       ... show in `svn-process-buffer-name' buffer
4b6e5a
t         ... show in dedicated *svn-info* buffer
4b6e5a
invisible ... don't show the buffer (eventually useful for update)
2e0edb
a string  ... show in a buffer named string"
2e0edb
  :type '(svn-alist
2e0edb
          :key-type symbol
2e0edb
          :value-type (group
2e0edb
                       (choice
2e0edb
                        (const :tag "Show in *svn-process* buffer" nil)
2e0edb
                        (const :tag "Show in dedicated *svn-info* buffer" t)
2e0edb
                        (const :tag "Don't show the output" invisible)
2e0edb
                        (string :tag "Show in a buffer named"))))
2e0edb
  :options '(diff log info blame proplist update)
2e0edb
  :group 'psvn)
4b6e5a
2e0edb
(defcustom svn-status-short-mod-flag-p t
4b6e5a
  "*Whether the mark for out of date files is short or long.
4b6e5a
4b6e5a
If this variable is is t, and a file is out of date (i.e., there is a newer
4b6e5a
version in the repository than the working copy), then the file will
4b6e5a
be marked by \"**\"
4b6e5a
4b6e5a
If this variable is nil, and the file is out of date then the longer phrase
4b6e5a
\"(Update Available)\" is used.
4b6e5a
4b6e5a
In either case the mark gets the face
4b6e5a
`svn-status-update-available-face', and will only be visible if
2e0edb
`\\[svn-status-update]' is run with a prefix argument"
2e0edb
  :type '(choice (const :tag "Short \"**\"" t)
2e0edb
                 (const :tag "Long \"(Update Available)\"" nil))
2e0edb
  :group 'psvn)
4b6e5a
4b6e5a
(defvar svn-status-debug-level 0 "The psvn.el debugging verbosity level.
4b6e5a
The higher the number, the more debug messages are shown.
4b6e5a
4b6e5a
See `svn-status-message' for the meaning of values for that variable.")
4b6e5a
c707a3
(defvar svn-bookmark-list nil "A list of locations for a quick access via `svn-status-via-bookmark'")
c707a3
;;(setq svn-bookmark-list '(("proj1" . "~/work/proj1")
c707a3
;;                          ("doc1" . "~/docs/doc1")))
c707a3
4b6e5a
(defvar svn-status-buffer-name "*svn-status*" "Name for the svn status buffer")
c707a3
(defvar svn-process-buffer-name " *svn-process*" "Name for the svn process buffer")
c707a3
(defvar svn-log-edit-buffer-name "*svn-log-edit*" "Name for the svn log-edit buffer")
4b6e5a
2e0edb
(defcustom svn-status-use-header-line
2e0edb
  (if (boundp 'header-line-format) t 'inline)
4b6e5a
  "*Whether a header line should be used.
4b6e5a
When t: Use the emacs header line
4b6e5a
When 'inline: Insert the header line in the `svn-status-buffer-name' buffer
2e0edb
Otherwise: Don't display a header line"
2e0edb
  :type '(choice (const :tag "Show column titles as a header line" t)
2e0edb
                 (const :tag "Insert column titles as text in the buffer" inline)
2e0edb
                 (other :tag "No column titles" nil))
2e0edb
  :group 'psvn)
4b6e5a
cvsdist e1e786
;;; default arguments to pass to svn commands
2e0edb
;; TODO: When customizing, an option menu or completion might be nice....
c707a3
(defcustom svn-status-default-log-arguments '("-v")
2e0edb
  "*List of arguments to pass to svn log.
2e0edb
\(used in `svn-status-show-svn-log'; override these by giving prefixes\)."
2e0edb
  :type '(repeat string)
2e0edb
  :group 'psvn)
1cd9ea
(put 'svn-status-default-log-arguments 'risky-local-variable t)
2e0edb
2e0edb
(defcustom svn-status-default-commit-arguments '()
2e0edb
  "*List of arguments to pass to svn commit.
2e0edb
If you don't like recursive commits, set this value to (\"-N\")
2e0edb
or mark the directory before committing it.
2e0edb
Do not put an empty string here, except as an argument of an option:
2e0edb
Subversion and the operating system may treat that as a file name
2e0edb
equivalent to \".\", so you would commit more than you intended."
2e0edb
  :type '(repeat string)
2e0edb
  :group 'psvn)
1cd9ea
(put 'svn-status-default-commit-arguments 'risky-local-variable t)
cvsdist e1e786
c707a3
(defcustom svn-status-default-diff-arguments '("-x" "--ignore-eol-style")
4b6e5a
  "*A list of arguments that is passed to the svn diff command.
c707a3
When the built in diff command is used,
c707a3
the following options are available: --ignore-eol-style, --ignore-space-change,
c707a3
--ignore-all-space, --ignore-eol-style.
c707a3
The following setting ignores eol style changes and all white space changes:
c707a3
'(\"-x\" \"--ignore-eol-style --ignore-all-space\")
c707a3
c707a3
If you'd like to suppress whitespace changes using the external diff command
c707a3
use the following value:
c707a3
'(\"--diff-cmd\" \"diff\" \"-x\" \"-wbBu\")
c707a3
c707a3
"
2e0edb
  :type '(repeat string)
2e0edb
  :group 'psvn)
1cd9ea
(put 'svn-status-default-diff-arguments 'risky-local-variable t)
4b6e5a
1b1de0
(defcustom svn-status-default-status-arguments '()
1b1de0
  "*A list of arguments that is passed to the svn status command.
1b1de0
The following options are available: --ignore-externals
1b1de0
1b1de0
"
1b1de0
  :type '(repeat string)
1b1de0
  :group 'psvn)
1b1de0
(put 'svn-status-default-status-arguments 'risky-local-variable t)
1b1de0
c707a3
(defcustom svn-status-default-blame-arguments '("-x" "--ignore-eol-style")
c707a3
  "*A list of arguments that is passed to the svn blame command.
1b1de0
See `svn-status-default-diff-arguments' for some examples."
1b1de0
  :type '(repeat string)
1b1de0
  :group 'psvn)
1b1de0
c707a3
(put 'svn-status-default-blame-arguments 'risky-local-variable t)
c707a3
2e0edb
(defvar svn-trac-project-root nil
2e0edb
  "Path for an eventual existing trac issue tracker.
2e0edb
This can be set with \\[svn-status-set-trac-project-root].")
4b6e5a
2e0edb
(defvar svn-status-module-name nil
a73eb4
  "*A short name for the actual project.
2e0edb
This can be set with \\[svn-status-set-module-name].")
4b6e5a
c707a3
(defvar svn-status-branch-list nil
c707a3
  "*A list of known branches for the actual project
c707a3
This can be set with \\[svn-status-set-branch-list].
c707a3
c707a3
The list contains full repository paths or shortcuts starting with \#
c707a3
\# at the beginning is replaced by the repository url.
c707a3
\#1\# has the special meaning that all paths below the given directory
c707a3
will be considered for interactive selections.
c707a3
c707a3
A useful setting might be: '\(\"\#trunk\" \"\#1\#tags\" \"\#1\#branches\")")
c707a3
a73eb4
(defvar svn-status-load-state-before-svn-status t
a73eb4
  "*Whether to automatically restore state from ++psvn.state file before running svn-status.")
4b6e5a
c707a3
(defvar svn-log-link-handlers nil "A list of link handlers in *svn-log* buffers.
c707a3
These link handlers must be registered via `svn-log-register-link-handler'")
c707a3
cvsdist e1e786
;;; hooks
c707a3
(defvar svn-status-mode-hook nil "Hook run when entering `svn-status-mode'.")
cvsdist e1e786
(defvar svn-log-edit-mode-hook nil "Hook run when entering `svn-log-edit-mode'.")
4b6e5a
(defvar svn-log-edit-done-hook nil "Hook run after commiting files via svn.")
1cd9ea
;; (put 'svn-log-edit-mode-hook 'risky-local-variable t)
1cd9ea
;; (put 'svn-log-edit-done-hook 'risky-local-variable t)
1cd9ea
;; already implied by "-hook" suffix
4b6e5a
f41b0b
(defvar svn-post-process-svn-output-hook 'svn-fixup-tramp-output-maybe "Hook that can be used to preprocess the output from svn.
c707a3
The function `svn-status-remove-control-M' can be useful for that hook")
c707a3
c707a3
(when (eq system-type 'windows-nt)
c707a3
  (add-hook 'svn-post-process-svn-output-hook 'svn-status-remove-control-M))
c707a3
c707a3
(defvar svn-status-svn-process-coding-system (when (boundp 'locale-coding-system) locale-coding-system)
c707a3
  "The coding system that is used for the svn command line client.
c707a3
It is used in svn-run, if it is not nil.")
cvsdist e1e786
c707a3
(defvar svn-status-svn-file-coding-system 'undecided-unix
c707a3
  "The coding system that is used to save files that are loaded as
c707a3
parameter or data files via the svn command line client.
c707a3
It is used in the following functions: `svn-prop-edit-do-it', `svn-log-edit-done'.
c707a3
You could set it to 'utf-8")
c707a3
c707a3
(defcustom svn-status-use-ido-completion
c707a3
  (fboundp 'ido-completing-read)
c707a3
  "*Use ido completion functionality."
2e0edb
  :type 'boolean
2e0edb
  :group 'psvn)
cvsdist e1e786
c707a3
(defvar svn-status-completing-read-function
c707a3
  (if svn-status-use-ido-completion 'ido-completing-read 'completing-read))
c707a3
4b6e5a
;;; experimental features
4b6e5a
(defvar svn-status-track-user-input nil "Track user/password queries.
4b6e5a
This feature is implemented via a process filter.
4b6e5a
It is an experimental feature.")
4b6e5a
c707a3
(defvar svn-status-refresh-info nil "Whether `svn-status-update-buffer' should call `svn-status-parse-info'.")
c707a3
cvsdist e1e786
;;; Customize group
cvsdist e1e786
(defgroup psvn nil
cvsdist e1e786
  "Subversion interface for Emacs."
cvsdist e1e786
  :group 'tools)
cvsdist e1e786
cvsdist e1e786
(defgroup psvn-faces nil
cvsdist e1e786
  "psvn faces."
cvsdist e1e786
  :group 'psvn)
cvsdist e1e786
cvsdist e1e786
cvsdist e1e786
(eval-and-compile
cvsdist e1e786
  (require 'cl)
cvsdist e1e786
  (defconst svn-xemacsp (featurep 'xemacs))
cvsdist e1e786
  (if svn-xemacsp
cvsdist e1e786
      (require 'overlay)
cvsdist e1e786
    (require 'overlay nil t)))
cvsdist e1e786
4b6e5a
(defcustom svn-status-display-full-path nil
4b6e5a
  "Specifies how the filenames look like in the listing.
4b6e5a
If t, their full path name will be displayed, else only the filename."
4b6e5a
  :type 'boolean
4b6e5a
  :group 'psvn)
4b6e5a
4b6e5a
(defcustom svn-status-prefix-key [(control x) (meta s)]
4b6e5a
  "Prefix key for the psvn commands in the global keymap."
4b6e5a
  :type '(choice (const [(control x) ?v ?S])
4b6e5a
                 (const [(super s)])
4b6e5a
                 (const [(hyper s)])
4b6e5a
                 (const [(control x) ?v])
4b6e5a
                 (const [(control x) ?V])
4b6e5a
                 (sexp))
4b6e5a
  :group 'psvn
4b6e5a
  :set  (lambda (var value)
4b6e5a
          (if (boundp var)
4b6e5a
              (global-unset-key (symbol-value var)))
4b6e5a
          (set var value)
4b6e5a
          (global-set-key (symbol-value var) 'svn-global-keymap)))
4b6e5a
c707a3
(defcustom svn-admin-default-create-directory "~/"
c707a3
  "*The default directory that is suggested for `svn-admin-create'."
c707a3
  :type 'string
c707a3
  :group 'psvn)
c707a3
c707a3
(defvar svn-status-custom-hide-function nil
c707a3
  "A function that receives a line-info and decides whether to hide that line.
c707a3
See psvn.el for an example function.")
c707a3
;; (put 'svn-status-custom-hide-function 'risky-local-variable t)
c707a3
;; already implied by "-function" suffix
c707a3
c707a3
cvsdist e1e786
;; Use the normally used mode for files ending in .~HEAD~, .~BASE~, ...
cvsdist e1e786
(add-to-list 'auto-mode-alist '("\\.~?\\(HEAD\\|BASE\\|PREV\\)~?\\'" ignore t))
cvsdist e1e786
cvsdist e1e786
;;; internal variables
4b6e5a
(defvar svn-status-directory-history nil "List of visited svn working directories.")
cvsdist e1e786
(defvar svn-process-cmd nil)
cvsdist e1e786
(defvar svn-status-info nil)
4b6e5a
(defvar svn-status-filename-to-buffer-position-cache (make-hash-table :test 'equal :weakness t))
699a1a
(defvar svn-status-base-info nil "The parsed result from the svn info command.")
cvsdist e1e786
(defvar svn-status-initial-window-configuration nil)
cvsdist e1e786
(defvar svn-status-default-column 23)
cvsdist e1e786
(defvar svn-status-default-revision-width 4)
cvsdist e1e786
(defvar svn-status-default-author-width 9)
4b6e5a
(defvar svn-status-line-format " %c%c%c %4s %4s %-9s")
cvsdist e1e786
(defvar svn-start-of-file-list-line-number 0)
2e0edb
(defvar svn-status-files-to-commit nil
2e0edb
  "List of files to commit at `svn-log-edit-done'.
2e0edb
This is always set together with `svn-status-recursive-commit'.")
2e0edb
(defvar svn-status-recursive-commit nil
2e0edb
  "Non-nil if the next commit should be recursive.
2e0edb
This is always set together with `svn-status-files-to-commit'.")
1cd9ea
(defvar svn-log-edit-update-log-entry nil
1cd9ea
  "Revision number whose log entry is being edited.
1cd9ea
This is nil if the log entry is for a new commit.")
cvsdist e1e786
(defvar svn-status-pre-commit-window-configuration nil)
cvsdist e1e786
(defvar svn-status-pre-propedit-window-configuration nil)
cvsdist e1e786
(defvar svn-status-head-revision nil)
cvsdist e1e786
(defvar svn-status-root-return-info nil)
cvsdist e1e786
(defvar svn-status-property-edit-must-match-flag nil)
c707a3
(defvar svn-status-propedit-property-name nil "The property name for the actual svn propset command")
cvsdist e1e786
(defvar svn-status-propedit-file-list nil)
cvsdist e1e786
(defvar svn-status-mode-line-process "")
cvsdist e1e786
(defvar svn-status-mode-line-process-status "")
cvsdist e1e786
(defvar svn-status-mode-line-process-edit-flag "")
cvsdist e1e786
(defvar svn-status-edit-svn-command nil)
cvsdist e1e786
(defvar svn-status-update-previous-process-output nil)
a73eb4
(defvar svn-pre-run-asynch-recent-keys nil)
c707a3
(defvar svn-pre-run-mode-line-process nil)
d9a7f5
(defvar svn-arg-file-content nil)
cvsdist e1e786
(defvar svn-status-temp-dir
4b6e5a
  (expand-file-name
4b6e5a
   (or
4b6e5a
    (when (boundp 'temporary-file-directory) temporary-file-directory) ;emacs
1cd9ea
    ;; XEmacs 21.4.17 can return "/tmp/kalle" from (temp-directory).
1cd9ea
    ;; `file-name-as-directory' adds a slash so we can append a file name.
1cd9ea
    (when (fboundp 'temp-directory) (file-name-as-directory (temp-directory)))
4b6e5a
    "/tmp/")) "The directory that is used to store temporary files for psvn.")
1cd9ea
;; Because `temporary-file-directory' is not a risky local variable in
1cd9ea
;; GNU Emacs 22.0.51, we don't mark `svn-status-temp-dir' as such either.
cvsdist e1e786
(defvar svn-temp-suffix (make-temp-name "."))
1cd9ea
(put 'svn-temp-suffix 'risky-local-variable t)
cvsdist e1e786
(defvar svn-status-temp-file-to-remove nil)
1cd9ea
(put 'svn-status-temp-file-to-remove 'risky-local-variable t)
cvsdist e1e786
(defvar svn-status-temp-arg-file (concat svn-status-temp-dir "svn.arg" svn-temp-suffix))
1cd9ea
(put 'svn-status-temp-arg-file 'risky-local-variable t)
357017
(defvar svn-status-options nil)
1cd9ea
(defvar svn-status-remote)
4b6e5a
(defvar svn-status-commit-rev-number nil)
c707a3
(defvar svn-status-update-rev-number nil)
4b6e5a
(defvar svn-status-operated-on-dot nil)
c707a3
(defvar svn-status-last-commit-author nil)
4b6e5a
(defvar svn-status-elided-list nil)
c707a3
(defvar svn-status-last-output-buffer-name nil "The buffer name for the buffer that holds the output from the last executed svn command")
699a1a
(defvar svn-status-pre-run-svn-buffer nil)
699a1a
(defvar svn-status-update-list nil)
1cd9ea
(defvar svn-transient-buffers)
1cd9ea
(defvar svn-ediff-windows)
1cd9ea
(defvar svn-ediff-result)
c707a3
(defvar svn-status-last-diff-options nil)
c707a3
(defvar svn-status-blame-file-name nil)
1b1de0
(defvar svn-status-blame-revision nil)
c707a3
(defvar svn-admin-last-repository-dir nil "The last repository url for various operations.")
c707a3
(defvar svn-last-cmd-ring (make-ring 30) "Ring that holds the last executed svn commands (for debugging purposes)")
c707a3
(defvar svn-status-cached-version-string nil)
c707a3
(defvar svn-client-version nil "The version number of the used svn client")
c707a3
(defvar svn-status-get-line-information-for-file nil)
c707a3
(defvar svn-status-base-dir-cache (make-hash-table :test 'equal :weakness nil))
1b1de0
(defvar svn-status-usermark-storage (make-hash-table :test 'equal :weakness nil))
c707a3
(defvar svn-log-registered-link-handlers (make-hash-table :test 'eql :weakness nil))
c707a3
c707a3
(defvar svn-status-partner-buffer nil "The partner buffer for this svn related buffer")
c707a3
(make-variable-buffer-local 'svn-status-partner-buffer)
1cd9ea
1cd9ea
;; Emacs 21 defines these in ediff-init.el but it seems more robust
1cd9ea
;; to just declare the variables here than try to load that file.
1cd9ea
;; It is Ediff's job to declare these as risky-local-variable if needed.
1cd9ea
(defvar ediff-buffer-A)
1cd9ea
(defvar ediff-buffer-B)
1cd9ea
(defvar ediff-buffer-C)
1cd9ea
(defvar ediff-quit-hook)
1cd9ea
1cd9ea
;; Ditto for log-edit.el.
1cd9ea
(defvar log-edit-initial-files)
1cd9ea
(defvar log-edit-callback)
1cd9ea
(defvar log-edit-listfun)
1cd9ea
1cd9ea
;; Ediff does not use this variable in GNU Emacs 20.7, GNU Emacs 21.4,
1cd9ea
;; nor XEmacs 21.4.17.  However, pcl-cvs (a.k.a. pcvs) does.
1cd9ea
;; TODO: Check if this should be moved into the "svn-" namespace.
1cd9ea
(defvar ediff-after-quit-destination-buffer)
4b6e5a
4b6e5a
;; That is an example for the svn-status-custom-hide-function:
c707a3
;; Note: For many cases it is a better solution to ignore files or
c707a3
;; file extensions via the svn-ignore properties (on P i, P I)
4b6e5a
;; (setq svn-status-custom-hide-function 'svn-status-hide-pyc-files)
4b6e5a
;; (defun svn-status-hide-pyc-files (info)
4b6e5a
;;   "Hide all pyc files in the `svn-status-buffer-name' buffer."
4b6e5a
;;   (let* ((fname (svn-status-line-info->filename-nondirectory info))
4b6e5a
;;          (fname-len (length fname)))
4b6e5a
;;     (and (> fname-len 4) (string= (substring fname (- fname-len 4)) ".pyc"))))
cvsdist e1e786
cvsdist e1e786
;;; faces
cvsdist e1e786
(defface svn-status-marked-face
cvsdist e1e786
  '((((type tty) (class color)) (:foreground "green" :weight light))
cvsdist e1e786
    (((class color) (background light)) (:foreground "green3"))
cvsdist e1e786
    (((class color) (background dark)) (:foreground "palegreen2"))
cvsdist e1e786
    (t (:weight bold)))
cvsdist e1e786
  "Face to highlight the mark for user marked files in svn status buffers."
cvsdist e1e786
  :group 'psvn-faces)
cvsdist e1e786
4b6e5a
(defface svn-status-marked-popup-face
4b6e5a
  '((((type tty) (class color)) (:foreground "green" :weight light))
4b6e5a
    (((class color) (background light)) (:foreground "green3"))
4b6e5a
    (((class color) (background dark)) (:foreground "palegreen2"))
4b6e5a
    (t (:weight bold)))
4b6e5a
  "Face to highlight the actual file, if a popup menu is activated."
4b6e5a
  :group 'psvn-faces)
4b6e5a
4b6e5a
(defface svn-status-update-available-face
cvsdist e1e786
  '((((type tty) (class color)) (:foreground "magenta" :weight light))
cvsdist e1e786
    (((class color) (background light)) (:foreground "magenta"))
cvsdist e1e786
    (((class color) (background dark)) (:foreground "yellow"))
cvsdist e1e786
    (t (:weight bold)))
4b6e5a
  "Face used to highlight the 'out of date' mark.
4b6e5a
\(i.e., the mark used when there is a newer version in the repository
4b6e5a
than the working copy.\)
4b6e5a
4b6e5a
See also `svn-status-short-mod-flag-p'."
cvsdist e1e786
  :group 'psvn-faces)
cvsdist e1e786
cvsdist e1e786
;based on cvs-filename-face
cvsdist e1e786
(defface svn-status-directory-face
cvsdist e1e786
  '((((type tty) (class color)) (:foreground "lightblue" :weight light))
cvsdist e1e786
    (((class color) (background light)) (:foreground "blue4"))
cvsdist e1e786
    (((class color) (background dark)) (:foreground "lightskyblue1"))
cvsdist e1e786
    (t (:weight bold)))
a73eb4
  "Face for directories in *svn-status* buffers.
cvsdist e1e786
See `svn-status--line-info->directory-p' for what counts as a directory."
cvsdist e1e786
  :group 'psvn-faces)
cvsdist e1e786
cvsdist e1e786
;based on font-lock-comment-face
cvsdist e1e786
(defface svn-status-filename-face
cvsdist e1e786
  '((((class color) (background light)) (:foreground "chocolate"))
cvsdist e1e786
    (((class color) (background dark)) (:foreground "beige")))
a73eb4
  "Face for non-directories in *svn-status* buffers.
cvsdist e1e786
See `svn-status--line-info->directory-p' for what counts as a directory."
cvsdist e1e786
  :group 'psvn-faces)
cvsdist e1e786
c707a3
;not based on anything, may be horribly ugly!
c707a3
(defface svn-status-symlink-face
c707a3
  '((((class color) (background light)) (:foreground "cornflower blue"))
c707a3
    (((class color) (background dark)) (:foreground "cyan")))
c707a3
  "Face for symlinks in *svn-status* buffers.
c707a3
c707a3
This is the face given to the actual link (i.e., the versioned item),
c707a3
the target of the link gets either `svn-status-filename-face' or
c707a3
`svn-status-directory-face'."
c707a3
  :group 'psvn-faces)
c707a3
4b6e5a
;based on font-lock-warning-face
4b6e5a
(defface svn-status-locked-face
4b6e5a
  '((t
4b6e5a
     (:weight bold :foreground "Red")))
4b6e5a
  "Face for the phrase \"[ LOCKED ]\" `svn-status-buffer-name' buffers."
4b6e5a
  :group 'psvn-faces)
4b6e5a
4b6e5a
;based on vhdl-font-lock-directive-face
4b6e5a
(defface svn-status-switched-face
4b6e5a
  '((((class color)
4b6e5a
      (background light))
4b6e5a
     (:foreground "CadetBlue"))
4b6e5a
    (((class color)
4b6e5a
      (background dark))
4b6e5a
     (:foreground "Aquamarine"))
4b6e5a
    (t
4b6e5a
     (:bold t :italic t)))
4b6e5a
  "Face for the phrase \"(switched)\" non-directories in svn status buffers."
4b6e5a
  :group 'psvn-faces)
4b6e5a
c707a3
(if svn-xemacsp
c707a3
    (defface svn-status-blame-highlight-face
c707a3
      '((((type tty) (class color)) (:foreground "green" :weight light))
c707a3
        (((class color) (background light)) (:foreground "green3"))
c707a3
        (((class color) (background dark)) (:foreground "palegreen2"))
c707a3
        (t (:weight bold)))
c707a3
      "Default face for highlighting a line in svn status blame mode."
c707a3
      :group 'psvn-faces)
c707a3
  (defface svn-status-blame-highlight-face
c707a3
    '((t :inherit highlight))
c707a3
    "Default face for highlighting a line in svn status blame mode."
c707a3
    :group 'psvn-faces))
c707a3
1b1de0
(if svn-xemacsp
1b1de0
    (defface svn-log-partner-highlight-face
1b1de0
      '((((type tty) (class color)) (:foreground "yellow" :weight light))
1b1de0
        (((class color) (background light)) (:foreground "gold"))
1b1de0
        (((class color) (background dark)) (:foreground "gold"))
1b1de0
        (t (:weight bold)))
1b1de0
      "Default face for highlighting the partner in svn log mode."
1b1de0
      :group 'psvn-faces)
1b1de0
  (defface svn-log-partner-highlight-face
1b1de0
  '((((class color) (background light))
1b1de0
     (:background "light goldenrod" :weight bold))
1b1de0
    (t (:weight bold)))
1b1de0
    "Default face for highlighting the partner in svn log mode."
1b1de0
    :group 'psvn-faces))
1b1de0
c707a3
(defface svn-status-blame-rev-number-face
c707a3
  '((((class color) (background light)) (:foreground "DarkGoldenrod"))
c707a3
    (((class color) (background dark)) (:foreground "LightGoldenrod"))
c707a3
    (t (:weight bold :slant italic)))
c707a3
  "Face to highlight revision numbers in the svn-blame mode."
c707a3
  :group 'psvn-faces)
c707a3
cvsdist e1e786
(defvar svn-highlight t)
cvsdist e1e786
;; stolen from PCL-CVS
cvsdist e1e786
(defun svn-add-face (str face &optional keymap)
4b6e5a
  "Return string STR decorated with the specified FACE.
4b6e5a
If `svn-highlight' is nil then just return STR."
cvsdist e1e786
  (when svn-highlight
cvsdist e1e786
    ;; Do not use `list*'; cl.el might not have been loaded.  We could
cvsdist e1e786
    ;; put (require 'cl) at the top but let's try to manage without.
cvsdist e1e786
    (add-text-properties 0 (length str)
cvsdist e1e786
                         `(face ,face
4b6e5a
                                mouse-face highlight)
4b6e5a
;; 18.10.2004: the keymap parameter is not used (yet) in psvn.el
4b6e5a
;;                           ,@(when keymap
4b6e5a
;;                               `(mouse-face highlight
4b6e5a
;;                                 local-map ,keymap)))
cvsdist e1e786
                         str))
cvsdist e1e786
  str)
cvsdist e1e786
cvsdist e1e786
(defun svn-status-maybe-add-face (condition text face)
cvsdist e1e786
  "If CONDITION then add FACE to TEXT.
cvsdist e1e786
Else return TEXT unchanged."
cvsdist e1e786
  (if condition
cvsdist e1e786
      (svn-add-face text face)
cvsdist e1e786
    text))
cvsdist e1e786
cvsdist e1e786
(defun svn-status-choose-face-to-add (condition text face1 face2)
cvsdist e1e786
  "If CONDITION then add FACE1 to TEXT, else add FACE2 to TEXT."
cvsdist e1e786
  (if condition
cvsdist e1e786
      (svn-add-face text face1)
cvsdist e1e786
    (svn-add-face text face2)))
cvsdist e1e786
4b6e5a
(defun svn-status-maybe-add-string (condition string face)
4b6e5a
  "If CONDITION then return STRING decorated with FACE.
4b6e5a
Otherwise, return \"\"."
4b6e5a
  (if condition
4b6e5a
      (svn-add-face string face)
4b6e5a
    ""))
4b6e5a
c707a3
;; compatibility
c707a3
;; emacs 20
2e0edb
(defalias 'svn-point-at-eol
2e0edb
  (if (fboundp 'point-at-eol) 'point-at-eol 'line-end-position))
2e0edb
(defalias 'svn-point-at-bol
2e0edb
  (if (fboundp 'point-at-bol) 'point-at-bol 'line-beginning-position))
1cd9ea
(defalias 'svn-read-directory-name
2e0edb
  (if (fboundp 'read-directory-name) 'read-directory-name 'read-file-name))
cvsdist e1e786
cvsdist e1e786
(eval-when-compile
cvsdist e1e786
  (if (not (fboundp 'gethash))
cvsdist e1e786
      (require 'cl-macs)))
2e0edb
(defalias 'svn-puthash (if (fboundp 'puthash) 'puthash 'cl-puthash))
cvsdist e1e786
c707a3
;; emacs 21
c707a3
(if (fboundp 'line-number-at-pos)
c707a3
    (defalias 'svn-line-number-at-pos 'line-number-at-pos)
c707a3
  (defun svn-line-number-at-pos (&optional pos)
c707a3
    "Return (narrowed) buffer line number at position POS.
c707a3
If POS is nil, use current buffer location."
c707a3
    (let ((opoint (or pos (point))) start)
c707a3
      (save-excursion
c707a3
        (goto-char (point-min))
c707a3
        (setq start (point))
c707a3
        (goto-char opoint)
c707a3
        (forward-line 0)
c707a3
        (1+ (count-lines start (point)))))))
c707a3
1b1de0
(defun svn-substring-no-properties (string &optional from to)
1b1de0
  (if (fboundp 'substring-no-properties)
1b1de0
      (substring-no-properties string from to)
f41b0b
    (substring string (or from 0) to)))
1b1de0
4b6e5a
; xemacs
2e0edb
;; Evaluate the defsubst at compile time, so that the byte compiler
2e0edb
;; knows the definition and can inline calls.  It cannot detect the
2e0edb
;; defsubst automatically from within the if form.
2e0edb
(eval-and-compile
2e0edb
  (if (fboundp 'match-string-no-properties)
2e0edb
      (defalias 'svn-match-string-no-properties 'match-string-no-properties)
2e0edb
    (defsubst svn-match-string-no-properties (match)
2e0edb
      (buffer-substring-no-properties (match-beginning match) (match-end match)))))
2e0edb
f41b0b
; XEmacs doesn't have a function `help-buffer'
f41b0b
(eval-and-compile
f41b0b
  (if (fboundp 'help-buffer)
f41b0b
      (defalias 'svn-help-buffer 'help-buffer) ; FSF Emacs
f41b0b
    (defun svn-help-buffer ()
f41b0b
      (buffer-name (get-buffer-create (help-buffer-name "SVN")))))) ; XEmacs
f41b0b
f41b0b
2e0edb
;; XEmacs 21.4.17 does not have an `alist' widget.  Define a replacement.
2e0edb
;; To find out whether the `alist' widget exists, we cannot check just
2e0edb
;; (get 'alist 'widget-type), because GNU Emacs 21.4 defines it in
2e0edb
;; "wid-edit.el", which is not preloaded; it will be autoloaded when
2e0edb
;; `widget-create' is called.  Instead, we call `widgetp', which is
2e0edb
;; also autoloaded from "wid-edit.el".  XEmacs 21.4.17 does not have
2e0edb
;; `widgetp' either, so we check that first.
2e0edb
(if (and (fboundp 'widgetp) (widgetp 'alist))
2e0edb
    (define-widget 'svn-alist 'alist
2e0edb
      "An association list.
2e0edb
Use this instead of `alist', for XEmacs 21.4 compatibility.")
2e0edb
  (define-widget 'svn-alist 'list
2e0edb
    "An association list.
2e0edb
Use this instead of `alist', for XEmacs 21.4 compatibility."
2e0edb
    :convert-widget 'svn-alist-convert-widget
2e0edb
    :tag "Association List"
2e0edb
    :key-type 'sexp
2e0edb
    :value-type 'sexp)
2e0edb
  (defun svn-alist-convert-widget (widget)
2e0edb
    (let* ((value-type (widget-get widget :value-type))
2e0edb
           (option-widgets (loop for option in (widget-get widget :options)
2e0edb
                             collect `(cons :format "%v"
2e0edb
                                            (const :format "%t: %v\n"
2e0edb
                                                   :tag "Key"
2e0edb
                                                   ,option)
2e0edb
                                            ,value-type))))
2e0edb
      (widget-put widget :args
2e0edb
                  `(,@(when option-widgets
2e0edb
                        `((set :inline t :format "%v"
2e0edb
                               ,@option-widgets)))
2e0edb
                    (editable-list :inline t
2e0edb
                                   (cons :format "%v"
2e0edb
                                         ,(widget-get widget :key-type)
2e0edb
                                         ,value-type)))))
2e0edb
    widget))
4b6e5a
1b1de0
;; process launch functions
1b1de0
(defvar svn-call-process-function (if (fboundp 'process-file) 'process-file 'call-process))
1b1de0
(defvar svn-start-process-function (if (fboundp 'start-file-process) 'start-file-process 'start-process))
1b1de0
a73eb4
a73eb4
;;; keymaps
a73eb4
4b6e5a
(defvar svn-global-keymap nil "Global keymap for psvn.el.
4b6e5a
To bind this to a different key, customize `svn-status-prefix-key'.")
1cd9ea
(put 'svn-global-keymap 'risky-local-variable t)
4b6e5a
(when (not svn-global-keymap)
4b6e5a
  (setq svn-global-keymap (make-sparse-keymap))
c707a3
  (define-key svn-global-keymap (kbd "v") 'svn-status-version)
4b6e5a
  (define-key svn-global-keymap (kbd "s") 'svn-status-this-directory)
c707a3
  (define-key svn-global-keymap (kbd "b") 'svn-status-via-bookmark)
c707a3
  (define-key svn-global-keymap (kbd "h") 'svn-status-use-history)
4b6e5a
  (define-key svn-global-keymap (kbd "u") 'svn-status-update-cmd)
4b6e5a
  (define-key svn-global-keymap (kbd "=") 'svn-status-show-svn-diff)
c707a3
  (define-key svn-global-keymap (kbd "f =") 'svn-file-show-svn-diff)
c707a3
  (define-key svn-global-keymap (kbd "f e") 'svn-file-show-svn-ediff)
c707a3
  (define-key svn-global-keymap (kbd "f l") 'svn-status-show-svn-log)
c707a3
  (define-key svn-global-keymap (kbd "f b") 'svn-status-blame)
c707a3
  (define-key svn-global-keymap (kbd "f a") 'svn-file-add-to-changelog)
1b1de0
  (define-key svn-global-keymap (kbd "f r") 'svn-file-revert)
a73eb4
  (define-key svn-global-keymap (kbd "c") 'svn-status-commit)
699a1a
  (define-key svn-global-keymap (kbd "S") 'svn-status-switch-to-status-buffer)
f41b0b
  (define-key svn-global-keymap (kbd "o") 'svn-status-pop-to-status-buffer)
f41b0b
  (define-key svn-global-keymap (kbd "C-k") 'svn-process-kill))
4b6e5a
1cd9ea
(defvar svn-status-diff-mode-map ()
1cd9ea
  "Keymap used in `svn-status-diff-mode' for additional commands that are not defined in diff-mode.")
1cd9ea
(put 'svn-status-diff-mode-map 'risky-local-variable t) ;for Emacs 20.7
1cd9ea
1cd9ea
(when (not svn-status-diff-mode-map)
1cd9ea
  (setq svn-status-diff-mode-map (copy-keymap diff-mode-shared-map))
c707a3
  (define-key svn-status-diff-mode-map [?g] 'revert-buffer)
c707a3
  (define-key svn-status-diff-mode-map [?s] 'svn-status-pop-to-status-buffer)
c707a3
  (define-key svn-status-diff-mode-map [?c] 'svn-status-diff-pop-to-commit-buffer)
1cd9ea
  (define-key svn-status-diff-mode-map [?w] 'svn-status-diff-save-current-defun-as-kill))
1cd9ea
4b6e5a
(defvar svn-global-trac-map ()
4b6e5a
  "Subkeymap used in `svn-global-keymap' for trac issue tracker commands.")
1cd9ea
(put 'svn-global-trac-map 'risky-local-variable t) ;for Emacs 20.7
4b6e5a
(when (not svn-global-trac-map)
4b6e5a
  (setq svn-global-trac-map (make-sparse-keymap))
c707a3
  (define-key svn-global-trac-map (kbd "w") 'svn-trac-browse-wiki)
4b6e5a
  (define-key svn-global-trac-map (kbd "t") 'svn-trac-browse-timeline)
c707a3
  (define-key svn-global-trac-map (kbd "m") 'svn-trac-browse-roadmap)
c707a3
  (define-key svn-global-trac-map (kbd "s") 'svn-trac-browse-source)
c707a3
  (define-key svn-global-trac-map (kbd "r") 'svn-trac-browse-report)
4b6e5a
  (define-key svn-global-trac-map (kbd "i") 'svn-trac-browse-ticket)
4b6e5a
  (define-key svn-global-trac-map (kbd "c") 'svn-trac-browse-changeset)
4b6e5a
  (define-key svn-global-keymap (kbd "t") svn-global-trac-map))
4b6e5a
4b6e5a
;; The setter of `svn-status-prefix-key' makes a binding in the global
4b6e5a
;; map refer to the `svn-global-keymap' symbol, rather than directly
4b6e5a
;; to the keymap.  Emacs then implicitly uses the symbol-function.
4b6e5a
;; This has the advantage that `describe-bindings' (C-h b) can show
4b6e5a
;; the name of the keymap and link to its documentation.
4b6e5a
(defalias 'svn-global-keymap svn-global-keymap)
4b6e5a
;; `defalias' of GNU Emacs 21.4 doesn't allow a docstring argument.
4b6e5a
(put 'svn-global-keymap 'function-documentation
4b6e5a
     '(documentation-property 'svn-global-keymap 'variable-documentation t))
4b6e5a
4b6e5a
2e0edb
;; named after SVN_WC_ADM_DIR_NAME in svn_wc.h
2e0edb
(defun svn-wc-adm-dir-name ()
2e0edb
  "Return the name of the \".svn\" subdirectory or equivalent."
2e0edb
  (if (and (eq system-type 'windows-nt)
2e0edb
           (getenv "SVN_ASP_DOT_NET_HACK"))
2e0edb
      "_svn"
2e0edb
    ".svn"))
2e0edb
c707a3
(defun svn-log-edit-file-name (&optional curdir)
c707a3
  "Get the name of the saved log edit file
c707a3
If curdir, return `svn-log-edit-file-name'
c707a3
Otherwise position svn-log-edit-file-name in the root directory of this working copy"
c707a3
  (if curdir
c707a3
      svn-log-edit-file-name
c707a3
    (concat (svn-status-base-dir) svn-log-edit-file-name)))
c707a3
4b6e5a
(defun svn-status-message (level &rest args)
4b6e5a
  "If LEVEL is lower than `svn-status-debug-level' print ARGS using `message'.
4b6e5a
4b6e5a
Guideline for numbers:
4b6e5a
1 - error messages, 3 - non-serious error messages, 5 - messages for things
4b6e5a
that take a long time, 7 - not very important messages on stuff, 9 - messages
4b6e5a
inside loops."
4b6e5a
  (if (<= level svn-status-debug-level)
4b6e5a
      (apply 'message args)))
4b6e5a
4b6e5a
(defun svn-status-flatten-list (list)
4b6e5a
  "Flatten any lists within ARGS, so that there are no sublists."
4b6e5a
  (loop for item in list
2e0edb
        if (listp item) nconc (svn-status-flatten-list item)
2e0edb
        else collect item))
4b6e5a
c707a3
(defun svn-status-window-line-position (w)
c707a3
  "Return the window line at point for window W, or nil if W is nil."
c707a3
  (svn-status-message 3 "About to count lines; selected window is %s" (selected-window))
c707a3
  (and w (count-lines (window-start w) (point))))
699a1a
c707a3
;;;###autoload
c707a3
(defun svn-checkout (repos-url path)
c707a3
  "Run svn checkout REPOS-URL PATH."
c707a3
  (interactive (list (read-string "Checkout from repository Url: ")
c707a3
                     (svn-read-directory-name "Checkout to directory: ")))
c707a3
  (svn-run t t 'checkout "checkout" repos-url (expand-file-name path)))
699a1a
699a1a
;;;###autoload (defalias 'svn-examine 'svn-status)
699a1a
(defalias 'svn-examine 'svn-status)
699a1a
cvsdist e1e786
;;;###autoload
cvsdist e1e786
(defun svn-status (dir &optional arg)
cvsdist e1e786
  "Examine the status of Subversion working copy in directory DIR.
a73eb4
If ARG is -, allow editing of the parameters. One could add -N to
a73eb4
run svn status non recursively to make it faster.
c707a3
For every other non nil ARG pass the -u argument to `svn status', which
c707a3
asks svn to connect to the repository and check to see if there are updates
c707a3
there.
699a1a
c707a3
If there is no .svn directory, examine if there is CVS and run
699a1a
`cvs-examine'. Otherwise ask if to run `dired'."
2e0edb
  (interactive (list (svn-read-directory-name "SVN status directory: "
2e0edb
                                              nil default-directory nil)
4b6e5a
                     current-prefix-arg))
699a1a
  (let ((svn-dir (format "%s%s"
699a1a
                         (file-name-as-directory dir)
699a1a
                         (svn-wc-adm-dir-name)))
699a1a
        (cvs-dir (format "%sCVS" (file-name-as-directory dir))))
699a1a
    (cond
699a1a
     ((file-directory-p svn-dir)
699a1a
      (setq arg (svn-status-possibly-negate-meaning-of-arg arg 'svn-status))
699a1a
      (svn-status-1 dir arg))
699a1a
     ((and (file-directory-p cvs-dir)
699a1a
           (fboundp 'cvs-examine))
699a1a
      (cvs-examine dir nil))
699a1a
     (t
699a1a
      (when (y-or-n-p
699a1a
             (format
699a1a
              (concat
699a1a
               "%s "
699a1a
               "is not Subversion controlled (missing %s "
699a1a
               "directory). "
699a1a
               "Run dired instead? ")
699a1a
              dir
699a1a
              (svn-wc-adm-dir-name)))
699a1a
        (dired dir))))))
699a1a
699a1a
(defvar svn-status-display-new-status-buffer nil)
699a1a
(defun svn-status-1 (dir &optional arg)
699a1a
  "Examine DIR. See `svn-status' for more information."
cvsdist e1e786
  (unless (file-directory-p dir)
cvsdist e1e786
    (error "%s is not a directory" dir))
699a1a
  (setq dir (file-name-as-directory dir))
699a1a
  (when svn-status-load-state-before-svn-status
699a1a
    (unless (string= dir (car svn-status-directory-history))
c707a3
      (let ((default-directory dir))    ;otherwise svn-status-base-dir looks in the wrong place
c707a3
        (svn-status-load-state t))))
699a1a
  (setq svn-status-directory-history (delete dir svn-status-directory-history))
699a1a
  (add-to-list 'svn-status-directory-history dir)
699a1a
  (if (string= (buffer-name) svn-status-buffer-name)
699a1a
      (setq svn-status-display-new-status-buffer nil)
699a1a
    (setq svn-status-display-new-status-buffer t)
699a1a
    ;;(message "psvn: Saving initial window configuration")
699a1a
    (setq svn-status-initial-window-configuration
699a1a
          (current-window-configuration)))
c707a3
  (let* ((cur-buf (current-buffer))
c707a3
         (status-buf (get-buffer-create svn-status-buffer-name))
c707a3
         (proc-buf (get-buffer-create svn-process-buffer-name))
699a1a
         (want-edit (eq arg '-))
699a1a
         (status-option (if want-edit
699a1a
                            (if svn-status-verbose "-v" "")
699a1a
                          (if svn-status-verbose
699a1a
                              (if arg "-uv" "-v")
1b1de0
                            (if arg "-u" "")))))
699a1a
    (save-excursion
699a1a
      (set-buffer status-buf)
f41b0b
      (buffer-disable-undo)
699a1a
      (setq default-directory dir)
699a1a
      (set-buffer proc-buf)
699a1a
      (setq default-directory dir
699a1a
            svn-status-remote (when arg t))
c707a3
      (set-buffer cur-buf)
1b1de0
      (if want-edit
f41b0b
          (let ((svn-status-edit-svn-command t))
1b1de0
            (svn-run t t 'status "status" svn-status-default-status-arguments status-option))
1b1de0
        (svn-run t t 'status "status" svn-status-default-status-arguments status-option)))))
4b6e5a
4b6e5a
(defun svn-status-this-directory (arg)
4b6e5a
  "Run `svn-status' for the `default-directory'"
4b6e5a
  (interactive "P")
4b6e5a
  (svn-status default-directory arg))
cvsdist e1e786
cvsdist e1e786
(defun svn-status-use-history ()
c707a3
  "Interactively select a different directory from `svn-status-directory-history'."
cvsdist e1e786
  (interactive)
c707a3
  (let* ((in-status-buffer (eq major-mode 'svn-status-mode))
c707a3
         (hist (if in-status-buffer (cdr svn-status-directory-history) svn-status-directory-history))
c707a3
         (dir (funcall svn-status-completing-read-function "svn-status on directory: " hist))
1b1de0
         (svn-status-buffer (get-buffer svn-status-buffer-name))
1b1de0
         (svn-buffer-available (and svn-status-buffer
1b1de0
                                    (with-current-buffer svn-status-buffer-name (string= default-directory dir)))))
4b6e5a
    (if (file-directory-p dir)
c707a3
        (if svn-buffer-available
c707a3
            (svn-status-switch-to-status-buffer)
c707a3
          (unless svn-status-refresh-info
c707a3
            (setq svn-status-refresh-info 'once))
c707a3
          (svn-status dir))
4b6e5a
      (error "%s is not a directory" dir))))
cvsdist e1e786
a73eb4
(defun svn-had-user-input-since-asynch-run ()
a73eb4
  (not (equal (recent-keys) svn-pre-run-asynch-recent-keys)))
a73eb4
f41b0b
(defun svn-expand-filename-for-remote-access (file-name)
f41b0b
  "Convert the given local part of a filename to a full file name to allow accessing remote files"
f41b0b
  ;; when running svn on a remote host: expand local file names to get full names to access the file on the remote host via emacs
f41b0b
  (if (and (fboundp 'file-remote-p) (file-remote-p default-directory))
f41b0b
      (concat (file-remote-p default-directory) file-name)
f41b0b
    file-name))
f41b0b
f41b0b
(defun svn-local-filename-for-remote-access (file-name)
f41b0b
  "Convert a full file name to a local file name that can be used for a local svn invocation."
f41b0b
  (if (and (fboundp 'file-remote-p) (file-remote-p file-name))
f41b0b
      (tramp-file-name-localname (tramp-dissect-file-name file-name))
f41b0b
    file-name))
f41b0b
1cd9ea
(defun svn-process-environment ()
1cd9ea
  "Construct the environment for the svn process.
1cd9ea
It is a combination of `svn-status-svn-environment-var-list' and
1cd9ea
the usual `process-environment'."
1cd9ea
  ;; If there are duplicate elements in `process-environment', then GNU
1cd9ea
  ;; Emacs 21.4 guarantees that the first one wins; but GNU Emacs 20.7
1cd9ea
  ;; and XEmacs 21.4.17 don't document what happens.  We'll just remove
1cd9ea
  ;; any duplicates ourselves, then.  This also gives us an opportunity
1cd9ea
  ;; to handle the "VARIABLE" syntax that none of them supports.
1cd9ea
  (loop with found = '()
1cd9ea
        for elt in (append svn-status-svn-environment-var-list
1cd9ea
                           process-environment)
1cd9ea
        for has-value = (string-match "=" elt)
1cd9ea
        for name = (substring elt 0 has-value)
1cd9ea
        unless (member name found)
1cd9ea
          do (push name found)
1cd9ea
          and when has-value
1cd9ea
            collect elt))
1cd9ea
a73eb4
(defun svn-run (run-asynchron clear-process-buffer cmdtype &rest arglist)
cvsdist e1e786
  "Run svn with arguments ARGLIST.
cvsdist e1e786
cvsdist e1e786
If RUN-ASYNCHRON is t then run svn asynchronously.
cvsdist e1e786
cvsdist e1e786
If CLEAR-PROCESS-BUFFER is t then erase the contents of the
c707a3
`svn-process-buffer-name' buffer before commencing.
cvsdist e1e786
cvsdist e1e786
CMDTYPE is a symbol such as 'mv, 'revert, or 'add, representing the
cvsdist e1e786
command to run.
cvsdist e1e786
cvsdist e1e786
ARGLIST is a list of arguments \(which must include the command name,
4b6e5a
for example: '(\"revert\" \"file1\"\)
4b6e5a
ARGLIST is flattened and any every nil value is discarded.
4b6e5a
4b6e5a
If the variable `svn-status-edit-svn-command' is non-nil then the user
c707a3
can edit ARGLIST before running svn.
c707a3
c707a3
The hook svn-pre-run-hook allows to monitor/modify the ARGLIST."
4b6e5a
  (setq arglist (svn-status-flatten-list arglist))
cvsdist e1e786
  (if (eq (process-status "svn") nil)
cvsdist e1e786
      (progn
cvsdist e1e786
        (when svn-status-edit-svn-command
a73eb4
          (setq arglist (append
a73eb4
                         (list (car arglist))
a73eb4
                         (split-string
a73eb4
                          (read-from-minibuffer
a73eb4
                           (format "svn %s flags: " (car arglist))
a73eb4
                           (mapconcat 'identity (cdr arglist) " ")))))
cvsdist e1e786
          (when (eq svn-status-edit-svn-command t)
cvsdist e1e786
            (svn-status-toggle-edit-cmd-flag t))
a73eb4
          (message "svn-run %s: %S" cmdtype arglist))
c707a3
        (run-hooks 'svn-pre-run-hook)
c707a3
        (unless (eq mode-line-process 'svn-status-mode-line-process)
c707a3
          (setq svn-pre-run-mode-line-process mode-line-process)
c707a3
          (setq mode-line-process 'svn-status-mode-line-process))
c707a3
        (setq svn-status-pre-run-svn-buffer (current-buffer))
f89e89
        (let* ((pre-run-buffer-default-directory default-directory)
f89e89
               (proc-buf (get-buffer-create svn-process-buffer-name))
4b6e5a
               (svn-exe svn-status-svn-executable)
cvsdist e1e786
               (svn-proc))
cvsdist e1e786
          (when (listp (car arglist))
cvsdist e1e786
            (setq arglist (car arglist)))
cvsdist e1e786
          (save-excursion
cvsdist e1e786
            (set-buffer proc-buf)
f89e89
            (setq default-directory pre-run-buffer-default-directory)
cvsdist e1e786
            (setq buffer-read-only nil)
c707a3
            (buffer-disable-undo)
cvsdist e1e786
            (fundamental-mode)
cvsdist e1e786
            (if clear-process-buffer
cvsdist e1e786
                (delete-region (point-min) (point-max))
cvsdist e1e786
              (goto-char (point-max)))
cvsdist e1e786
            (setq svn-process-cmd cmdtype)
c707a3
            (setq svn-status-last-commit-author nil)
cvsdist e1e786
            (setq svn-status-mode-line-process-status (format " running %s" cmdtype))
cvsdist e1e786
            (svn-status-update-mode-line)
f41b0b
            (save-excursion (sit-for 0.1))
d9a7f5
            (ring-insert svn-last-cmd-ring (list (current-time-string) arglist default-directory svn-arg-file-content))
d9a7f5
            (setq svn-arg-file-content nil)
d9a7f5
            (setq svn-process-handle-error-msg nil)
cvsdist e1e786
            (if run-asynchron
cvsdist e1e786
                (progn
4b6e5a
                  ;;(message "running asynchron: %s %S" svn-exe arglist)
a73eb4
                  (setq svn-pre-run-asynch-recent-keys (recent-keys))
1cd9ea
                  (let ((process-environment (svn-process-environment))
1cd9ea
                        (process-connection-type nil))
1cd9ea
                    ;; Communicate with the subprocess via pipes rather
1cd9ea
                    ;; than via a pseudoterminal, so that if the svn+ssh
1cd9ea
                    ;; scheme is being used, SSH will not ask for a
1cd9ea
                    ;; passphrase via stdio; psvn.el is currently unable
1cd9ea
                    ;; to answer such prompts.  Instead, SSH will run
1cd9ea
                    ;; x11-ssh-askpass if possible.  If Emacs is being
1cd9ea
                    ;; run on a TTY without $DISPLAY, this will fail; in
1cd9ea
                    ;; such cases, the user should start ssh-agent and
1cd9ea
                    ;; then run ssh-add explicitly.
1b1de0
                    (setq svn-proc (apply svn-start-process-function "svn" proc-buf svn-exe arglist)))
c707a3
                  (when svn-status-svn-process-coding-system
c707a3
                    (set-process-coding-system svn-proc svn-status-svn-process-coding-system
c707a3
                                               svn-status-svn-process-coding-system))
4b6e5a
                  (set-process-sentinel svn-proc 'svn-process-sentinel)
4b6e5a
                  (when svn-status-track-user-input
4b6e5a
                    (set-process-filter svn-proc 'svn-process-filter)))
4b6e5a
              ;;(message "running synchron: %s %S" svn-exe arglist)
1cd9ea
              (let ((process-environment (svn-process-environment)))
1cd9ea
                ;; `call-process' ignores `process-connection-type' and
1cd9ea
                ;; never opens a pseudoterminal.
1b1de0
                (apply svn-call-process-function svn-exe nil proc-buf nil arglist))
c707a3
              (setq svn-status-last-output-buffer-name svn-process-buffer-name)
c707a3
              (run-hooks 'svn-post-process-svn-output-hook)
cvsdist e1e786
              (setq svn-status-mode-line-process-status "")
c707a3
              (svn-status-update-mode-line)
c707a3
              (when svn-pre-run-mode-line-process
c707a3
                (setq mode-line-process svn-pre-run-mode-line-process)
c707a3
                (setq svn-pre-run-mode-line-process nil))))))
cvsdist e1e786
    (error "You can only run one svn process at once!")))
cvsdist e1e786
a73eb4
(defun svn-process-sentinel-fixup-path-seperators ()
699a1a
    "Convert all path separators to UNIX style.
a73eb4
\(This is a no-op unless `system-type' is windows-nt\)"
4b6e5a
  (when (eq system-type 'windows-nt)
4b6e5a
      (save-excursion
4b6e5a
        (goto-char (point-min))
4b6e5a
        (while (search-forward "\\" nil t)
4b6e5a
          (replace-match "/")))))
4b6e5a
cvsdist e1e786
(defun svn-process-sentinel (process event)
f41b0b
  "Called after a svn process has finished."
cvsdist e1e786
  ;;(princ (format "Process: %s had the event `%s'" process event)))
cvsdist e1e786
  (let ((act-buf (current-buffer)))
c707a3
    (when svn-pre-run-mode-line-process
c707a3
      (with-current-buffer svn-status-pre-run-svn-buffer
c707a3
        (setq mode-line-process svn-pre-run-mode-line-process))
c707a3
      (setq svn-pre-run-mode-line-process nil))
cvsdist e1e786
    (set-buffer (process-buffer process))
cvsdist e1e786
    (setq svn-status-mode-line-process-status "")
cvsdist e1e786
    (svn-status-update-mode-line)
cvsdist e1e786
    (cond ((string= event "finished\n")
c707a3
           (run-hooks 'svn-post-process-svn-output-hook)
cvsdist e1e786
           (cond ((eq svn-process-cmd 'status)
cvsdist e1e786
                  ;;(message "svn status finished")
4b6e5a
                  (svn-process-sentinel-fixup-path-seperators)
cvsdist e1e786
                  (svn-parse-status-result)
c707a3
                  (svn-status-apply-elide-list)
cvsdist e1e786
                  (when svn-status-update-previous-process-output
cvsdist e1e786
                    (set-buffer (process-buffer process))
cvsdist e1e786
                    (delete-region (point-min) (point-max))
cvsdist e1e786
                    (insert "Output from svn command:\n")
cvsdist e1e786
                    (insert svn-status-update-previous-process-output)
cvsdist e1e786
                    (goto-char (point-min))
357017
                    (setq svn-status-update-previous-process-output nil))
699a1a
                  (when svn-status-update-list
699a1a
                    ;; (message "Using svn-status-update-list: %S" svn-status-update-list)
699a1a
                    (save-excursion
699a1a
                      (svn-status-update-with-command-list svn-status-update-list))
699a1a
                    (setq svn-status-update-list nil))
357017
                  (when svn-status-display-new-status-buffer
357017
                    (set-window-configuration svn-status-initial-window-configuration)
a73eb4
                    (if (svn-had-user-input-since-asynch-run)
a73eb4
                        (message "svn status finished")
a73eb4
                      (switch-to-buffer svn-status-buffer-name))))
cvsdist e1e786
                 ((eq svn-process-cmd 'log)
4b6e5a
                  (svn-status-show-process-output 'log t)
4b6e5a
                  (pop-to-buffer svn-status-last-output-buffer-name)
cvsdist e1e786
                  (svn-log-view-mode)
c707a3
                  (forward-line 2)
c707a3
                  (unless (looking-at "Changed paths:")
c707a3
                    (forward-line 1))
cvsdist e1e786
                  (font-lock-fontify-buffer)
cvsdist e1e786
                  (message "svn log finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'info)
4b6e5a
                  (svn-status-show-process-output 'info t)
cvsdist e1e786
                  (message "svn info finished"))
699a1a
                 ((eq svn-process-cmd 'ls)
699a1a
                  (svn-status-show-process-output 'info t)
699a1a
                  (message "svn ls finished"))
c707a3
                 ((eq svn-process-cmd 'diff)
c707a3
                  (svn-status-activate-diff-mode)
c707a3
                  (message "svn diff finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'parse-info)
cvsdist e1e786
                  (svn-status-parse-info-result))
cvsdist e1e786
                 ((eq svn-process-cmd 'blame)
4b6e5a
                  (svn-status-show-process-output 'blame t)
699a1a
                  (when svn-status-pre-run-svn-buffer
699a1a
                    (with-current-buffer svn-status-pre-run-svn-buffer
699a1a
                      (unless (eq major-mode 'svn-status-mode)
c707a3
                        (let ((src-line-number (svn-line-number-at-pos)))
c707a3
                          (pop-to-buffer (get-buffer svn-status-last-output-buffer-name))
c707a3
                          (goto-line src-line-number)))))
c707a3
                  (with-current-buffer (get-buffer svn-status-last-output-buffer-name)
c707a3
                    (svn-status-activate-blame-mode))
cvsdist e1e786
                  (message "svn blame finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'commit)
4b6e5a
                  (svn-process-sentinel-fixup-path-seperators)
cvsdist e1e786
                  (svn-status-remove-temp-file-maybe)
cvsdist e1e786
                  (when (member 'commit svn-status-unmark-files-after-list)
cvsdist e1e786
                    (svn-status-unset-all-usermarks))
4b6e5a
                  (svn-status-update-with-command-list (svn-status-parse-commit-output))
c707a3
                  (svn-revert-some-buffers)
4b6e5a
                  (run-hooks 'svn-log-edit-done-hook)
2e0edb
                  (setq svn-status-files-to-commit nil
2e0edb
                        svn-status-recursive-commit nil)
1b1de0
                  (if (null svn-status-commit-rev-number)
1b1de0
                      (message "No revision to commit.")
1b1de0
                    (message "svn: Committed revision %s." svn-status-commit-rev-number)))
cvsdist e1e786
                 ((eq svn-process-cmd 'update)
4b6e5a
                  (svn-status-show-process-output 'update t)
699a1a
                  (setq svn-status-update-list (svn-status-parse-update-output))
c707a3
                  (svn-revert-some-buffers)
cvsdist e1e786
                  (svn-status-update)
c707a3
                  (if (car svn-status-update-rev-number)
c707a3
                      (message "svn: Updated to revision %s." (cadr svn-status-update-rev-number))
c707a3
                    (message "svn: At revision %s." (cadr svn-status-update-rev-number))))
cvsdist e1e786
                 ((eq svn-process-cmd 'add)
4b6e5a
                  (svn-status-update-with-command-list (svn-status-parse-ar-output))
cvsdist e1e786
                  (message "svn add finished"))
c707a3
                 ((eq svn-process-cmd 'lock)
c707a3
                  (svn-status-update)
c707a3
                  (message "svn lock finished"))
c707a3
                 ((eq svn-process-cmd 'unlock)
c707a3
                  (svn-status-update)
c707a3
                  (message "svn unlock finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'mkdir)
cvsdist e1e786
                  (svn-status-update)
cvsdist e1e786
                  (message "svn mkdir finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'revert)
cvsdist e1e786
                  (when (member 'revert svn-status-unmark-files-after-list)
cvsdist e1e786
                    (svn-status-unset-all-usermarks))
1b1de0
                  (svn-revert-some-buffers)
cvsdist e1e786
                  (svn-status-update)
cvsdist e1e786
                  (message "svn revert finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'resolved)
cvsdist e1e786
                  (svn-status-update)
cvsdist e1e786
                  (message "svn resolved finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'rm)
4b6e5a
                  (svn-status-update-with-command-list (svn-status-parse-ar-output))
cvsdist e1e786
                  (message "svn rm finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'cleanup)
cvsdist e1e786
                  (message "svn cleanup finished"))
cvsdist e1e786
                 ((eq svn-process-cmd 'proplist)
4b6e5a
                  (svn-status-show-process-output 'proplist t)
cvsdist e1e786
                  (message "svn proplist finished"))
c707a3
                 ((eq svn-process-cmd 'checkout)
c707a3
                  (svn-status default-directory))
cvsdist e1e786
                 ((eq svn-process-cmd 'proplist-parse)
cvsdist e1e786
                  (svn-status-property-parse-property-names))
cvsdist e1e786
                 ((eq svn-process-cmd 'propset)
cvsdist e1e786
                  (svn-status-remove-temp-file-maybe)
699a1a
                  (if (member svn-status-propedit-property-name '("svn:keywords"))
699a1a
                      (svn-status-update-with-command-list (svn-status-parse-property-output))
699a1a
                    (svn-status-update)))
cvsdist e1e786
                 ((eq svn-process-cmd 'propdel)
cvsdist e1e786
                  (svn-status-update))))
cvsdist e1e786
          ((string= event "killed\n")
cvsdist e1e786
           (message "svn process killed"))
cvsdist e1e786
          ((string-match "exited abnormally" event)
cvsdist e1e786
           (while (accept-process-output process 0 100))
cvsdist e1e786
           ;; find last error message and show it.
cvsdist e1e786
           (goto-char (point-max))
f41b0b
           (if (re-search-backward "^svn: " nil t)
f41b0b
               (let ((error-strings)
f41b0b
                     (beginning-of-buffer))
f41b0b
                 (while (and (looking-at "^svn: ") (not beginning-of-buffer))
f41b0b
                   (setq error-strings (append error-strings (list (buffer-substring-no-properties (+ 5 (svn-point-at-bol)) (svn-point-at-eol)))))
f41b0b
                   (setq beginning-of-buffer (bobp))
f41b0b
                   (forward-line -1))
f41b0b
                 (svn-process-handle-error (mapconcat 'identity (reverse error-strings) "\n")))
c707a3
             (message "svn failed: %s" event)))
cvsdist e1e786
          (t
cvsdist e1e786
           (message "svn process had unknown event: %s" event))
4b6e5a
          (svn-status-show-process-output nil t))))
4b6e5a
1b1de0
(defvar svn-process-handle-error-msg nil)
f41b0b
(defvar svn-handle-error-function nil
f41b0b
  "A function that will be called with an error string received from the svn client.
f41b0b
When this function resets `svn-process-handle-error-msg' to nil, the default error handling
f41b0b
(just show the error message) is not executed.")
c707a3
(defun svn-process-handle-error (error-msg)
d9a7f5
  (setq svn-process-handle-error-msg error-msg)
d9a7f5
  (when (functionp svn-handle-error-function)
d9a7f5
    (funcall svn-handle-error-function error-msg))
d9a7f5
  (when svn-process-handle-error-msg
d9a7f5
    (electric-helpify 'svn-process-help-with-error-msg)))
c707a3
c707a3
(defun svn-process-help-with-error-msg ()
c707a3
  (interactive)
c707a3
  (let ((help-msg (cadr (assoc svn-process-handle-error-msg
c707a3
                               '(("Cannot non-recursively commit a directory deletion"
c707a3
                                  "Please unmark all files and position point at the directory you would like to remove.\nThen run commit again."))))))
c707a3
    (if help-msg
c707a3
        (save-excursion
f41b0b
          (with-output-to-temp-buffer (svn-help-buffer)
c707a3
            (princ (format "svn failed: %s\n\n%s" svn-process-handle-error-msg help-msg))))
f41b0b
      (message "svn failed:\n%s" svn-process-handle-error-msg))))
c707a3
c707a3
4b6e5a
(defun svn-process-filter (process str)
c707a3
  "Track the svn process output and ask user questions in the minibuffer when appropriate."
4b6e5a
  (save-window-excursion
c707a3
    (set-buffer svn-process-buffer-name)
4b6e5a
    ;;(message "svn-process-filter: %s" str)
4b6e5a
    (goto-char (point-max))
4b6e5a
    (insert str)
4b6e5a
    (save-excursion
a73eb4
      (goto-char (svn-point-at-bol))
f41b0b
      (when (looking-at "Password for '\\(.*\\)': ")
4b6e5a
        ;(svn-status-show-process-buffer)
4b6e5a
        (let ((passwd (read-passwd
4b6e5a
                       (format "Enter svn password for %s: " (match-string 1)))))
c707a3
          (svn-process-send-string-and-newline passwd t)))
4b6e5a
      (when (looking-at "Username: ")
f41b0b
        (let ((user-name (with-local-quit (read-string "Username for svn operation: "))))
c707a3
          (svn-process-send-string-and-newline user-name)))
c707a3
      (when (looking-at "(R)eject, accept (t)emporarily or accept (p)ermanently")
c707a3
        (svn-status-show-process-buffer)
f41b0b
        (let ((answer (with-local-quit (read-string "(R)eject, accept (t)emporarily or accept (p)ermanently? "))))
c707a3
          (svn-process-send-string (substring answer 0 1)))))))
c707a3
c707a3
(defun svn-revert-some-buffers (&optional tree)
c707a3
  "Reverts all buffers visiting a file in TREE that aren't modified.
c707a3
To be run after a commit, an update or a merge."
c707a3
  (interactive)
c707a3
  (let ((tree (or (svn-status-base-dir) tree)))
c707a3
    (dolist (buffer (buffer-list))
c707a3
      (with-current-buffer buffer
c707a3
        (when (not (buffer-modified-p))
c707a3
          (let ((file (buffer-file-name)))
c707a3
            (when file
c707a3
              (let ((root (svn-status-base-dir (file-name-directory file)))
c707a3
                    (point-pos (point)))
c707a3
                (when (and root
c707a3
                           (string= root tree)
c707a3
                           ;; buffer is modified and in the tree TREE.
c707a3
                           svn-status-auto-revert-buffers)
1b1de0
                  (when svn-status-fancy-file-state-in-modeline
1b1de0
                    (svn-status-update-modeline))
c707a3
                  ;; (message "svn-revert-some-buffers: %s %s" (buffer-file-name) (verify-visited-file-modtime (current-buffer)))
c707a3
                  ;; Keep the buffer if the file doesn't exist
c707a3
                  (when (and (file-exists-p file) (not (verify-visited-file-modtime (current-buffer))))
c707a3
                    (revert-buffer t t)
c707a3
                    (goto-char point-pos)))))))))))
cvsdist e1e786
cvsdist e1e786
(defun svn-parse-rev-num (str)
cvsdist e1e786
  (if (and str (stringp str)
cvsdist e1e786
           (save-match-data (string-match "^[0-9]+" str)))
cvsdist e1e786
      (string-to-number str)
cvsdist e1e786
    -1))
cvsdist e1e786
2e0edb
(defsubst svn-status-make-ui-status ()
2e0edb
  "Make a ui-status structure for a file in a svn working copy.
2e0edb
The initial values in the structure returned by this function
2e0edb
are good for a file or directory that the user hasn't seen before.
2e0edb
2e0edb
The ui-status structure keeps track of how the file or directory
2e0edb
should be displayed in svn-status mode.  Updating the svn-status
2e0edb
buffer from the working copy preserves the ui-status if possible.
2e0edb
User commands modify this structure; each file or directory must
2e0edb
thus have its own copy.
2e0edb
2e0edb
Currently, the ui-status is a list (USER-MARK USER-ELIDE).
2e0edb
USER-MARK is non-nil iff the user has marked the file or directory,
2e0edb
  typically with `svn-status-set-user-mark'.  To read USER-MARK,
2e0edb
  call `svn-status-line-info->has-usermark'.
2e0edb
USER-ELIDE is non-nil iff the user has elided the file or directory
2e0edb
  from the svn-status buffer, typically with `svn-status-toggle-elide'.
2e0edb
  To read USER-ELIDE, call `svn-status-line-info->user-elide'.
2e0edb
2e0edb
Call `svn-status-line-info->ui-status' to access the whole ui-status
2e0edb
structure."
2e0edb
  (list nil nil))
cvsdist e1e786
4b6e5a
(defun svn-status-make-dummy-dirs (dir-list old-ui-information)
c707a3
  "Calculate additionally necessary directories that were not shown in the output
c707a3
of 'svn status'"
c707a3
  ;; (message "svn-status-make-dummy-dirs %S" dir-list)
c707a3
  (let ((candidate)
c707a3
        (base-dir))
c707a3
    (dolist (dir dir-list)
c707a3
      (setq base-dir (file-name-directory dir))
c707a3
      (while base-dir
c707a3
        ;;(message "dir: %S dir-list: %S, base-dir: %S" dir dir-list base-dir)
c707a3
        (setq candidate (replace-regexp-in-string "/+$" "" base-dir))
c707a3
        (setq base-dir (file-name-directory candidate))
c707a3
        ;; (message "dir: %S, candidate: %S" dir candidate)
c707a3
        (add-to-list 'dir-list candidate))))
c707a3
  ;; (message "svn-status-make-dummy-dirs %S" dir-list)
4b6e5a
  (append (mapcar (lambda (dir)
c707a3
                    (svn-status-make-line-info
c707a3
                     dir
c707a3
                     (gethash dir old-ui-information)))
4b6e5a
                  dir-list)
4b6e5a
          svn-status-info))
4b6e5a
c707a3
(defun svn-status-make-line-info (&optional
c707a3
                                  path
c707a3
                                  ui
c707a3
                                  file-mark prop-mark
c707a3
                                  local-rev last-change-rev
c707a3
                                  author
c707a3
                                  update-mark
c707a3
                                  locked-mark
c707a3
                                  with-history-mark
c707a3
                                  switched-mark
c707a3
                                  locked-repo-mark
c707a3
                                  psvn-extra-info)
c707a3
  "Create a new line-info from the given arguments
c707a3
Anything left nil gets a sensible default.
c707a3
nb: LOCKED-MARK refers to the kind of locks you get after an error,
c707a3
    LOCKED-REPO-MARK is the kind managed with `svn lock'"
c707a3
  (list (or ui (svn-status-make-ui-status))
c707a3
        (or file-mark ? )
c707a3
        (or prop-mark ? )
c707a3
        (or path "")
c707a3
        (or local-rev ? )
c707a3
        (or last-change-rev ? )
c707a3
        (or author "")
c707a3
        update-mark
c707a3
        locked-mark
c707a3
        with-history-mark
c707a3
        switched-mark
c707a3
        locked-repo-mark
c707a3
        psvn-extra-info))
c707a3
1b1de0
(defvar svn-user-names-including-blanks nil "A list of svn user names that include blanks.
1b1de0
To add support for the names \"feng shui\" and \"mister blank\", place the following in your .emacs:
1b1de0
 (setq svn-user-names-including-blanks '(\"feng shui\" \"mister blank\"))
1b1de0
 (add-hook 'svn-pre-parse-status-hook 'svn-status-parse-fixup-user-names-including-blanks)
1b1de0
")
c707a3
;;(setq svn-user-names-including-blanks '("feng shui" "mister blank"))
c707a3
;;(add-hook 'svn-pre-parse-status-hook 'svn-status-parse-fixup-user-names-including-blanks)
c707a3
c707a3
(defun svn-status-parse-fixup-user-names-including-blanks ()
c707a3
  "Helper function to allow user names that include blanks.
c707a3
Add this function to the `svn-pre-parse-status-hook'. The variable
c707a3
`svn-user-names-including-blanks' must be configured to hold all user names that contain
c707a3
blanks. This function replaces the blanks with '-' to allow further processing with
c707a3
the usual parsing functionality in `svn-parse-status-result'."
c707a3
  (when svn-user-names-including-blanks
c707a3
    (goto-char (point-min))
c707a3
    (let ((search-string (concat " \\(" (mapconcat 'concat svn-user-names-including-blanks "\\|") "\\) ")))
c707a3
      (save-match-data
c707a3
        (save-excursion
c707a3
          (while (re-search-forward search-string (point-max) t)
c707a3
            (replace-match (replace-regexp-in-string " " "-" (match-string 1)) nil nil nil 1)))))))
4b6e5a
cvsdist e1e786
(defun svn-parse-status-result ()
c707a3
  "Parse the `svn-process-buffer-name' buffer.
cvsdist e1e786
The results are used to build the `svn-status-info' variable."
cvsdist e1e786
  (setq svn-status-head-revision nil)
cvsdist e1e786
  (save-excursion
cvsdist e1e786
    (let ((old-ui-information (svn-status-ui-information-hash-table))
cvsdist e1e786
          (svn-marks)
cvsdist e1e786
          (svn-file-mark)
cvsdist e1e786
          (svn-property-mark)
c707a3
          (svn-wc-locked-mark)
c707a3
          (svn-repo-locked-mark)
4b6e5a
          (svn-with-history-mark)
4b6e5a
          (svn-switched-mark)
cvsdist e1e786
          (svn-update-mark)
cvsdist e1e786
          (local-rev)
cvsdist e1e786
          (last-change-rev)
cvsdist e1e786
          (author)
cvsdist e1e786
          (path)
4b6e5a
          (dir)
cvsdist e1e786
          (revision-width svn-status-default-revision-width)
4b6e5a
          (author-width svn-status-default-author-width)
c707a3
          (svn-marks-length (if svn-status-verbose
c707a3
                                (if svn-status-remote
c707a3
                                    8 6)
c707a3
                              (if svn-status-remote
c707a3
                                  ;; not verbose
c707a3
                                  8 7)))
c707a3
          (dir-set '("."))
c707a3
          (externals-map (make-hash-table :test 'equal))
c707a3
          (skip-double-external-dir-entry-name nil))
c707a3
      (set-buffer svn-process-buffer-name)
cvsdist e1e786
      (setq svn-status-info nil)
c707a3
      (run-hooks 'svn-pre-parse-status-hook)
cvsdist e1e786
      (goto-char (point-min))
cvsdist e1e786
      (while (< (point) (point-max))
cvsdist e1e786
        (cond
2e0edb
         ((= (svn-point-at-eol) (svn-point-at-bol)) ;skip blank lines
cvsdist e1e786
          nil)
357017
         ((looking-at "Status against revision:[ ]+\\([0-9]+\\)")
cvsdist e1e786
          ;; the above message appears for the main listing plus once for each svn:externals entry
cvsdist e1e786
          (unless svn-status-head-revision
cvsdist e1e786
            (setq svn-status-head-revision (match-string 1))))
4b6e5a
         ((looking-at "Performing status on external item at '\\(.*\\)'")
cvsdist e1e786
          ;; The *next* line has info about the directory named in svn:externals
4b6e5a
          ;; [ie the directory in (match-string 1)]
cvsdist e1e786
          ;; we should parse it, and merge the info with what we have already know
cvsdist e1e786
          ;; but for now just ignore the line completely
c707a3
          ; (forward-line)
c707a3
          ;;  Actually, this seems to not always be the case
c707a3
          ;;  I have an example where we are in an svn:external which
c707a3
          ;;  is itself inside a svn:external, this need not be true:
c707a3
          ;;  the next line is not 'X dir' but just 'dir', so we
c707a3
          ;;  actually need to parse that line, or the results will
c707a3
          ;;  not contain dir!
c707a3
          ;; so we should merge lines 'X dir' with ' dir', but for now
c707a3
          ;; we just leave both in the results
c707a3
c707a3
          ;; My attempt to merge the lines uses skip-double-external-dir-entry-name
c707a3
          ;; and externals-map
1b1de0
          (setq skip-double-external-dir-entry-name (svn-match-string-no-properties 1))
c707a3
          ;; (message "Going to skip %s" skip-double-external-dir-entry-name)
c707a3
          nil)
1b1de0
         ((looking-at "--- Changelist") ; skip svn changelist header lines
1b1de0
          ;; See: http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
1b1de0
          nil)
cvsdist e1e786
         (t
4b6e5a
          (setq svn-marks (buffer-substring (point) (+ (point) svn-marks-length))
4b6e5a
                svn-file-mark (elt svn-marks 0)         ; 1st column - M,A,C,D,G,? etc
4b6e5a
                svn-property-mark (elt svn-marks 1)     ; 2nd column - M,C (properties)
c707a3
                svn-wc-locked-mark (elt svn-marks 2)    ; 3rd column - L or blank
4b6e5a
                svn-with-history-mark (elt svn-marks 3) ; 4th column - + or blank
f41b0b
                svn-switched-mark (elt svn-marks 4)     ; 5th column - S,X or blank
c707a3
                svn-repo-locked-mark (elt svn-marks 5)) ; 6th column - K,O,T,B or blank
c707a3
          (when svn-status-remote
f41b0b
            (setq svn-update-mark (elt svn-marks 7)))   ; 8th column - * or blank
4b6e5a
          (when (eq svn-property-mark ?\ )     (setq svn-property-mark nil))
c707a3
          (when (eq svn-wc-locked-mark ?\ )    (setq svn-wc-locked-mark nil))
4b6e5a
          (when (eq svn-with-history-mark ?\ ) (setq svn-with-history-mark nil))
4b6e5a
          (when (eq svn-switched-mark ?\ )     (setq svn-switched-mark nil))
4b6e5a
          (when (eq svn-update-mark ?\ )       (setq svn-update-mark nil))
c707a3
          (when (eq svn-repo-locked-mark ?\ )  (setq svn-repo-locked-mark nil))
4b6e5a
          (forward-char svn-marks-length)
cvsdist e1e786
          (skip-chars-forward " ")
c707a3
          ;; (message "after marks: '%s'" (buffer-substring (point) (line-end-position)))
cvsdist e1e786
          (cond
4b6e5a
           ((looking-at "\\([-?]\\|[0-9]+\\) +\\([-?]\\|[0-9]+\\) +\\([^ ]+\\) *\\(.+\\)$")
cvsdist e1e786
            (setq local-rev (svn-parse-rev-num (match-string 1))
cvsdist e1e786
                  last-change-rev (svn-parse-rev-num (match-string 2))
cvsdist e1e786
                  author (match-string 3)
cvsdist e1e786
                  path (match-string 4)))
4b6e5a
           ((looking-at "\\([-?]\\|[0-9]+\\) +\\([^ ]+\\)$")
4b6e5a
            (setq local-rev (svn-parse-rev-num (match-string 1))
4b6e5a
                  last-change-rev -1
4b6e5a
                  author "?"
4b6e5a
                  path (match-string 2)))
cvsdist e1e786
           ((looking-at "\\(.*\\)")
cvsdist e1e786
            (setq path (match-string 1)
cvsdist e1e786
                  local-rev -1
cvsdist e1e786
                  last-change-rev -1
c707a3
                  author (if (eq svn-file-mark ?X) "" "?"))) ;clear author of svn:externals dirs
cvsdist e1e786
           (t
cvsdist e1e786
            (error "Unknown status line format")))
cvsdist e1e786
          (unless path (setq path "."))
4b6e5a
          (setq dir (file-name-directory path))
4b6e5a
          (if (and (not svn-status-verbose) dir)
4b6e5a
              (let ((dirname (directory-file-name dir)))
4b6e5a
                (if (not (member dirname dir-set))
4b6e5a
                    (setq dir-set (cons dirname dir-set)))))
c707a3
          (if (and skip-double-external-dir-entry-name (string= skip-double-external-dir-entry-name path))
c707a3
              ;; merge this entry to a previous saved one
c707a3
              (let ((info (gethash path externals-map)))
c707a3
                ;; (message "skip-double-external-dir-entry-name: %s - path: %s" skip-double-external-dir-entry-name path)
c707a3
                (if info
c707a3
                    (progn
c707a3
                      (svn-status-line-info->set-localrev info local-rev)
c707a3
                      (svn-status-line-info->set-lastchangerev info last-change-rev)
c707a3
                      (svn-status-line-info->set-author info author)
c707a3
                      (svn-status-message 3 "merging entry for %s to %s" path info)
c707a3
                      (setq skip-double-external-dir-entry-name nil))
c707a3
                  (message "psvn: %s not handled correct, please report this case." path)))
c707a3
            (setq svn-status-info
c707a3
                  (cons (svn-status-make-line-info path
c707a3
                                                   (gethash path old-ui-information)
c707a3
                                                   svn-file-mark
c707a3
                                                   svn-property-mark
c707a3
                                                   local-rev
c707a3
                                                   last-change-rev
c707a3
                                                   author
c707a3
                                                   svn-update-mark
c707a3
                                                   svn-wc-locked-mark
c707a3
                                                   svn-with-history-mark
c707a3
                                                   svn-switched-mark
c707a3
                                                   svn-repo-locked-mark
c707a3
                                                   nil) ;;psvn-extra-info
c707a3
                        svn-status-info)))
c707a3
          (when (eq svn-file-mark ?X)
c707a3
            (svn-puthash (match-string 1) (car svn-status-info) externals-map)
c707a3
            (svn-status-message 3 "found external: %s %S" (match-string 1) (car svn-status-info)))
cvsdist e1e786
          (setq revision-width (max revision-width
357017
                                    (length (number-to-string local-rev))
357017
                                    (length (number-to-string last-change-rev))))
cvsdist e1e786
          (setq author-width (max author-width (length author)))))
357017
        (forward-line 1))
4b6e5a
      (unless svn-status-verbose
4b6e5a
        (setq svn-status-info (svn-status-make-dummy-dirs dir-set
4b6e5a
                                                          old-ui-information)))
cvsdist e1e786
      (setq svn-status-default-column
cvsdist e1e786
            (+ 6 revision-width revision-width author-width
cvsdist e1e786
               (if svn-status-short-mod-flag-p 3 0)))
4b6e5a
      (setq svn-status-line-format (format " %%c%%c%%c %%%ds %%%ds %%-%ds"
cvsdist e1e786
                                           revision-width
cvsdist e1e786
                                           revision-width
cvsdist e1e786
                                           author-width))
4b6e5a
      (setq svn-status-info (nreverse svn-status-info))
357017
      (when svn-status-sort-status-buffer
357017
        (setq svn-status-info (sort svn-status-info 'svn-status-sort-predicate))))))
cvsdist e1e786
cvsdist e1e786
;;(string-lessp "." "%") => nil
f41b0b
;;(svn-status-sort-predicate '(t t t ".") '(t t t "%")) => t
cvsdist e1e786
(defun svn-status-sort-predicate (a b)
4b6e5a
  "Return t if A should appear before B in the `svn-status-buffer-name' buffer.
cvsdist e1e786
A and B must be line-info's."
cvsdist e1e786
  (string-lessp (concat (svn-status-line-info->full-path a) "/")
cvsdist e1e786
                (concat (svn-status-line-info->full-path b) "/")))
cvsdist e1e786
cvsdist e1e786
(defun svn-status-remove-temp-file-maybe ()
cvsdist e1e786
  "Remove any (no longer required) temporary files created by psvn.el."
cvsdist e1e786
  (when svn-status-temp-file-to-remove
cvsdist e1e786
    (when (file-exists-p svn-status-temp-file-to-remove)
cvsdist e1e786
      (delete-file svn-status-temp-file-to-remove))
cvsdist e1e786
    (when (file-exists-p svn-status-temp-arg-file)
cvsdist e1e786
      (delete-file svn-status-temp-arg-file))
cvsdist e1e786
    (setq svn-status-temp-file-to-remove nil)))
cvsdist e1e786
cvsdist e1e786
(defun svn-status-remove-control-M ()
cvsdist e1e786
  "Remove ^M at end of line in the whole buffer."
cvsdist e1e786
  (interactive)
cvsdist e1e786
  (let ((buffer-read-only nil))
cvsdist e1e786
    (save-match-data
cvsdist e1e786
      (save-excursion
cvsdist e1e786
        (goto-char (point-min))
cvsdist e1e786
        (while (re-search-forward "\r$" (point-max) t)
cvsdist e1e786
          (replace-match "" nil nil))))))
cvsdist e1e786
f41b0b
(defun svn-fixup-tramp-exit ()
f41b0b
  "Helper function to handle tramp connections stopping with an exit output."
f41b0b
  (goto-char (point-max))
f41b0b
  (when (eq (svn-point-at-bol) (svn-point-at-eol))
f41b0b
    (forward-line -1))
f41b0b
  (beginning-of-line)
f41b0b
  (when (looking-at "exit")
f41b0b
    (delete-region (point) (svn-point-at-eol))))
f41b0b
f41b0b
(defun svn-fixup-tramp-output-maybe ()
f41b0b
  "Fixup leftover output when running via tramp"
f41b0b
  (when (fboundp 'file-remote-p)
f41b0b
    (when (file-remote-p default-directory)
f41b0b
      (svn-fixup-tramp-exit))))
f41b0b
cvsdist e1e786
(condition-case nil
cvsdist e1e786
    ;;(easy-menu-add-item nil '("tools") ["SVN Status" svn-status t] "PCL-CVS")
cvsdist e1e786
    (easy-menu-add-item nil '("tools") ["SVN Status" svn-status t])
cvsdist e1e786
  (error (message "psvn: could not install menu")))
cvsdist e1e786
cvsdist e1e786
(defvar svn-status-mode-map () "Keymap used in `svn-status-mode' buffers.")
1cd9ea
(put 'svn-status-mode-map 'risky-local-variable t) ;for Emacs 20.7
1cd9ea
(defvar svn-status-mode-mark-map ()
1cd9ea
  "Subkeymap used in `svn-status-mode' for mark commands.")
1cd9ea
(put 'svn-status-mode-mark-map      'risky-local-variable t) ;for Emacs 20.7
cvsdist e1e786
(defvar svn-status-mode-property-map ()
cvsdist e1e786
  "Subkeymap used in `svn-status-mode' for property commands.")
1cd9ea
(put 'svn-status-mode-property-map  'risky-local-variable t) ;for Emacs 20.7
357017
(defvar svn-status-mode-options-map ()
357017
  "Subkeymap used in `svn-status-mode' for option commands.")
1cd9ea
(put 'svn-status-mode-options-map   'risky-local-variable t) ;for Emacs 20.7
4b6e5a
(defvar svn-status-mode-trac-map ()
4b6e5a
  "Subkeymap used in `svn-status-mode' for trac issue tracker commands.")
1cd9ea
(put 'svn-status-mode-trac-map      'risky-local-variable t) ;for Emacs 20.7
4b6e5a
(defvar svn-status-mode-extension-map ()
4b6e5a
  "Subkeymap used in `svn-status-mode' for some seldom used commands.")
1cd9ea
(put 'svn-status-mode-extension-map 'risky-local-variable t) ;for Emacs 20.7
c707a3
(defvar svn-status-mode-branch-map ()
c707a3
  "Subkeymap used in `svn-status-mode' for branching commands.")
c707a3
(put 'svn-status-mode-extension-map 'risky-local-variable t) ;for Emacs 20.7
1b1de0
(defvar svn-status-mode-search-map ()
1b1de0
  "Subkeymap used in `svn-status-mode' for search commands.")
1b1de0
(put 'svn-status-mode-search-map      'risky-local-variable t) ;for Emacs 20.7
cvsdist e1e786
cvsdist e1e786
(when (not svn-status-mode-map)
cvsdist e1e786
  (setq svn-status-mode-map (make-sparse-keymap))
cvsdist e1e786
  (suppress-keymap svn-status-mode-map)
cvsdist e1e786
  ;; Don't use (kbd "<return>"); it's unreachable with GNU Emacs 21.3 on a TTY.
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "RET") 'svn-status-find-file-or-examine-directory)
4b6e5a
  (define-key svn-status-mode-map (kbd "<mouse-2>") 'svn-status-mouse-find-file-or-examine-directory)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "^") 'svn-status-examine-parent)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "s") 'svn-status-show-process-buffer)
c707a3
  (define-key svn-status-mode-map (kbd "h") 'svn-status-pop-to-partner-buffer)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "f") 'svn-status-find-files)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "o") 'svn-status-find-file-other-window)
c707a3
  (define-key svn-status-mode-map (kbd "C-o") 'svn-status-find-file-other-window-noselect)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "v") 'svn-status-view-file-other-window)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "e") 'svn-status-toggle-edit-cmd-flag)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "g") 'svn-status-update)
4b6e5a
  (define-key svn-status-mode-map (kbd "M-s") 'svn-status-update) ;; PCL-CVS compatibility
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "q") 'svn-status-bury-buffer)
c707a3
  (define-key svn-status-mode-map (kbd "x") 'svn-status-redraw-status-buffer)
c707a3
  (define-key svn-status-mode-map (kbd "H") 'svn-status-use-history)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "m") 'svn-status-set-user-mark)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "u") 'svn-status-unset-user-mark)
cvsdist e1e786
  ;; This matches a binding of `dired-unmark-all-files' in `dired-mode-map'
cvsdist e1e786
  ;; of both GNU Emacs and XEmacs.  It seems unreachable with XEmacs on
cvsdist e1e786
  ;; TTY, but if that's a problem then its Dired needs fixing too.
cvsdist e1e786
  ;; Or you could just use "*!".
cvsdist e1e786
  (define-key svn-status-mode-map "\M-\C-?" 'svn-status-unset-all-usermarks)
cvsdist e1e786
  ;; The key that normally deletes characters backwards should here
cvsdist e1e786
  ;; instead unmark files backwards.  In GNU Emacs, that would be (kbd
cvsdist e1e786
  ;; "DEL") aka [?\177], but XEmacs treats those as [(delete)] and
cvsdist e1e786
  ;; would bind a key that normally deletes forwards.  [(backspace)]
cvsdist e1e786
  ;; is unreachable with GNU Emacs on a tty.  Try to recognize the
cvsdist e1e786
  ;; dialect and act accordingly.
cvsdist e1e786
  ;;
cvsdist e1e786
  ;; XEmacs has a `delete-forward-p' function that checks the
cvsdist e1e786
  ;; `delete-key-deletes-forward' option.  We don't use those, for two
cvsdist e1e786
  ;; reasons: psvn.el may be loaded before user customizations, and
cvsdist e1e786
  ;; XEmacs allows simultaneous connections to multiple devices with
cvsdist e1e786
  ;; different keyboards.
cvsdist e1e786
  (define-key svn-status-mode-map
f41b0b
    (if (member (kbd "DEL") '([(delete)] [delete]))
f41b0b
        [(backspace)]         ; XEmacs
f41b0b
      (kbd "DEL"))            ; GNU Emacs
f41b0b
    'svn-status-unset-user-mark-backwards)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "$") 'svn-status-toggle-elide)
c707a3
  (define-key svn-status-mode-map (kbd "w") 'svn-status-copy-current-line-info)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd ".") 'svn-status-goto-root-or-return)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "I") 'svn-status-parse-info)
4b6e5a
  (define-key svn-status-mode-map (kbd "V") 'svn-status-svnversion)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "?") 'svn-status-toggle-hide-unknown)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "_") 'svn-status-toggle-hide-unmodified)
f41b0b
  (define-key svn-status-mode-map (kbd "z") 'svn-status-toggle-hide-externals)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "a") 'svn-status-add-file)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "A") 'svn-status-add-file-recursively)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "+") 'svn-status-make-directory)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "R") 'svn-status-mv)
c707a3
  (define-key svn-status-mode-map (kbd "C") 'svn-status-cp)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "D") 'svn-status-rm)
4b6e5a
  (define-key svn-status-mode-map (kbd "c") 'svn-status-commit)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "M-c") 'svn-status-cleanup)
c707a3
  (define-key svn-status-mode-map (kbd "k") 'svn-status-lock)
c707a3
  (define-key svn-status-mode-map (kbd "K") 'svn-status-unlock)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "U") 'svn-status-update-cmd)
2e0edb
  (define-key svn-status-mode-map (kbd "M-u") 'svn-status-update-cmd)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "r") 'svn-status-revert)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "l") 'svn-status-show-svn-log)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "i") 'svn-status-info)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "b") 'svn-status-blame)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "=") 'svn-status-show-svn-diff)
cvsdist e1e786
  ;; [(control ?=)] is unreachable on TTY, but you can use "*u" instead.
cvsdist e1e786
  ;; (Is the "u" mnemonic for something?)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "C-=") 'svn-status-show-svn-diff-for-marked-files)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "~") 'svn-status-get-specific-revision)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "E") 'svn-status-ediff-with-revision)
4b6e5a
1cd9ea
  (define-key svn-status-mode-map (kbd "n") 'svn-status-next-line)
1cd9ea
  (define-key svn-status-mode-map (kbd "p") 'svn-status-previous-line)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "<down>") 'svn-status-next-line)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "<up>") 'svn-status-previous-line)
4b6e5a
  (define-key svn-status-mode-map (kbd "C-x C-j") 'svn-status-dired-jump)
1b1de0
  (define-key svn-status-mode-map [down-mouse-3] 'svn-status-popup-menu))
1b1de0
1b1de0
(when (not svn-status-mode-mark-map)
cvsdist e1e786
  (setq svn-status-mode-mark-map (make-sparse-keymap))
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "*") svn-status-mode-mark-map)
cvsdist e1e786
  (define-key svn-status-mode-mark-map (kbd "!") 'svn-status-unset-all-usermarks)
cvsdist e1e786
  (define-key svn-status-mode-mark-map (kbd "?") 'svn-status-mark-unknown)
cvsdist e1e786
  (define-key svn-status-mode-mark-map (kbd "A") 'svn-status-mark-added)
cvsdist e1e786
  (define-key svn-status-mode-mark-map (kbd "M") 'svn-status-mark-modified)
1b1de0
  (define-key svn-status-mode-mark-map (kbd "P") 'svn-status-mark-modified-properties)
4b6e5a
  (define-key svn-status-mode-mark-map (kbd "D") 'svn-status-mark-deleted)
4b6e5a
  (define-key svn-status-mode-mark-map (kbd "*") 'svn-status-mark-changed)
c707a3
  (define-key svn-status-mode-mark-map (kbd ".") 'svn-status-mark-by-file-ext)
c707a3
  (define-key svn-status-mode-mark-map (kbd "%") 'svn-status-mark-filename-regexp)
1b1de0
  (define-key svn-status-mode-mark-map (kbd "s") 'svn-status-store-usermarks)
1b1de0
  (define-key svn-status-mode-mark-map (kbd "l") 'svn-status-load-usermarks)
cvsdist e1e786
  (define-key svn-status-mode-mark-map (kbd "u") 'svn-status-show-svn-diff-for-marked-files))
1b1de0
1b1de0
(when (not svn-status-mode-search-map)
1b1de0
  (setq svn-status-mode-search-map (make-sparse-keymap))
1b1de0
  (define-key svn-status-mode-search-map (kbd "g") 'svn-status-grep-files)
1b1de0
  (define-key svn-status-mode-search-map (kbd "s") 'svn-status-search-files)
1b1de0
  (define-key svn-status-mode-map (kbd "S") svn-status-mode-search-map))
1b1de0
cvsdist e1e786
(when (not svn-status-mode-property-map)
cvsdist e1e786
  (setq svn-status-mode-property-map (make-sparse-keymap))
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "l") 'svn-status-property-list)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "s") 'svn-status-property-set)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "d") 'svn-status-property-delete)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "e") 'svn-status-property-edit-one-entry)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "i") 'svn-status-property-ignore-file)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "I") 'svn-status-property-ignore-file-extension)
cvsdist e1e786
  ;; XEmacs 21.4.15 on TTY (vt420) converts `C-i' to `TAB',
cvsdist e1e786
  ;; which [(control ?i)] won't match.  Handle it separately.
cvsdist e1e786
  ;; On GNU Emacs, the following two forms bind the same key,
cvsdist e1e786
  ;; reducing clutter in `where-is'.
cvsdist e1e786
  (define-key svn-status-mode-property-map [(control ?i)] 'svn-status-property-edit-svn-ignore)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "TAB") 'svn-status-property-edit-svn-ignore)
f41b0b
  (define-key svn-status-mode-property-map (kbd "Xe") 'svn-status-property-edit-svn-externals)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "k") 'svn-status-property-set-keyword-list)
c707a3
  (define-key svn-status-mode-property-map (kbd "Ki") 'svn-status-property-set-keyword-id)
c707a3
  (define-key svn-status-mode-property-map (kbd "Kd") 'svn-status-property-set-keyword-date)
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "y") 'svn-status-property-set-eol-style)
4b6e5a
  (define-key svn-status-mode-property-map (kbd "x") 'svn-status-property-set-executable)
c707a3
  (define-key svn-status-mode-property-map (kbd "m") 'svn-status-property-set-mime-type)
cvsdist e1e786
  ;; TODO: Why is `svn-status-select-line' in `svn-status-mode-property-map'?
cvsdist e1e786
  (define-key svn-status-mode-property-map (kbd "RET") 'svn-status-select-line)
cvsdist e1e786
  (define-key svn-status-mode-map (kbd "P") svn-status-mode-property-map))
4b6e5a
(when (not svn-status-mode-extension-map)
4b6e5a
  (setq svn-status-mode-extension-map (make-sparse-keymap))
4b6e5a
  (define-key svn-status-mode-extension-map (kbd "v") 'svn-status-resolved)
4b6e5a
  (define-key svn-status-mode-extension-map (kbd "X") 'svn-status-resolve-conflicts)
1cd9ea
  (define-key svn-status-mode-extension-map (kbd "e") 'svn-status-export)
4b6e5a
  (define-key svn-status-mode-map (kbd "X") svn-status-mode-extension-map))
357017
(when (not svn-status-mode-options-map)
357017
  (setq svn-status-mode-options-map (make-sparse-keymap))
357017
  (define-key svn-status-mode-options-map (kbd "s") 'svn-status-save-state)
357017
  (define-key svn-status-mode-options-map (kbd "l") 'svn-status-load-state)
357017
  (define-key svn-status-mode-options-map (kbd "x") 'svn-status-toggle-sort-status-buffer)
c707a3
  (define-key svn-status-mode-options-map (kbd "v") 'svn-status-toggle-svn-verbose-flag)
4b6e5a
  (define-key svn-status-mode-options-map (kbd "f") 'svn-status-toggle-display-full-path)
4b6e5a
  (define-key svn-status-mode-options-map (kbd "t") 'svn-status-set-trac-project-root)
4b6e5a
  (define-key svn-status-mode-options-map (kbd "n") 'svn-status-set-module-name)
c707a3
  (define-key svn-status-mode-options-map (kbd "c") 'svn-status-set-changelog-style)
c707a3
  (define-key svn-status-mode-options-map (kbd "b") 'svn-status-set-branch-list)
357017
  (define-key svn-status-mode-map (kbd "O") svn-status-mode-options-map))
4b6e5a
(when (not svn-status-mode-trac-map)
4b6e5a
  (setq svn-status-mode-trac-map (make-sparse-keymap))
c707a3
  (define-key svn-status-mode-trac-map (kbd "w") 'svn-trac-browse-wiki)
4b6e5a
  (define-key svn-status-mode-trac-map (kbd "t") 'svn-trac-browse-timeline)
c707a3
  (define-key svn-status-mode-trac-map (kbd "m") 'svn-trac-browse-roadmap)
c707a3
  (define-key svn-status-mode-trac-map (kbd "r") 'svn-trac-browse-report)
c707a3
  (define-key svn-status-mode-trac-map (kbd "s") 'svn-trac-browse-source)
c707a3
  (define-key svn-status-mode-trac-map (kbd "i") 'svn-trac-browse-ticket)
c707a3
  (define-key svn-status-mode-trac-map (kbd "c") 'svn-trac-browse-changeset)
4b6e5a
  (define-key svn-status-mode-map (kbd "T") svn-status-mode-trac-map))
c707a3
(when (not svn-status-mode-branch-map)
c707a3
  (setq svn-status-mode-branch-map (make-sparse-keymap))
c707a3
  (define-key svn-status-mode-branch-map (kbd "d") 'svn-branch-diff)
c707a3
  (define-key svn-status-mode-map (kbd "B") svn-status-mode-branch-map))
cvsdist e1e786
cvsdist e1e786
(easy-menu-define svn-status-mode-menu svn-status-mode-map
cvsdist e1e786
  "'svn-status-mode' menu"
cvsdist e1e786
  '("SVN"
cvsdist e1e786
    ["svn status" svn-status-update t]
cvsdist e1e786
    ["svn update" svn-status-update-cmd t]
4b6e5a
    ["svn commit" svn-status-commit t]
cvsdist e1e786
    ["svn log" svn-status-show-svn-log t]
cvsdist e1e786
    ["svn info" svn-status-info t]
cvsdist e1e786
    ["svn blame" svn-status-blame t]
cvsdist e1e786
    ("Diff"
cvsdist e1e786
     ["svn diff current file" svn-status-show-svn-diff t]
cvsdist e1e786
     ["svn diff marked files" svn-status-show-svn-diff-for-marked-files t]
cvsdist e1e786
     ["svn ediff current file" svn-status-ediff-with-revision t]
4b6e5a
     ["svn resolve conflicts" svn-status-resolve-conflicts]
cvsdist e1e786
     )
1b1de0
    ("Search"
1b1de0
     ["Grep marked files" svn-status-grep-files t]
1b1de0
     ["Search marked files" svn-status-search-files t]
1b1de0
     )
cvsdist e1e786
    ["svn cat ..." svn-status-get-specific-revision t]
cvsdist e1e786
    ["svn add" svn-status-add-file t]
4b6e5a
    ["svn add recursively" svn-status-add-file-recursively t]
cvsdist e1e786
    ["svn mkdir..." svn-status-make-directory t]
cvsdist e1e786
    ["svn mv..." svn-status-mv t]
c707a3
    ["svn cp..." svn-status-cp t]
cvsdist e1e786
    ["svn rm..." svn-status-rm t]
1cd9ea
    ["svn export..." svn-status-export t]
cvsdist e1e786
    ["Up Directory" svn-status-examine-parent t]
cvsdist e1e786
    ["Elide Directory" svn-status-toggle-elide t]
cvsdist e1e786
    ["svn revert" svn-status-revert t]
cvsdist e1e786
    ["svn resolved" svn-status-resolved t]
cvsdist e1e786
    ["svn cleanup" svn-status-cleanup t]
c707a3
    ["svn lock" svn-status-lock t]
c707a3
    ["svn unlock" svn-status-unlock t]
cvsdist e1e786
    ["Show Process Buffer" svn-status-show-process-buffer t]
c707a3
    ("Branch"
c707a3
     ["diff" svn-branch-diff t]
c707a3
     ["Set Branch list" svn-status-set-branch-list t]
c707a3
     )
cvsdist e1e786
    ("Property"
cvsdist e1e786
     ["svn proplist" svn-status-property-list t]
cvsdist e1e786
     ["Set Multiple Properties..." svn-status-property-set t]
cvsdist e1e786
     ["Edit One Property..." svn-status-property-edit-one-entry t]
cvsdist e1e786
     ["svn propdel..." svn-status-property-delete t]
cvsdist e1e786
     "---"
cvsdist e1e786
     ["svn:ignore File..." svn-status-property-ignore-file t]
cvsdist e1e786
     ["svn:ignore File Extension..." svn-status-property-ignore-file-extension t]
cvsdist e1e786
     ["Edit svn:ignore Property" svn-status-property-edit-svn-ignore t]
cvsdist e1e786
     "---"
f41b0b
     ["Edit svn:externals Property" svn-status-property-edit-svn-externals t]
f41b0b
     "---"
4b6e5a
     ["Edit svn:keywords List" svn-status-property-set-keyword-list t]
c707a3
     ["Add/Remove Id to/from svn:keywords" svn-status-property-set-keyword-id t]
c707a3
     ["Add/Remove Date to/from svn:keywords" svn-status-property-set-keyword-date t]
c707a3
     "---"
4b6e5a
     ["Select svn:eol-style" svn-status-property-set-eol-style t]
4b6e5a
     ["Set svn:executable" svn-status-property-set-executable t]
c707a3
     ["Set svn:mime-type" svn-status-property-set-mime-type t]
cvsdist e1e786
     )
357017
    ("Options"
357017
     ["Save Options" svn-status-save-state t]
357017
     ["Load Options" svn-status-load-state t]
4b6e5a
     ["Set Trac project root" svn-status-set-trac-project-root t]
4b6e5a
     ["Set Short module name" svn-status-set-module-name t]
c707a3
     ["Set Changelog style" svn-status-set-changelog-style t]
c707a3
     ["Set Branch list" svn-status-set-branch-list t]
c707a3
     ["Sort the *svn-status* buffer" svn-status-toggle-sort-status-buffer
357017
      :style toggle :selected svn-status-sort-status-buffer]
c707a3
     ["Use -v for svn status calls" svn-status-toggle-svn-verbose-flag
c707a3
      :style toggle :selected svn-status-verbose]
c707a3
     ["Display full path names" svn-status-toggle-display-full-path
4b6e5a
      :style toggle :selected svn-status-display-full-path]
4b6e5a
     )
4b6e5a
    ("Trac"
c707a3
     ["Browse wiki" svn-trac-browse-wiki t]
4b6e5a
     ["Browse timeline" svn-trac-browse-timeline t]
c707a3
     ["Browse roadmap" svn-trac-browse-roadmap t]
c707a3
     ["Browse source" svn-trac-browse-source t]
c707a3
     ["Browse report" svn-trac-browse-report t]
c707a3
     ["Browse ticket" svn-trac-browse-ticket t]
c707a3
     ["Browse changeset" svn-trac-browse-changeset t]
4b6e5a
     ["Set Trac project root" svn-status-set-trac-project-root t]
357017
     )
cvsdist e1e786
    "---"
cvsdist e1e786
    ["Edit Next SVN Cmd Line" svn-status-toggle-edit-cmd-flag t]
cvsdist e1e786
    ["Work Directory History..." svn-status-use-history t]
cvsdist e1e786
    ("Mark / Unmark"
4b6e5a
     ["Mark" svn-status-set-user-mark t]
4b6e5a
     ["Unmark" svn-status-unset-user-mark t]
cvsdist e1e786
     ["Unmark all" svn-status-unset-all-usermarks t]
4b6e5a
     "---"
cvsdist e1e786
     ["Mark/Unmark unknown" svn-status-mark-unknown t]
cvsdist e1e786
     ["Mark/Unmark modified" svn-status-mark-modified t]
1b1de0
     ["Mark/Unmark modified properties" svn-status-mark-modified-properties t]
1b1de0
     ["Mark/Unmark added" svn-status-mark-added t]
4b6e5a
     ["Mark/Unmark deleted" svn-status-mark-deleted t]
4b6e5a
     ["Mark/Unmark modified/added/deleted" svn-status-mark-changed t]
c707a3
     ["Mark/Unmark filename by extension" svn-status-mark-by-file-ext t]
c707a3
     ["Mark/Unmark filename by regexp" svn-status-mark-filename-regexp t]
1b1de0
     ["Store Usermarks" svn-status-store-usermarks t]
1b1de0
     ["Load Usermarks" svn-status-load-usermarks t]
cvsdist e1e786
     )
cvsdist e1e786
    ["Hide Unknown" svn-status-toggle-hide-unknown
cvsdist e1e786
     :style toggle :selected svn-status-hide-unknown]
cvsdist e1e786
    ["Hide Unmodified" svn-status-toggle-hide-unmodified
cvsdist e1e786
     :style toggle :selected svn-status-hide-unmodified]
f41b0b
    ["Hide Externals" svn-status-toggle-hide-externals
f41b0b
     :style toggle :selected svn-status-hide-externals]
c707a3
    ["Show Client versions" svn-status-version t]
c707a3
    ["Prepare bug report" svn-prepare-bug-report t]
cvsdist e1e786
    ))
cvsdist e1e786
c707a3
(defvar svn-status-file-popup-menu-list
c707a3
  '(["open" svn-status-find-file-other-window t]
c707a3
    ["svn diff" svn-status-show-svn-diff t]
c707a3
    ["svn commit" svn-status-commit t]
c707a3
    ["svn log" svn-status-show-svn-log t]
c707a3
    ["svn blame" svn-status-blame t]
c707a3
    ["mark" svn-status-set-user-mark t]
c707a3
    ["unmark" svn-status-unset-user-mark t]
c707a3
    ["svn add" svn-status-add-file t]
c707a3
    ["svn add recursively" svn-status-add-file-recursively t]
c707a3
    ["svn mv..." svn-status-mv t]
c707a3
    ["svn rm..." svn-status-rm t]
c707a3
    ["svn lock" svn-status-lock t]
c707a3
    ["svn unlock" svn-status-unlock t]
c707a3
    ["svn info" svn-status-info t]
c707a3
    ) "A list of menu entries for `svn-status-popup-menu'")
c707a3
c707a3
;; extend svn-status-file-popup-menu-list via:
c707a3
;; (add-to-list 'svn-status-file-popup-menu-list ["commit" svn-status-commit t])
4b6e5a
4b6e5a
(defun svn-status-popup-menu (event)
c707a3
  "Display a file specific popup menu"
4b6e5a
  (interactive "e")
4b6e5a
  (mouse-set-point event)
4b6e5a
  (let* ((line-info (svn-status-get-line-information))
4b6e5a
         (name (svn-status-line-info->filename line-info)))
4b6e5a
    (when line-info
4b6e5a
      (easy-menu-define svn-status-actual-popup-menu nil nil
c707a3
        (append (list name) svn-status-file-popup-menu-list))
4b6e5a
      (svn-status-face-set-temporary-during-popup
a73eb4
       'svn-status-marked-popup-face (svn-point-at-bol) (svn-point-at-eol)
4b6e5a
       svn-status-actual-popup-menu))))
4b6e5a
4b6e5a
(defun svn-status-face-set-temporary-during-popup (face begin end menu &optional prefix)
4b6e5a
  "Put FACE on BEGIN and END in the buffer during Popup MENU.
4b6e5a
PREFIX is passed to `popup-menu'."
4b6e5a
  (let (o)
4b6e5a
    (unwind-protect
4b6e5a
        (progn
4b6e5a
          (setq o (make-overlay begin end))
4b6e5a
          (overlay-put o 'face face)
f41b0b
          (save-excursion (sit-for 0))
4b6e5a
          (popup-menu menu prefix))
4b6e5a
      (delete-overlay o))))
4b6e5a
cvsdist e1e786
(defun svn-status-mode ()
4b6e5a
  "Major mode used by psvn.el to display the output of \"svn status\".
4b6e5a
4b6e5a
The Output has the following format:
4b6e5a
  FPH BASE CMTD Author   em File
4b6e5a
F = Filemark
4b6e5a
P = Property mark