From 5bcc9f06410335d6cf54325f10a11ed77006f61f Mon Sep 17 00:00:00 2001 From: James Antill Date: Mon, 8 Aug 2022 14:08:13 -0400 Subject: [PATCH] Import rpm: b6e4734d78ea3b740513dd461e779baf56fe8aa8 --- .gitignore | 1 + clog2markdown | 27 + filter-requires.sh | 13 + gating.yaml | 9 + mirrors | 1 + psvn-init.el | 3 + psvn.el | 6562 +++++++++++++++++++++++ pullrev.sh | 53 + sources | 1 + subversion-1.12.0-linking.patch | 84 + subversion-1.14.0-findpy.patch | 11 + subversion-1.14.0-soversion.patch | 19 + subversion-1.14.0-testwarn.patch | 14 + subversion-1.14.1-CVE-2022-24070.patch | 41 + subversion-1.14.1-fixjavatests.patch | 30 + subversion-1.14.1-testnoautoprops.patch | 14 + subversion-1.8.0-rubybind.patch | 24 + subversion-1.8.5-swigplWall.patch | 16 + subversion.conf | 41 + subversion.spec | 1028 ++++ svnserve.service | 13 + svnserve.sysconf | 4 + svnserve.tmpfiles | 1 + upstream | 1 + upstream-key.gpg | 2358 ++++++++ 25 files changed, 10369 insertions(+) create mode 100644 .gitignore create mode 100755 clog2markdown create mode 100755 filter-requires.sh create mode 100644 gating.yaml create mode 100644 mirrors create mode 100644 psvn-init.el create mode 100644 psvn.el create mode 100755 pullrev.sh create mode 100644 sources create mode 100644 subversion-1.12.0-linking.patch create mode 100644 subversion-1.14.0-findpy.patch create mode 100644 subversion-1.14.0-soversion.patch create mode 100644 subversion-1.14.0-testwarn.patch create mode 100644 subversion-1.14.1-CVE-2022-24070.patch create mode 100644 subversion-1.14.1-fixjavatests.patch create mode 100644 subversion-1.14.1-testnoautoprops.patch create mode 100644 subversion-1.8.0-rubybind.patch create mode 100644 subversion-1.8.5-swigplWall.patch create mode 100644 subversion.conf create mode 100644 subversion.spec create mode 100644 svnserve.service create mode 100644 svnserve.sysconf create mode 100644 svnserve.tmpfiles create mode 100644 upstream create mode 100644 upstream-key.gpg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4264f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/subversion-1.14.1.tar.bz2 diff --git a/clog2markdown b/clog2markdown new file mode 100755 index 0000000..0acb69e --- /dev/null +++ b/clog2markdown @@ -0,0 +1,27 @@ +#!/bin/sh + +version=$1 + +echo "This update includes the latest stable release of _Apache Subversion_, version **${1}**". +echo + +curl --silent -n "http://svn.apache.org/repos/asf/subversion/tags/$1/CHANGES" | \ +sed -n " +/^#/d; +/^Version ${1/-rc*/}/,/^Version /{ +/, from \/branches/d; +/repos\/asf\/subversion\/tags/d; +s,#\([0-9]*\),[SVN-\1](https://issues.apache.org/jira/browse/SVN-\1),; +s/(r[0-9, retal]+)\*//g; +s/^ *//; +s/ +/ /g; +s/^ *- \(.*\)$/#### \1/; +s/\(.*visible changes.*:\)$/### \1/; +/^ *$/d; +/Windows/d +/^Version /d +s,(r1.*),,g +s,\(@[0-9]*\),\\\1,g +p; +} +" - diff --git a/filter-requires.sh b/filter-requires.sh new file mode 100755 index 0000000..26131c9 --- /dev/null +++ b/filter-requires.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Munge Perl requirements: +# - remove dependency on Config::Inifiles +# - only require File::Path >= 1.04, not >= 1.404 +# (since rpmvercmp thinks 04 < 1.404, not unreasonably) +# - filter out requirements for SVN:: modules; otherwise +# subversion requires subversion-perl +/usr/lib/rpm/perl.req $* | +sed -e '/perl(Config::IniFiles)/d' \ + -e '/perl(SVN::/d' \ + -e 's/perl(File::Path) >= 1.0404/perl(File::Path) >= 1.04/' + + diff --git a/gating.yaml b/gating.yaml new file mode 100644 index 0000000..2e4e68f --- /dev/null +++ b/gating.yaml @@ -0,0 +1,9 @@ +--- !Policy +product_versions: + - rhel-9 +decision_context: osci_compose_gate +rules: + - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional} + - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier2.functional} + - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier3.functional} + - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.acceptance-tier.functional} diff --git a/mirrors b/mirrors new file mode 100644 index 0000000..bb12745 --- /dev/null +++ b/mirrors @@ -0,0 +1 @@ +http://subversion.tigris.org/downloads diff --git a/psvn-init.el b/psvn-init.el new file mode 100644 index 0000000..cbe7cc3 --- /dev/null +++ b/psvn-init.el @@ -0,0 +1,3 @@ +(defalias 'svn-examine 'svn-status) +(autoload 'svn-status "psvn" "Examine the status of Subversion working copy in +directory DIR.") diff --git a/psvn.el b/psvn.el new file mode 100644 index 0000000..f775b67 --- /dev/null +++ b/psvn.el @@ -0,0 +1,6562 @@ +;;; psvn.el --- Subversion interface for emacs +;; Copyright (C) 2002-2015 by Stefan Reichoer + +;; Author: Stefan Reichoer +;; Note: This version is currently not under svn control +;; For the revision date see svn-psvn-revision below + +;; psvn.el is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; psvn.el is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary + +;; psvn.el is tested with GNU Emacs 21.3 on windows, debian linux, +;; freebsd5, red hat el4, ubuntu 11.10 with svn 1.6.12 + +;; psvn.el needs at least svn 1.1.0 +;; if you upgrade to a higher version, you need to do a fresh checkout + +;; psvn.el is an interface for the revision control tool subversion +;; (see http://subversion.tigris.org) +;; psvn.el provides a similar interface for subversion as pcl-cvs for cvs. +;; At the moment the following commands are implemented: +;; +;; M-x svn-status: run 'svn -status -v' +;; M-x svn-examine (like pcl-cvs cvs-examine) is alias for svn-status +;; +;; and show the result in the svn-status-buffer-name buffer (normally: *svn-status*). +;; If svn-status-verbose is set to nil, only "svn status" without "-v" +;; is run. Currently you have to toggle this variable manually. +;; This buffer uses svn-status mode in which the following keys are defined: +;; g - svn-status-update: run 'svn status -v' +;; M-s - svn-status-update: run 'svn status -v' +;; C-u g - svn-status-update: run 'svn status -vu' +;; = - svn-status-show-svn-diff run 'svn diff' +;; l - svn-status-show-svn-log run 'svn log' +;; i - svn-status-info run 'svn info' +;; r - svn-status-revert run 'svn revert' +;; X v - svn-status-resolved run 'svn resolved' +;; U - svn-status-update-cmd run 'svn update' +;; M-u - svn-status-update-cmd run 'svn update' +;; c - svn-status-commit run 'svn commit' +;; a - svn-status-add-file run 'svn add --non-recursive' +;; A - svn-status-add-file-recursively run 'svn add' +;; + - svn-status-make-directory run 'svn mkdir' +;; R - svn-status-mv run 'svn mv' +;; C - svn-status-cp run 'svn cp' +;; D - svn-status-rm run 'svn rm' +;; M-c - svn-status-cleanup run 'svn cleanup' +;; k - svn-status-lock run 'svn lock' +;; K - svn-status-unlock run 'svn unlock' +;; b - svn-status-blame run 'svn blame' +;; X e - svn-status-export run 'svn export' +;; RET - svn-status-find-file-or-examine-directory +;; ^ - svn-status-examine-parent +;; ~ - svn-status-get-specific-revision +;; E - svn-status-ediff-with-revision +;; X X - svn-status-resolve-conflicts +;; S g - svn-status-grep-files +;; S s - svn-status-search-files +;; s - svn-status-show-process-buffer +;; h - svn-status-pop-to-partner-buffer +;; e - svn-status-toggle-edit-cmd-flag +;; ? - svn-status-toggle-hide-unknown +;; _ - svn-status-toggle-hide-unmodified +;; z - svn-status-toggle-hide-externals +;; m - svn-status-set-user-mark +;; u - svn-status-unset-user-mark +;; $ - svn-status-toggle-elide +;; w - svn-status-copy-current-line-info +;; DEL - svn-status-unset-user-mark-backwards +;; * ! - svn-status-unset-all-usermarks +;; * ? - svn-status-mark-unknown +;; * A - svn-status-mark-added +;; * M - svn-status-mark-modified +;; * P - svn-status-mark-modified-properties +;; * D - svn-status-mark-deleted +;; * * - svn-status-mark-changed +;; * . - svn-status-mark-by-file-ext +;; * % - svn-status-mark-filename-regexp +;; * s - svn-status-store-usermarks +;; * l - svn-status-load-usermarks +;; . - svn-status-goto-root-or-return +;; f - svn-status-find-file +;; o - svn-status-find-file-other-window +;; C-o - svn-status-find-file-other-window-noselect +;; v - svn-status-view-file-other-window +;; I - svn-status-parse-info +;; V - svn-status-svnversion +;; P l - svn-status-property-list +;; P s - svn-status-property-set +;; P d - svn-status-property-delete +;; P e - svn-status-property-edit-one-entry +;; P i - svn-status-property-ignore-file +;; P I - svn-status-property-ignore-file-extension +;; P C-i - svn-status-property-edit-svn-ignore +;; P X e - svn-status-property-edit-svn-externals +;; P k - svn-status-property-set-keyword-list +;; P K i - svn-status-property-set-keyword-id +;; P K d - svn-status-property-set-keyword-date +;; P y - svn-status-property-set-eol-style +;; P x - svn-status-property-set-executable +;; P m - svn-status-property-set-mime-type +;; H - svn-status-use-history +;; x - svn-status-update-buffer +;; q - svn-status-bury-buffer + +;; C-x C-j - svn-status-dired-jump + +;; The output in the buffer contains this header to ease reading +;; of svn output: +;; FPH BASE CMTD Author em File +;; F = Filemark +;; P = Property mark +;; H = History mark +;; BASE = local base revision +;; CMTD = last committed revision +;; Author = author of change +;; em = "**" or "(Update Available)" [see `svn-status-short-mod-flag-p'] +;; if file can be updated +;; File = path/filename +;; + +;; To use psvn.el put the following line in your .emacs: +;; (require 'psvn) +;; Start the svn interface with M-x svn-status + +;; The latest version of psvn.el can be found at: +;; http://www.xsteve.at/prg/emacs/psvn.el + +;; TODO: +;; * shortcut for svn propset svn:keywords "Date" psvn.el +;; * docstrings for the functions +;; * perhaps shortcuts for ranges, dates +;; * when editing the command line - offer help from the svn client +;; * finish svn-status-property-set +;; * Add repository browser +;; * Get rid of all byte-compiler warnings +;; * SVK working copy support +;; * multiple independent buffers in svn-status-mode +;; There are "TODO" comments in other parts of this file as well. + +;; Overview over the implemented/not (yet) implemented svn sub-commands: +;; * add implemented +;; * blame implemented +;; * cat implemented +;; * checkout (co) implemented +;; * cleanup implemented +;; * commit (ci) implemented +;; * copy (cp) implemented +;; * delete (del, remove, rm) implemented +;; * diff (di) implemented +;; * export implemented +;; * help (?, h) +;; * import used (in svn-admin-create-trunk-directory) +;; * info implemented +;; * list (ls) implemented +;; * lock implemented +;; * log implemented +;; * merge +;; * mkdir implemented +;; * move (mv, rename, ren) implemented +;; * propdel (pdel) implemented +;; * propedit (pedit, pe) not needed +;; * propget (pget, pg) used (in svn-status-property-edit) +;; * proplist (plist, pl) implemented +;; * propset (pset, ps) used (in svn-prop-edit-do-it) +;; * resolved implemented +;; * revert implemented +;; * status (stat, st) implemented +;; * switch (sw) +;; * unlock implemented +;; * update (up) implemented + +;; For the not yet implemented commands you should use the command line +;; svn client. If there are user requests for any missing commands I will +;; probably implement them. + +;; There is also limited support for the web-based software project management and bug/issue tracking system trac +;; Trac ticket links can be enabled in the *svn-log* buffers when using the following: +;; (setq svn-log-link-handlers '(trac-ticket-short)) + +;; --------------------------- +;; Frequently asked questions: +;; --------------------------- + +;; Q1: I need support for user names with blanks/spaces +;; A1: Add the user names to svn-user-names-including-blanks and set the +;; svn-pre-parse-status-hook. +;; The problem is, that the user names and the file names from the svn status +;; output can both contain blanks. Blanks in file names are supported. +;; the svn-user-names-including-blanks list is used to replace the spaces +;; in the user names with - to overcome this problem + +;; Q2: My svn-update command it taking a really long time. How can I +;; see what's going on? +;; A2: In the *svn-status* buffer press "s". + +;; Q3: How do I enter a username and password? +;; A3: In the *svn-status* buffer press "s", switch to the +;; *svn-process* buffer and press enter. You will be prompted for +;; username and password. + +;; Q4: What does "?", "M", and "C" in the first column of the +;; *svn-status* buffer mean? +;; A4: "?" means the file(s) is not under Subversion control +;; "M" means you have a locally modified file +;; "C" means there is a conflict +;; "@$&#!" means someone is saying nasty things to you + + +;; Comments / suggestions and bug reports are welcome! + +;; Development notes +;; ----------------- + +;; "svn-" is the package prefix used in psvn.el. There are also longer +;; prefixes which clarify the code and help symbol completion, but they +;; are not intended to prevent name clashes with other packages. All +;; interactive commands meant to be used only in a specific mode should +;; have names beginning with the name of that mode: for example, +;; "svn-status-add-file" in "svn-status-mode". "psvn" should be used +;; only in names of files, customization groups, and features. If SVK +;; support is ever added, it should use "svn-svk-" when no existing +;; prefix is applicable. + +;; Many of the variables marked as `risky-local-variable' are probably +;; impossible to abuse, as the commands that read them are used only in +;; buffers that are not visiting any files. Better safe than sorry. + +;;; Code: + +(defconst svn-psvn-revision "2015-07-20, 21:42:00" "The revision date of psvn.") + + +(require 'easymenu) + +(eval-when-compile (require 'dired)) +(eval-when-compile (require 'ediff-util)) +(eval-when-compile (require 'ediff-wind)) +(eval-when-compile (require 'vc-hooks)) +(eval-when-compile (require 'elp)) +(eval-when-compile (require 'pp)) + +(condition-case nil + (progn + (require 'diff-mode)) + (error nil)) + + +;;; user setable variables +(defcustom svn-status-verbose t + "*Add '-v' to svn status call. +This can be toggled with \\[svn-status-toggle-svn-verbose-flag]." + :type 'boolean + :group 'psvn) +(defcustom svn-log-edit-file-name "++svn-log++" + "*Name of a saved log file. +This can be either absolute, or relative to the default directory +of the `svn-log-edit-buffer-name' buffer." + :type 'file + :group 'psvn) +(put 'svn-log-edit-file-name 'risky-local-variable t) +(defcustom svn-log-edit-insert-files-to-commit t + "*Insert the filelist to commit in the *svn-log* buffer" + :type 'boolean + :group 'psvn) +(defcustom svn-log-edit-show-diff-for-commit nil + "*Show the diff being committed when you run `svn-status-commit.'." + :type 'boolean + :group 'psvn) +(defcustom svn-log-edit-use-log-edit-mode + (and (condition-case nil (require 'log-edit) (error nil)) t) + "*Use log-edit-mode as base for svn-log-edit-mode +This variable takes effect only when psvn.el is being loaded." + :type 'boolean + :group 'psvn) +(defcustom svn-log-edit-paragraph-start + "$\\|[ \t]*$\\|##.*$\\|\\*.*:.*$\\|[ \t]+(.+):.*$" + "*Value used for `paragraph-start' in `svn-log-edit-buffer-name' buffer." + :type 'regexp + :group 'psvn) +(defcustom svn-log-edit-paragraph-separate "$\\|##.*$" + "*Value used for `paragraph-separate' in `svn-log-edit-buffer-name' buffer." + :type 'regexp + :group 'psvn) +(defcustom svn-status-hide-unknown nil + "*Hide unknown files in `svn-status-buffer-name' buffer. +This can be toggled with \\[svn-status-toggle-hide-unknown]." + :type 'boolean + :group 'psvn) +(defcustom svn-status-hide-unmodified nil + "*Hide unmodified files in `svn-status-buffer-name' buffer. +This can be toggled with \\[svn-status-toggle-hide-unmodified]." + :type 'boolean + :group 'psvn) +(defcustom svn-status-hide-externals nil + "*Hide external files in `svn-status-buffer-name' buffer. +This can be toggled with \\[svn-status-toggle-hide-externals]." + :type 'boolean + :group 'psvn) +(defcustom svn-status-sort-status-buffer t + "*Whether to sort the `svn-status-buffer-name' buffer. + +Setting this variable to nil speeds up \\[M-x svn-status], however the +listing may then become incorrect. + +This can be toggled with \\[svn-status-toggle-sort-status-buffer]." + :type 'boolean + :group 'psvn) + +(defcustom svn-status-ediff-delete-temporary-files nil + "*Whether to delete temporary ediff files. If set to ask, ask the user" + :type '(choice (const t) + (const nil) + (const ask)) + :group 'psvn) + +(defcustom svn-status-changelog-style 'changelog + "*The changelog style that is used for `svn-file-add-to-changelog'. +Possible values are: + 'changelog: use `add-change-log-entry-other-window' + 'svn-dev: use commit messages that are used by the svn developers + a function: This function is called to add a new entry to the changelog file. +" + :type '(set (const changelog) + (const svn-dev)) + :group 'psvn) + +(defcustom svn-status-unmark-files-after-list '(commit revert) + "*List of operations after which all user marks will be removed. +Possible values are: commit, revert." + :type '(set (const commit) + (const revert)) + :group 'psvn) + +(defcustom svn-status-preserve-window-configuration t + "*Try to preserve the window configuration." + :type 'boolean + :group 'psvn) + +(defcustom svn-status-auto-revert-buffers t + "*Auto revert buffers that have changed on disk." + :type 'boolean + :group 'psvn) + +(defcustom svn-status-fancy-file-state-in-modeline t + "*Show a color dot in the modeline that describes the state of the current file." + :type 'boolean + :group 'psvn) + +(defcustom svn-status-indentation 2 + "*Indenation per directory level in the `svn-status-buffer-name' buffer." + :type 'integer + :group 'psvn) + +(defcustom svn-status-negate-meaning-of-arg-commands '() + "*List of operations that should use a negated meaning of the prefix argument. +The supported functions are `svn-status' and `svn-status-set-user-mark'." + :type '(set (function-item svn-status) + (function-item svn-status-set-user-mark)) + :group 'psvn) + +(defcustom svn-status-svn-executable "svn" + "*The name of the svn executable. +This can be either absolute or looked up on `exec-path'." + ;; Don't use (file :must-match t). It doesn't know about `exec-path'. + :type 'file + :group 'psvn) +(put 'svn-status-svn-executable 'risky-local-variable t) + +(defcustom svn-status-default-export-directory "~/" "*The default directory that is suggested svn export." + :type 'file + :group 'psvn) + +(defcustom svn-status-svn-environment-var-list '("LC_MESSAGES=C" "LC_ALL=") + "*A list of environment variables that should be set for that svn process. +Each element is either a string \"VARIABLE=VALUE\" which will be added to +the environment when svn is run, or just \"VARIABLE\" which causes that +variable to be entirely removed from the environment. + +The default setting is '(\"LC_MESSAGES=C\" \"LC_ALL=\"). This ensures that the svn command +line client does not output localized strings. psvn.el relies on the english +messages." + :type '(repeat string) + :group 'psvn) +(put 'svn-status-svn-environment-var-list 'risky-local-variable t) + +(defcustom svn-browse-url-function nil + ;; If the user hasn't changed `svn-browse-url-function', then changing + ;; `browse-url-browser-function' should affect psvn even after it has + ;; been loaded. + "Function to display a Subversion related WWW page in a browser. +So far, this is used only for \"trac\" issue tracker integration. +By default, this is nil, which means use `browse-url-browser-function'. +Any non-nil value overrides that variable, with the same syntax." + ;; It would be nice to show the full list of browsers supported by + ;; browse-url, but (custom-variable-type 'browse-url-browser-function) + ;; returns just `function' if browse-url has not yet been loaded, + ;; and there seems to be no easy way to autoload browse-url when + ;; the custom-type of svn-browse-url-function is actually needed. + ;; So I'll only offer enough choices to cover all supported types. + :type `(choice (const :tag "Specified by `browse-url-browser-function'" nil) + (function :value browse-url-default-browser + ;; In XEmacs 21.4.17, the `function' widget matches + ;; all objects. Constrain it here so that alists + ;; fall through to the next choice. Accept either + ;; a symbol (fbound or not) or a lambda expression. + :match ,(lambda (widget value) + (or (symbolp value) (functionp value)))) + (svn-alist :tag "Regexp/function association list" + :key-type regexp :value-type function + :value (("." . browse-url-default-browser)))) + :link '(emacs-commentary-link "browse-url") + :group 'psvn) +;; (put 'svn-browse-url-function 'risky-local-variable t) +;; already implied by "-function" suffix + +(defcustom svn-log-edit-header + "## Lines starting with '## ' will be removed from the log message.\n" + "*Header content of the *svn-log* buffer" + :type 'string + :group 'psvn) + +(defcustom svn-status-window-alist + '((diff "*svn-diff*") (log "*svn-log*") (info t) (blame t) (proplist t) (update t)) + "An alist to specify which windows should be used for svn command outputs. +The following keys are supported: diff, log, info, blame, proplist, update. +The following values can be given: +nil ... show in `svn-process-buffer-name' buffer +t ... show in dedicated *svn-info* buffer +invisible ... don't show the buffer (eventually useful for update) +a string ... show in a buffer named string" + :type '(svn-alist + :key-type symbol + :value-type (group + (choice + (const :tag "Show in *svn-process* buffer" nil) + (const :tag "Show in dedicated *svn-info* buffer" t) + (const :tag "Don't show the output" invisible) + (string :tag "Show in a buffer named")))) + :options '(diff log info blame proplist update) + :group 'psvn) + +(defcustom svn-status-short-mod-flag-p t + "*Whether the mark for out of date files is short or long. + +If this variable is is t, and a file is out of date (i.e., there is a newer +version in the repository than the working copy), then the file will +be marked by \"**\" + +If this variable is nil, and the file is out of date then the longer phrase +\"(Update Available)\" is used. + +In either case the mark gets the face +`svn-status-update-available-face', and will only be visible if +`\\[svn-status-update]' is run with a prefix argument" + :type '(choice (const :tag "Short \"**\"" t) + (const :tag "Long \"(Update Available)\"" nil)) + :group 'psvn) + +(defvar svn-status-debug-level 0 "The psvn.el debugging verbosity level. +The higher the number, the more debug messages are shown. + +See `svn-status-message' for the meaning of values for that variable.") + +(defvar svn-bookmark-list nil "A list of locations for a quick access via `svn-status-via-bookmark'") +;;(setq svn-bookmark-list '(("proj1" . "~/work/proj1") +;; ("doc1" . "~/docs/doc1"))) + +(defvar svn-status-buffer-name "*svn-status*" "Name for the svn status buffer") +(defvar svn-process-buffer-name " *svn-process*" "Name for the svn process buffer") +(defvar svn-log-edit-buffer-name "*svn-log-edit*" "Name for the svn log-edit buffer") + +(defcustom svn-status-use-header-line + (if (boundp 'header-line-format) t 'inline) + "*Whether a header line should be used. +When t: Use the emacs header line +When 'inline: Insert the header line in the `svn-status-buffer-name' buffer +Otherwise: Don't display a header line" + :type '(choice (const :tag "Show column titles as a header line" t) + (const :tag "Insert column titles as text in the buffer" inline) + (other :tag "No column titles" nil)) + :group 'psvn) + +;;; default arguments to pass to svn commands +;; TODO: When customizing, an option menu or completion might be nice.... +(defcustom svn-status-default-log-arguments '("-v") + "*List of arguments to pass to svn log. +\(used in `svn-status-show-svn-log'; override these by giving prefixes\)." + :type '(repeat string) + :group 'psvn) +(put 'svn-status-default-log-arguments 'risky-local-variable t) + +(defcustom svn-status-default-commit-arguments '() + "*List of arguments to pass to svn commit. +If you don't like recursive commits, set this value to (\"-N\") +or mark the directory before committing it. +Do not put an empty string here, except as an argument of an option: +Subversion and the operating system may treat that as a file name +equivalent to \".\", so you would commit more than you intended." + :type '(repeat string) + :group 'psvn) +(put 'svn-status-default-commit-arguments 'risky-local-variable t) + +(defcustom svn-status-default-diff-arguments '("-x" "--ignore-eol-style") + "*A list of arguments that is passed to the svn diff command. +When the built in diff command is used, +the following options are available: --ignore-eol-style, --ignore-space-change, +--ignore-all-space, --ignore-eol-style. +The following setting ignores eol style changes and all white space changes: +'(\"-x\" \"--ignore-eol-style --ignore-all-space\") + +If you'd like to suppress whitespace changes using the external diff command +use the following value: +'(\"--diff-cmd\" \"diff\" \"-x\" \"-wbBu\") + +" + :type '(repeat string) + :group 'psvn) +(put 'svn-status-default-diff-arguments 'risky-local-variable t) + +(defcustom svn-status-default-status-arguments '() + "*A list of arguments that is passed to the svn status command. +The following options are available: --ignore-externals + +" + :type '(repeat string) + :group 'psvn) +(put 'svn-status-default-status-arguments 'risky-local-variable t) + +(defcustom svn-status-default-blame-arguments '("-x" "--ignore-eol-style") + "*A list of arguments that is passed to the svn blame command. +See `svn-status-default-diff-arguments' for some examples." + :type '(repeat string) + :group 'psvn) + +(put 'svn-status-default-blame-arguments 'risky-local-variable t) + +(defvar svn-trac-project-root nil + "Path for an eventual existing trac issue tracker. +This can be set with \\[svn-status-set-trac-project-root].") + +(defvar svn-status-module-name nil + "*A short name for the actual project. +This can be set with \\[svn-status-set-module-name].") + +(defvar svn-status-branch-list nil + "*A list of known branches for the actual project +This can be set with \\[svn-status-set-branch-list]. + +The list contains full repository paths or shortcuts starting with \# +\# at the beginning is replaced by the repository url. +\#1\# has the special meaning that all paths below the given directory +will be considered for interactive selections. + +A useful setting might be: '\(\"\#trunk\" \"\#1\#tags\" \"\#1\#branches\")") + +(defvar svn-status-load-state-before-svn-status t + "*Whether to automatically restore state from ++psvn.state file before running svn-status.") + +(defvar svn-log-link-handlers nil "A list of link handlers in *svn-log* buffers. +These link handlers must be registered via `svn-log-register-link-handler'") + +;;; hooks +(defvar svn-status-mode-hook nil "Hook run when entering `svn-status-mode'.") +(defvar svn-log-edit-mode-hook nil "Hook run when entering `svn-log-edit-mode'.") +(defvar svn-log-edit-done-hook nil "Hook run after commiting files via svn.") +;; (put 'svn-log-edit-mode-hook 'risky-local-variable t) +;; (put 'svn-log-edit-done-hook 'risky-local-variable t) +;; already implied by "-hook" suffix + +(defvar svn-post-process-svn-output-hook 'svn-fixup-tramp-output-maybe "Hook that can be used to preprocess the output from svn. +The function `svn-status-remove-control-M' can be useful for that hook") + +(when (eq system-type 'windows-nt) + (add-hook 'svn-post-process-svn-output-hook 'svn-status-remove-control-M)) + +(defvar svn-status-svn-process-coding-system (when (boundp 'locale-coding-system) locale-coding-system) + "The coding system that is used for the svn command line client. +It is used in svn-run, if it is not nil.") + +(defvar svn-status-svn-file-coding-system 'undecided-unix + "The coding system that is used to save files that are loaded as +parameter or data files via the svn command line client. +It is used in the following functions: `svn-prop-edit-do-it', `svn-log-edit-done'. +You could set it to 'utf-8") + +(defcustom svn-status-use-ido-completion + (fboundp 'ido-completing-read) + "*Use ido completion functionality." + :type 'boolean + :group 'psvn) + +(defvar svn-status-completing-read-function + (if svn-status-use-ido-completion 'ido-completing-read 'completing-read)) + +;;; experimental features +(defvar svn-status-track-user-input nil "Track user/password queries. +This feature is implemented via a process filter. +It is an experimental feature.") + +(defvar svn-status-refresh-info nil "Whether `svn-status-update-buffer' should call `svn-status-parse-info'.") + +;;; Customize group +(defgroup psvn nil + "Subversion interface for Emacs." + :group 'tools) + +(defgroup psvn-faces nil + "psvn faces." + :group 'psvn) + + +(eval-and-compile + (require 'cl) + (defconst svn-xemacsp (featurep 'xemacs)) + (if svn-xemacsp + (require 'overlay) + (require 'overlay nil t))) + +(defcustom svn-status-display-full-path nil + "Specifies how the filenames look like in the listing. +If t, their full path name will be displayed, else only the filename." + :type 'boolean + :group 'psvn) + +(defcustom svn-status-prefix-key [(control x) (meta s)] + "Prefix key for the psvn commands in the global keymap." + :type '(choice (const [(control x) ?v ?S]) + (const [(super s)]) + (const [(hyper s)]) + (const [(control x) ?v]) + (const [(control x) ?V]) + (sexp)) + :group 'psvn + :set (lambda (var value) + (if (boundp var) + (global-unset-key (symbol-value var))) + (set var value) + (global-set-key (symbol-value var) 'svn-global-keymap))) + +(defcustom svn-admin-default-create-directory "~/" + "*The default directory that is suggested for `svn-admin-create'." + :type 'string + :group 'psvn) + +(defvar svn-status-custom-hide-function nil + "A function that receives a line-info and decides whether to hide that line. +See psvn.el for an example function.") +;; (put 'svn-status-custom-hide-function 'risky-local-variable t) +;; already implied by "-function" suffix + + +;; Use the normally used mode for files ending in .~HEAD~, .~BASE~, ... +(add-to-list 'auto-mode-alist '("\\.~?\\(HEAD\\|BASE\\|PREV\\)~?\\'" ignore t)) + +;;; internal variables +(defvar svn-status-directory-history nil "List of visited svn working directories.") +(defvar svn-process-cmd nil) +(defvar svn-status-info nil) +(defvar svn-status-filename-to-buffer-position-cache (make-hash-table :test 'equal :weakness t)) +(defvar svn-status-base-info nil "The parsed result from the svn info command as a plist.") +(defvar svn-status-initial-window-configuration nil) +(defvar svn-status-default-column 23) +(defvar svn-status-default-revision-width 4) +(defvar svn-status-default-author-width 9) +(defvar svn-status-line-format " %c%c%c %4s %4s %-9s") +(defvar svn-start-of-file-list-line-number 0) +(defvar svn-status-files-to-commit nil + "List of files to commit at `svn-log-edit-done'. +This is always set together with `svn-status-recursive-commit'.") +(defvar svn-status-recursive-commit nil + "Non-nil if the next commit should be recursive. +This is always set together with `svn-status-files-to-commit'.") +(defvar svn-log-edit-update-log-entry nil + "Revision number whose log entry is being edited. +This is nil if the log entry is for a new commit.") +(defvar svn-status-pre-commit-window-configuration nil) +(defvar svn-status-pre-propedit-window-configuration nil) +(defvar svn-status-head-revision nil) +(defvar svn-status-root-return-info nil) +(defvar svn-status-property-edit-must-match-flag nil) +(defvar svn-status-propedit-property-name nil "The property name for the actual svn propset command") +(defvar svn-status-propedit-file-list nil) +(defvar svn-status-mode-line-process "") +(defvar svn-status-mode-line-process-status "") +(defvar svn-status-mode-line-process-edit-flag "") +(defvar svn-status-edit-svn-command nil) +(defvar svn-status-update-previous-process-output nil) +(defvar svn-pre-run-asynch-recent-keys nil) +(defvar svn-pre-run-mode-line-process nil) +(defvar svn-arg-file-content nil) +(defvar svn-status-temp-dir + (file-name-as-directory + (expand-file-name + (or + (when (boundp 'temporary-file-directory) temporary-file-directory) ;emacs + ;; XEmacs 21.4.17 can return "/tmp/kalle" from (temp-directory). + ;; `file-name-as-directory' adds a slash so we can append a file name. + (when (fboundp 'temp-directory) (temp-directory)) + "/tmp/"))) "The directory that is used to store temporary files for psvn.") +;; Because `temporary-file-directory' is not a risky local variable in +;; GNU Emacs 22.0.51, we don't mark `svn-status-temp-dir' as such either. +(defvar svn-temp-suffix (make-temp-name ".")) +(put 'svn-temp-suffix 'risky-local-variable t) +(defvar svn-status-temp-file-to-remove nil) +(put 'svn-status-temp-file-to-remove 'risky-local-variable t) +(defvar svn-status-temp-arg-file (concat svn-status-temp-dir "svn.arg" svn-temp-suffix)) +(put 'svn-status-temp-arg-file 'risky-local-variable t) +(defvar svn-status-options nil) +(defvar svn-status-remote) +(defvar svn-status-commit-rev-number nil) +(defvar svn-status-update-rev-number nil) +(defvar svn-status-operated-on-dot nil) +(defvar svn-status-last-commit-author nil) +(defvar svn-status-elided-list nil) +(defvar svn-status-last-output-buffer-name nil "The buffer name for the buffer that holds the output from the last executed svn command") +(defvar svn-status-pre-run-svn-buffer nil) +(defvar svn-status-update-list nil) +(defvar svn-transient-buffers) +(defvar svn-ediff-windows) +(defvar svn-ediff-result) +(defvar svn-status-last-diff-options nil) +(defvar svn-status-blame-file-name nil) +(defvar svn-status-blame-revision nil) +(defvar svn-admin-last-repository-dir nil "The last repository url for various operations.") +(defvar svn-last-cmd-ring (make-ring 30) "Ring that holds the last executed svn commands (for debugging purposes)") +(defvar svn-status-cached-version-string nil) +(defvar svn-client-version nil "The version number of the used svn client") +(defvar svn-status-get-line-information-for-file nil) +(defvar svn-status-base-dir-cache (make-hash-table :test 'equal :weakness nil)) +(defvar svn-status-usermark-storage (make-hash-table :test 'equal :weakness nil)) +(defvar svn-log-registered-link-handlers (make-hash-table :test 'eql :weakness nil)) + +(defvar svn-status-partner-buffer nil "The partner buffer for this svn related buffer") +(make-variable-buffer-local 'svn-status-partner-buffer) + +;; Emacs 21 defines these in ediff-init.el but it seems more robust +;; to just declare the variables here than try to load that file. +;; It is Ediff's job to declare these as risky-local-variable if needed. +(defvar ediff-buffer-A) +(defvar ediff-buffer-B) +(defvar ediff-buffer-C) +(defvar ediff-quit-hook) + +;; Ditto for log-edit.el. +(defvar log-edit-initial-files) +(defvar log-edit-callback) +(defvar log-edit-listfun) + +;; Ediff does not use this variable in GNU Emacs 20.7, GNU Emacs 21.4, +;; nor XEmacs 21.4.17. However, pcl-cvs (a.k.a. pcvs) does. +;; TODO: Check if this should be moved into the "svn-" namespace. +(defvar ediff-after-quit-destination-buffer) + +;; That is an example for the svn-status-custom-hide-function: +;; Note: For many cases it is a better solution to ignore files or +;; file extensions via the svn-ignore properties (on P i, P I) +;; (setq svn-status-custom-hide-function 'svn-status-hide-pyc-files) +;; (defun svn-status-hide-pyc-files (info) +;; "Hide all pyc files in the `svn-status-buffer-name' buffer." +;; (let* ((fname (svn-status-line-info->filename-nondirectory info)) +;; (fname-len (length fname))) +;; (and (> fname-len 4) (string= (substring fname (- fname-len 4)) ".pyc")))) + +;;; faces +(defface svn-status-marked-face + '((((type tty) (class color)) (:foreground "green" :weight light)) + (((class color) (background light)) (:foreground "green3")) + (((class color) (background dark)) (:foreground "palegreen2")) + (t (:weight bold))) + "Face to highlight the mark for user marked files in svn status buffers." + :group 'psvn-faces) + +(defface svn-status-marked-popup-face + '((((type tty) (class color)) (:foreground "green" :weight light)) + (((class color) (background light)) (:foreground "green3")) + (((class color) (background dark)) (:foreground "palegreen2")) + (t (:weight bold))) + "Face to highlight the actual file, if a popup menu is activated." + :group 'psvn-faces) + +(defface svn-status-update-available-face + '((((type tty) (class color)) (:foreground "magenta" :weight light)) + (((class color) (background light)) (:foreground "magenta")) + (((class color) (background dark)) (:foreground "yellow")) + (t (:weight bold))) + "Face used to highlight the 'out of date' mark. +\(i.e., the mark used when there is a newer version in the repository +than the working copy.\) + +See also `svn-status-short-mod-flag-p'." + :group 'psvn-faces) + +;based on cvs-filename-face +(defface svn-status-directory-face + '((((type tty) (class color)) (:foreground "lightblue" :weight light)) + (((class color) (background light)) (:foreground "blue4")) + (((class color) (background dark)) (:foreground "lightskyblue1")) + (t (:weight bold))) + "Face for directories in *svn-status* buffers. +See `svn-status--line-info->directory-p' for what counts as a directory." + :group 'psvn-faces) + +;based on font-lock-comment-face +(defface svn-status-filename-face + '((((class color) (background light)) (:foreground "chocolate")) + (((class color) (background dark)) (:foreground "beige"))) + "Face for non-directories in *svn-status* buffers. +See `svn-status--line-info->directory-p' for what counts as a directory." + :group 'psvn-faces) + +;not based on anything, may be horribly ugly! +(defface svn-status-symlink-face + '((((class color) (background light)) (:foreground "cornflower blue")) + (((class color) (background dark)) (:foreground "cyan"))) + "Face for symlinks in *svn-status* buffers. + +This is the face given to the actual link (i.e., the versioned item), +the target of the link gets either `svn-status-filename-face' or +`svn-status-directory-face'." + :group 'psvn-faces) + +;based on font-lock-warning-face +(defface svn-status-locked-face + '((t + (:weight bold :foreground "Red"))) + "Face for the phrase \"[ LOCKED ]\" `svn-status-buffer-name' buffers." + :group 'psvn-faces) + +;based on vhdl-font-lock-directive-face +(defface svn-status-switched-face + '((((class color) + (background light)) + (:foreground "CadetBlue")) + (((class color) + (background dark)) + (:foreground "Aquamarine")) + (t + (:bold t :italic t))) + "Face for the phrase \"(switched)\" non-directories in svn status buffers." + :group 'psvn-faces) + +(if svn-xemacsp + (defface svn-status-blame-highlight-face + '((((type tty) (class color)) (:foreground "green" :weight light)) + (((class color) (background light)) (:foreground "green3")) + (((class color) (background dark)) (:foreground "palegreen2")) + (t (:weight bold))) + "Default face for highlighting a line in svn status blame mode." + :group 'psvn-faces) + (defface svn-status-blame-highlight-face + '((t :inherit highlight)) + "Default face for highlighting a line in svn status blame mode." + :group 'psvn-faces)) + +(if svn-xemacsp + (defface svn-log-partner-highlight-face + '((((type tty) (class color)) (:foreground "yellow" :weight light)) + (((class color) (background light)) (:foreground "gold")) + (((class color) (background dark)) (:foreground "gold")) + (t (:weight bold))) + "Default face for highlighting the partner in svn log mode." + :group 'psvn-faces) + (defface svn-log-partner-highlight-face + '((((class color) (background light)) + (:background "light goldenrod" :weight bold)) + (t (:weight bold))) + "Default face for highlighting the partner in svn log mode." + :group 'psvn-faces)) + +(defface svn-status-blame-rev-number-face + '((((class color) (background light)) (:foreground "DarkGoldenrod")) + (((class color) (background dark)) (:foreground "LightGoldenrod")) + (t (:weight bold :slant italic))) + "Face to highlight revision numbers in the svn-blame mode." + :group 'psvn-faces) + +(defvar svn-highlight t) +;; stolen from PCL-CVS +(defun svn-add-face (str face &optional keymap) + "Return string STR decorated with the specified FACE. +If `svn-highlight' is nil then just return STR." + (when svn-highlight + ;; Do not use `list*'; cl.el might not have been loaded. We could + ;; put (require 'cl) at the top but let's try to manage without. + (add-text-properties 0 (length str) + `(face ,face + mouse-face highlight) +;; 18.10.2004: the keymap parameter is not used (yet) in psvn.el +;; ,@(when keymap +;; `(mouse-face highlight +;; local-map ,keymap))) + str)) + str) + +(defun svn-status-maybe-add-face (condition text face) + "If CONDITION then add FACE to TEXT. +Else return TEXT unchanged." + (if condition + (svn-add-face text face) + text)) + +(defun svn-status-choose-face-to-add (condition text face1 face2) + "If CONDITION then add FACE1 to TEXT, else add FACE2 to TEXT." + (if condition + (svn-add-face text face1) + (svn-add-face text face2))) + +(defun svn-status-maybe-add-string (condition string face) + "If CONDITION then return STRING decorated with FACE. +Otherwise, return \"\"." + (if condition + (svn-add-face string face) + "")) + +;; compatibility +;; emacs 20 +(defalias 'svn-point-at-eol + (if (fboundp 'point-at-eol) 'point-at-eol 'line-end-position)) +(defalias 'svn-point-at-bol + (if (fboundp 'point-at-bol) 'point-at-bol 'line-beginning-position)) +(defalias 'svn-read-directory-name + (if (fboundp 'read-directory-name) 'read-directory-name 'read-file-name)) + +(eval-when-compile + (if (not (fboundp 'gethash)) + (require 'cl-macs))) +(defalias 'svn-puthash (if (fboundp 'puthash) 'puthash 'cl-puthash)) + +;; emacs 21 +(if (fboundp 'line-number-at-pos) + (defalias 'svn-line-number-at-pos 'line-number-at-pos) + (defun svn-line-number-at-pos (&optional pos) + "Return (narrowed) buffer line number at position POS. +If POS is nil, use current buffer location." + (let ((opoint (or pos (point))) start) + (save-excursion + (goto-char (point-min)) + (setq start (point)) + (goto-char opoint) + (forward-line 0) + (1+ (count-lines start (point))))))) + +(defun svn-substring-no-properties (string &optional from to) + (if (fboundp 'substring-no-properties) + (substring-no-properties string from to) + (substring string (or from 0) to))) + +; xemacs +;; Evaluate the defsubst at compile time, so that the byte compiler +;; knows the definition and can inline calls. It cannot detect the +;; defsubst automatically from within the if form. +(eval-and-compile + (if (fboundp 'match-string-no-properties) + (defalias 'svn-match-string-no-properties 'match-string-no-properties) + (defsubst svn-match-string-no-properties (match) + (buffer-substring-no-properties (match-beginning match) (match-end match))))) + +; XEmacs doesn't have a function `help-buffer' +(eval-and-compile + (if (fboundp 'help-buffer) + (defalias 'svn-help-buffer 'help-buffer) ; FSF Emacs + (defun svn-help-buffer () + (buffer-name (get-buffer-create (help-buffer-name "SVN")))))) ; XEmacs + + +;; XEmacs 21.4.17 does not have an `alist' widget. Define a replacement. +;; To find out whether the `alist' widget exists, we cannot check just +;; (get 'alist 'widget-type), because GNU Emacs 21.4 defines it in +;; "wid-edit.el", which is not preloaded; it will be autoloaded when +;; `widget-create' is called. Instead, we call `widgetp', which is +;; also autoloaded from "wid-edit.el". XEmacs 21.4.17 does not have +;; `widgetp' either, so we check that first. +(if (and (fboundp 'widgetp) (widgetp 'alist)) + (define-widget 'svn-alist 'alist + "An association list. +Use this instead of `alist', for XEmacs 21.4 compatibility.") + (define-widget 'svn-alist 'list + "An association list. +Use this instead of `alist', for XEmacs 21.4 compatibility." + :convert-widget 'svn-alist-convert-widget + :tag "Association List" + :key-type 'sexp + :value-type 'sexp) + (defun svn-alist-convert-widget (widget) + (let* ((value-type (widget-get widget :value-type)) + (option-widgets (loop for option in (widget-get widget :options) + collect `(cons :format "%v" + (const :format "%t: %v\n" + :tag "Key" + ,option) + ,value-type)))) + (widget-put widget :args + `(,@(when option-widgets + `((set :inline t :format "%v" + ,@option-widgets))) + (editable-list :inline t + (cons :format "%v" + ,(widget-get widget :key-type) + ,value-type))))) + widget)) + +;; process launch functions +(defvar svn-call-process-function (if (fboundp 'process-file) 'process-file 'call-process)) +(defvar svn-start-process-function (if (fboundp 'start-file-process) 'start-file-process 'start-process)) + + +;;; keymaps + +(defvar svn-global-keymap nil "Global keymap for psvn.el. +To bind this to a different key, customize `svn-status-prefix-key'.") +(put 'svn-global-keymap 'risky-local-variable t) +(when (not svn-global-keymap) + (setq svn-global-keymap (make-sparse-keymap)) + (define-key svn-global-keymap (kbd "v") 'svn-status-version) + (define-key svn-global-keymap (kbd "s") 'svn-status-this-directory) + (define-key svn-global-keymap (kbd "b") 'svn-status-via-bookmark) + (define-key svn-global-keymap (kbd "h") 'svn-status-use-history) + (define-key svn-global-keymap (kbd "u") 'svn-status-update-cmd) + (define-key svn-global-keymap (kbd "=") 'svn-status-show-svn-diff) + (define-key svn-global-keymap (kbd "f =") 'svn-file-show-svn-diff) + (define-key svn-global-keymap (kbd "f e") 'svn-file-show-svn-ediff) + (define-key svn-global-keymap (kbd "f l") 'svn-status-show-svn-log) + (define-key svn-global-keymap (kbd "f b") 'svn-status-blame) + (define-key svn-global-keymap (kbd "f a") 'svn-file-add-to-changelog) + (define-key svn-global-keymap (kbd "f r") 'svn-file-revert) + (define-key svn-global-keymap (kbd "c") 'svn-status-commit) + (define-key svn-global-keymap (kbd "S") 'svn-status-switch-to-status-buffer) + (define-key svn-global-keymap (kbd "o") 'svn-status-pop-to-status-buffer) + (define-key svn-global-keymap (kbd "C-k") 'svn-process-kill)) + +(defvar svn-status-diff-mode-map () + "Keymap used in `svn-status-diff-mode' for additional commands that are not defined in diff-mode.") +(put 'svn-status-diff-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-status-diff-mode-map) + (setq svn-status-diff-mode-map (copy-keymap diff-mode-shared-map)) + (define-key svn-status-diff-mode-map [?g] 'revert-buffer) + (define-key svn-status-diff-mode-map [?s] 'svn-status-pop-to-status-buffer) + (define-key svn-status-diff-mode-map [?c] 'svn-status-diff-pop-to-commit-buffer) + (define-key svn-status-diff-mode-map [?w] 'svn-status-diff-save-current-defun-as-kill)) + +(defvar svn-global-trac-map () + "Subkeymap used in `svn-global-keymap' for trac issue tracker commands.") +(put 'svn-global-trac-map 'risky-local-variable t) ;for Emacs 20.7 +(when (not svn-global-trac-map) + (setq svn-global-trac-map (make-sparse-keymap)) + (define-key svn-global-trac-map (kbd "w") 'svn-trac-browse-wiki) + (define-key svn-global-trac-map (kbd "t") 'svn-trac-browse-timeline) + (define-key svn-global-trac-map (kbd "m") 'svn-trac-browse-roadmap) + (define-key svn-global-trac-map (kbd "s") 'svn-trac-browse-source) + (define-key svn-global-trac-map (kbd "r") 'svn-trac-browse-report) + (define-key svn-global-trac-map (kbd "i") 'svn-trac-browse-ticket) + (define-key svn-global-trac-map (kbd "c") 'svn-trac-browse-changeset) + (define-key svn-global-keymap (kbd "t") svn-global-trac-map)) + +;; The setter of `svn-status-prefix-key' makes a binding in the global +;; map refer to the `svn-global-keymap' symbol, rather than directly +;; to the keymap. Emacs then implicitly uses the symbol-function. +;; This has the advantage that `describe-bindings' (C-h b) can show +;; the name of the keymap and link to its documentation. +(defalias 'svn-global-keymap svn-global-keymap) +;; `defalias' of GNU Emacs 21.4 doesn't allow a docstring argument. +(put 'svn-global-keymap 'function-documentation + '(documentation-property 'svn-global-keymap 'variable-documentation t)) + + +;; named after SVN_WC_ADM_DIR_NAME in svn_wc.h +(defun svn-wc-adm-dir-name () + "Return the name of the \".svn\" subdirectory or equivalent." + (if (and (eq system-type 'windows-nt) + (getenv "SVN_ASP_DOT_NET_HACK")) + "_svn" + ".svn")) + +(defun svn-log-edit-file-name (&optional curdir) + "Get the name of the saved log edit file +If curdir, return `svn-log-edit-file-name' +Otherwise position svn-log-edit-file-name in the root directory of this working copy" + (if curdir + svn-log-edit-file-name + (concat (svn-status-base-dir) svn-log-edit-file-name))) + +(defun svn-status-message (level &rest args) + "If LEVEL is lower than `svn-status-debug-level' print ARGS using `message'. + +Guideline for numbers: +1 - error messages, 3 - non-serious error messages, 5 - messages for things +that take a long time, 7 - not very important messages on stuff, 9 - messages +inside loops." + (if (<= level svn-status-debug-level) + (apply 'message args))) + +(defun svn-status-flatten-list (list) + "Flatten any lists within ARGS, so that there are no sublists." + (loop for item in list + if (listp item) nconc (svn-status-flatten-list item) + else collect item)) + +(defun svn-status-window-line-position (w) + "Return the window line at point for window W, or nil if W is nil." + (svn-status-message 3 "About to count lines; selected window is %s" (selected-window)) + (and w (count-lines (window-start w) (point)))) + +;;;###autoload +(defun svn-checkout (repos-url path) + "Run svn checkout REPOS-URL PATH." + (interactive (list (read-string "Checkout from repository Url: ") + (expand-file-name + (svn-read-directory-name "Checkout to directory: ")))) + (svn-run t t 'checkout "checkout" repos-url (expand-file-name path))) + +;;;###autoload (defalias 'svn-examine 'svn-status) +(defalias 'svn-examine 'svn-status) + +;;;###autoload +(defun svn-version-controlled-dir-p (dir) + "Return t if DIR is part of a Subversion workarea." + (= 0 (call-process svn-status-svn-executable nil nil nil "info" dir))) + +;;;###autoload +(defun svn-status (dir &optional arg) + "Examine the status of Subversion working copy in directory DIR. +If ARG is -, allow editing of the parameters. One could add -N to +run svn status non recursively to make it faster. +For every other non nil ARG pass the -u argument to `svn status', which +asks svn to connect to the repository and check to see if there are updates +there. + +If DIR is not an SVN working copy, examine if there is CVS and run +`cvs-examine'. Otherwise ask if to run `dired'." + (interactive (list (expand-file-name + (svn-read-directory-name "SVN status directory: " + nil default-directory nil)) + current-prefix-arg)) + (cond + ((svn-version-controlled-dir-p (expand-file-name dir)) + (setq arg (svn-status-possibly-negate-meaning-of-arg arg 'svn-status)) + (svn-status-1 dir arg)) + ((and (file-directory-p (concat (file-name-as-directory dir) "CVS")) + (fboundp 'cvs-examine)) + (cvs-examine dir nil)) + (t + (when (y-or-n-p + (format + (concat + "%s " + "is not Subversion controlled (missing %s " + "directory). " + "Run dired instead? ") + dir + (svn-wc-adm-dir-name))) + (dired dir))))) + +(defvar svn-status-display-new-status-buffer nil) +(defun svn-status-1 (dir &optional arg) + "Examine DIR. See `svn-status' for more information." + (unless (file-directory-p dir) + (error "%s is not a directory" dir)) + (setq dir (file-name-as-directory dir)) + (when svn-status-load-state-before-svn-status + (unless (string= dir (car svn-status-directory-history)) + (let ((default-directory dir)) ;otherwise svn-status-base-dir looks in the wrong place + (svn-status-load-state t)))) + (setq svn-status-directory-history (delete dir svn-status-directory-history)) + (add-to-list 'svn-status-directory-history dir) + (if (string= (buffer-name) svn-status-buffer-name) + (setq svn-status-display-new-status-buffer nil) + (setq svn-status-display-new-status-buffer t) + ;;(message "psvn: Saving initial window configuration") + (setq svn-status-initial-window-configuration + (current-window-configuration))) + (let* ((cur-buf (current-buffer)) + (status-buf (get-buffer-create svn-status-buffer-name)) + (proc-buf (get-buffer-create svn-process-buffer-name)) + (want-edit (eq arg '-)) + (status-option (if want-edit + (if svn-status-verbose "-v" "") + (if svn-status-verbose + (if arg "-uv" "-v") + (if arg "-u" ""))))) + (save-excursion + (set-buffer status-buf) + (buffer-disable-undo) + (setq default-directory dir) + (set-buffer proc-buf) + (setq default-directory dir + svn-status-remote (when arg t)) + (if want-edit + (let ((svn-status-edit-svn-command t)) + (svn-run t t 'status "status" svn-status-default-status-arguments status-option)) + (svn-run t t 'status "status" svn-status-default-status-arguments status-option))))) + +(defun svn-status-this-directory (arg) + "Run `svn-status' for the `default-directory'" + (interactive "P") + (svn-status default-directory arg)) + +(defun svn-status-use-history () + "Interactively select a different directory from `svn-status-directory-history'." + (interactive) + (let* ((in-status-buffer (eq major-mode 'svn-status-mode)) + (hist (if in-status-buffer (cdr svn-status-directory-history) svn-status-directory-history)) + (dir (funcall svn-status-completing-read-function "svn-status on directory: " hist)) + (svn-status-buffer (get-buffer svn-status-buffer-name)) + (svn-buffer-available (and svn-status-buffer + (with-current-buffer svn-status-buffer-name (string= default-directory dir))))) + (if (file-directory-p dir) + (if svn-buffer-available + (svn-status-switch-to-status-buffer) + (unless svn-status-refresh-info + (setq svn-status-refresh-info 'once)) + (svn-status dir)) + (error "%s is not a directory" dir)))) + +(defun svn-had-user-input-since-asynch-run () + (not (equal (recent-keys) svn-pre-run-asynch-recent-keys))) + +(defun svn-expand-filename-for-remote-access (file-name) + "Convert the given local part of a filename to a full file name to allow accessing remote files" + ;; 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 + (if (and (fboundp 'file-remote-p) (file-remote-p default-directory)) + (concat (file-remote-p default-directory) file-name) + file-name)) + +(defun svn-local-filename-for-remote-access (file-name) + "Convert a full file name to a local file name that can be used for a local svn invocation." + (if (and (fboundp 'file-remote-p) (file-remote-p file-name)) + (tramp-file-name-localname (tramp-dissect-file-name file-name)) + file-name)) + +(defun svn-process-environment () + "Construct the environment for the svn process. +It is a combination of `svn-status-svn-environment-var-list' and +the usual `process-environment'." + ;; If there are duplicate elements in `process-environment', then GNU + ;; Emacs 21.4 guarantees that the first one wins; but GNU Emacs 20.7 + ;; and XEmacs 21.4.17 don't document what happens. We'll just remove + ;; any duplicates ourselves, then. This also gives us an opportunity + ;; to handle the "VARIABLE" syntax that none of them supports. + (loop with found = '() + for elt in (append svn-status-svn-environment-var-list + process-environment) + for has-value = (string-match "=" elt) + for name = (substring elt 0 has-value) + unless (member name found) + do (push name found) + and when has-value + collect elt)) + +(defun svn-run (run-asynchron clear-process-buffer cmdtype &rest arglist) + "Run svn with arguments ARGLIST. + +If RUN-ASYNCHRON is t then run svn asynchronously. + +If CLEAR-PROCESS-BUFFER is t then erase the contents of the +`svn-process-buffer-name' buffer before commencing. + +CMDTYPE is a symbol such as 'mv, 'revert, or 'add, representing the +command to run. + +ARGLIST is a list of arguments \(which must include the command name, +for example: '(\"revert\" \"file1\"\) +ARGLIST is flattened and any every nil value is discarded. + +If the variable `svn-status-edit-svn-command' is non-nil then the user +can edit ARGLIST before running svn. + +The hook svn-pre-run-hook allows to monitor/modify the ARGLIST." + (setq arglist (svn-status-flatten-list arglist)) + (if (eq (process-status "svn") nil) + (progn + (when svn-status-edit-svn-command + (setq arglist (append + (list (car arglist)) + (split-string + (read-from-minibuffer + (format "svn %s flags: " (car arglist)) + (mapconcat 'identity (cdr arglist) " "))))) + (when (eq svn-status-edit-svn-command t) + (svn-status-toggle-edit-cmd-flag t)) + (message "svn-run %s: %S" cmdtype arglist)) + (run-hooks 'svn-pre-run-hook) + (unless (eq mode-line-process 'svn-status-mode-line-process) + (setq svn-pre-run-mode-line-process mode-line-process) + (setq mode-line-process 'svn-status-mode-line-process)) + (setq svn-status-pre-run-svn-buffer (current-buffer)) + (let* ((pre-run-buffer-default-directory default-directory) + (proc-buf (get-buffer-create svn-process-buffer-name)) + (svn-exe svn-status-svn-executable) + (svn-proc)) + (when (listp (car arglist)) + (setq arglist (car arglist))) + (save-excursion + (set-buffer proc-buf) + (setq default-directory pre-run-buffer-default-directory) + (setq buffer-read-only nil) + (buffer-disable-undo) + (fundamental-mode) + (if clear-process-buffer + (delete-region (point-min) (point-max)) + (goto-char (point-max))) + (setq svn-process-cmd cmdtype) + (setq svn-status-last-commit-author nil) + (setq svn-status-mode-line-process-status (format " running %s" cmdtype)) + (svn-status-update-mode-line) + (save-excursion (sit-for 0.1)) + (ring-insert svn-last-cmd-ring (list (current-time-string) arglist default-directory svn-arg-file-content)) + (setq svn-arg-file-content nil) + (setq svn-process-handle-error-msg nil) + (if run-asynchron + (progn + ;;(message "running asynchron: %s %S" svn-exe arglist) + (setq svn-pre-run-asynch-recent-keys (recent-keys)) + (let ((process-environment (svn-process-environment)) + (process-connection-type nil)) + ;; Communicate with the subprocess via pipes rather + ;; than via a pseudoterminal, so that if the svn+ssh + ;; scheme is being used, SSH will not ask for a + ;; passphrase via stdio; psvn.el is currently unable + ;; to answer such prompts. Instead, SSH will run + ;; x11-ssh-askpass if possible. If Emacs is being + ;; run on a TTY without $DISPLAY, this will fail; in + ;; such cases, the user should start ssh-agent and + ;; then run ssh-add explicitly. + (setq svn-proc (apply svn-start-process-function "svn" proc-buf svn-exe arglist))) + (when svn-status-svn-process-coding-system + (set-process-coding-system svn-proc svn-status-svn-process-coding-system + svn-status-svn-process-coding-system)) + (set-process-sentinel svn-proc 'svn-process-sentinel) + (when svn-status-track-user-input + (set-process-filter svn-proc 'svn-process-filter))) + ;;(message "running synchron: %s %S" svn-exe arglist) + (let ((process-environment (svn-process-environment))) + ;; `call-process' ignores `process-connection-type' and + ;; never opens a pseudoterminal. + (apply svn-call-process-function svn-exe nil proc-buf nil arglist)) + (setq svn-status-last-output-buffer-name svn-process-buffer-name) + (run-hooks 'svn-post-process-svn-output-hook) + (setq svn-status-mode-line-process-status "") + (svn-status-update-mode-line) + (when svn-pre-run-mode-line-process + (setq mode-line-process svn-pre-run-mode-line-process) + (setq svn-pre-run-mode-line-process nil)))))) + (error "You can only run one svn process at once!"))) + +(defun svn-process-sentinel-fixup-path-seperators () + "Convert all path separators to UNIX style. +\(This is a no-op unless `system-type' is windows-nt\)" + (when (eq system-type 'windows-nt) + (save-excursion + (goto-char (point-min)) + (while (search-forward "\\" nil t) + (replace-match "/"))))) + +(defun svn-process-sentinel (process event) + "Called after a svn process has finished." + ;;(princ (format "Process: %s had the event `%s'" process event))) + (let ((act-buf (current-buffer))) + (when svn-pre-run-mode-line-process + (with-current-buffer svn-status-pre-run-svn-buffer + (setq mode-line-process svn-pre-run-mode-line-process)) + (setq svn-pre-run-mode-line-process nil)) + (set-buffer (process-buffer process)) + (setq svn-status-mode-line-process-status "") + (svn-status-update-mode-line) + (cond ((string= event "finished\n") + (run-hooks 'svn-post-process-svn-output-hook) + (cond ((eq svn-process-cmd 'status) + ;;(message "svn status finished") + (svn-process-sentinel-fixup-path-seperators) + (svn-parse-status-result) + (svn-status-apply-elide-list) + (when svn-status-update-previous-process-output + (set-buffer (process-buffer process)) + (delete-region (point-min) (point-max)) + (insert "Output from svn command:\n") + (insert svn-status-update-previous-process-output) + (goto-char (point-min)) + (setq svn-status-update-previous-process-output nil)) + (when svn-status-update-list + ;; (message "Using svn-status-update-list: %S" svn-status-update-list) + (save-excursion + (svn-status-update-with-command-list svn-status-update-list)) + (setq svn-status-update-list nil)) + (when svn-status-display-new-status-buffer + (set-window-configuration svn-status-initial-window-configuration) + (if (svn-had-user-input-since-asynch-run) + (message "svn status finished") + (switch-to-buffer svn-status-buffer-name)))) + ((eq svn-process-cmd 'log) + (svn-status-show-process-output 'log t) + (pop-to-buffer svn-status-last-output-buffer-name) + (svn-log-view-mode) + (forward-line 2) + (unless (looking-at "Changed paths:") + (forward-line 1)) + (font-lock-fontify-buffer) + (message "svn log finished")) + ((eq svn-process-cmd 'info) + (svn-status-show-process-output 'info t) + (message "svn info finished")) + ((eq svn-process-cmd 'ls) + (svn-status-show-process-output 'info t) + (message "svn ls finished")) + ((eq svn-process-cmd 'diff) + (svn-status-activate-diff-mode) + (message "svn diff finished")) + ((eq svn-process-cmd 'parse-info) + (svn-status-parse-info-result)) + ((eq svn-process-cmd 'blame) + (svn-status-show-process-output 'blame t) + (when svn-status-pre-run-svn-buffer + (with-current-buffer svn-status-pre-run-svn-buffer + (unless (eq major-mode 'svn-status-mode) + (let ((src-line-number (svn-line-number-at-pos))) + (pop-to-buffer (get-buffer svn-status-last-output-buffer-name)) + (goto-line src-line-number))))) + (with-current-buffer (get-buffer svn-status-last-output-buffer-name) + (svn-status-activate-blame-mode)) + (message "svn blame finished")) + ((eq svn-process-cmd 'commit) + (svn-process-sentinel-fixup-path-seperators) + (svn-status-remove-temp-file-maybe) + (when (member 'commit svn-status-unmark-files-after-list) + (svn-status-unset-all-usermarks)) + (svn-status-update-with-command-list (svn-status-parse-commit-output)) + (svn-revert-some-buffers) + (run-hooks 'svn-log-edit-done-hook) + (setq svn-status-files-to-commit nil + svn-status-recursive-commit nil) + (if (null svn-status-commit-rev-number) + (message "No revision to commit.") + (message "svn: Committed revision %s." svn-status-commit-rev-number))) + ((eq svn-process-cmd 'update) + (svn-status-show-process-output 'update t) + (setq svn-status-update-list (svn-status-parse-update-output)) + (svn-revert-some-buffers) + (svn-status-update) + (if (car svn-status-update-rev-number) + (message "svn: Updated to revision %s." (cadr svn-status-update-rev-number)) + (message "svn: At revision %s." (cadr svn-status-update-rev-number)))) + ((eq svn-process-cmd 'add) + (svn-status-update-with-command-list (svn-status-parse-ar-output)) + (message "svn add finished")) + ((eq svn-process-cmd 'lock) + (svn-status-update) + (message "svn lock finished")) + ((eq svn-process-cmd 'unlock) + (svn-status-update) + (message "svn unlock finished")) + ((eq svn-process-cmd 'mkdir) + (svn-status-update) + (message "svn mkdir finished")) + ((eq svn-process-cmd 'revert) + (when (member 'revert svn-status-unmark-files-after-list) + (svn-status-unset-all-usermarks)) + (svn-revert-some-buffers) + (svn-status-update) + (message "svn revert finished")) + ((eq svn-process-cmd 'resolved) + (svn-status-update) + (message "svn resolved finished")) + ((eq svn-process-cmd 'rm) + (svn-status-update-with-command-list (svn-status-parse-ar-output)) + (message "svn rm finished")) + ((eq svn-process-cmd 'cleanup) + (message "svn cleanup finished")) + ((eq svn-process-cmd 'proplist) + (svn-status-show-process-output 'proplist t) + (message "svn proplist finished")) + ((eq svn-process-cmd 'checkout) + (svn-status default-directory)) + ((eq svn-process-cmd 'proplist-parse) + (svn-status-property-parse-property-names)) + ((eq svn-process-cmd 'propset) + (svn-status-remove-temp-file-maybe) + (if (member svn-status-propedit-property-name '("svn:keywords")) + (svn-status-update-with-command-list (svn-status-parse-property-output)) + (svn-status-update))) + ((eq svn-process-cmd 'propdel) + (svn-status-update)))) + ((string= event "killed\n") + (message "svn process killed")) + ((string-match "exited abnormally" event) + (while (accept-process-output process 0 100)) + ;; find last error message and show it. + (goto-char (point-max)) + (if (re-search-backward "^svn: " nil t) + (let ((error-strings) + (beginning-of-buffer)) + (while (and (looking-at "^svn: ") (not beginning-of-buffer)) + (setq error-strings (append error-strings (list (buffer-substring-no-properties (+ 5 (svn-point-at-bol)) (svn-point-at-eol))))) + (setq beginning-of-buffer (bobp)) + (forward-line -1)) + (svn-process-handle-error (mapconcat 'identity (reverse error-strings) "\n"))) + (message "svn failed: %s" event))) + (t + (message "svn process had unknown event: %s" event)) + (svn-status-show-process-output nil t)))) + +(defvar svn-process-handle-error-msg nil) +(defvar svn-handle-error-function nil + "A function that will be called with an error string received from the svn client. +When this function resets `svn-process-handle-error-msg' to nil, the default error handling +(just show the error message) is not executed.") +(defun svn-process-handle-error (error-msg) + (setq svn-process-handle-error-msg error-msg) + (when (functionp svn-handle-error-function) + (funcall svn-handle-error-function error-msg)) + (when svn-process-handle-error-msg + (electric-helpify 'svn-process-help-with-error-msg))) + +(defun svn-process-help-with-error-msg () + (interactive) + (let ((help-msg (cadr (assoc svn-process-handle-error-msg + '(("Cannot non-recursively commit a directory deletion" + "Please unmark all files and position point at the directory you would like to remove.\nThen run commit again.")))))) + (if help-msg + (save-excursion + (with-output-to-temp-buffer (svn-help-buffer) + (princ (format "svn failed: %s\n\n%s" svn-process-handle-error-msg help-msg)))) + (message "svn failed:\n%s" svn-process-handle-error-msg)))) + + +(defun svn-process-filter (process str) + "Track the svn process output and ask user questions in the minibuffer when appropriate." + (save-window-excursion + (set-buffer svn-process-buffer-name) + ;;(message "svn-process-filter: %s" str) + (goto-char (point-max)) + (insert str) + (save-excursion + (goto-char (svn-point-at-bol)) + (when (looking-at "Password for '\\(.*\\)': ") + ;(svn-status-show-process-buffer) + (let ((passwd (read-passwd + (format "Enter svn password for %s: " (match-string 1))))) + (svn-process-send-string-and-newline passwd t))) + (when (looking-at "Username: ") + (let ((user-name (with-local-quit (read-string "Username for svn operation: ")))) + (svn-process-send-string-and-newline user-name))) + (when (looking-at "(R)eject, accept (t)emporarily or accept (p)ermanently") + (svn-status-show-process-buffer) + (let ((answer (with-local-quit (read-string "(R)eject, accept (t)emporarily or accept (p)ermanently? ")))) + (svn-process-send-string (substring answer 0 1))))))) + +(defun svn-revert-some-buffers (&optional tree) + "Reverts all buffers visiting a file in TREE that aren't modified. +To be run after a commit, an update or a merge." + (interactive) + (let ((tree (or (svn-status-base-dir) tree))) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when (not (buffer-modified-p)) + (let ((file (buffer-file-name))) + (when file + (let ((root (svn-status-base-dir (file-name-directory file))) + (point-pos (point))) + (when (and root + (string= root tree) + ;; buffer is modified and in the tree TREE. + svn-status-auto-revert-buffers) + (when svn-status-fancy-file-state-in-modeline + (svn-status-update-modeline)) + ;; (message "svn-revert-some-buffers: %s %s" (buffer-file-name) (verify-visited-file-modtime (current-buffer))) + ;; Keep the buffer if the file doesn't exist + (when (and (file-exists-p file) (not (verify-visited-file-modtime (current-buffer)))) + (revert-buffer t t) + (goto-char point-pos))))))))))) + +(defun svn-parse-rev-num (str) + (if (and str (stringp str) + (save-match-data (string-match "^[0-9]+" str))) + (string-to-number str) + -1)) + +(defsubst svn-status-make-ui-status () + "Make a ui-status structure for a file in a svn working copy. +The initial values in the structure returned by this function +are good for a file or directory that the user hasn't seen before. + +The ui-status structure keeps track of how the file or directory +should be displayed in svn-status mode. Updating the svn-status +buffer from the working copy preserves the ui-status if possible. +User commands modify this structure; each file or directory must +thus have its own copy. + +Currently, the ui-status is a list (USER-MARK USER-ELIDE). +USER-MARK is non-nil iff the user has marked the file or directory, + typically with `svn-status-set-user-mark'. To read USER-MARK, + call `svn-status-line-info->has-usermark'. +USER-ELIDE is non-nil iff the user has elided the file or directory + from the svn-status buffer, typically with `svn-status-toggle-elide'. + To read USER-ELIDE, call `svn-status-line-info->user-elide'. + +Call `svn-status-line-info->ui-status' to access the whole ui-status +structure." + (list nil nil)) + +(defun svn-status-make-dummy-dirs (dir-list old-ui-information) + "Calculate additionally necessary directories that were not shown in the output +of 'svn status'" + ;; (message "svn-status-make-dummy-dirs %S" dir-list) + (let ((candidate) + (base-dir)) + (dolist (dir dir-list) + (setq base-dir (file-name-directory dir)) + (while base-dir + ;;(message "dir: %S dir-list: %S, base-dir: %S" dir dir-list base-dir) + (setq candidate (replace-regexp-in-string "/+$" "" base-dir)) + (setq base-dir (file-name-directory candidate)) + ;; (message "dir: %S, candidate: %S" dir candidate) + (add-to-list 'dir-list candidate)))) + ;; (message "svn-status-make-dummy-dirs %S" dir-list) + (append (mapcar (lambda (dir) + (svn-status-make-line-info + dir + (gethash dir old-ui-information))) + dir-list) + svn-status-info)) + +(defun svn-status-make-line-info (&optional + path + ui + file-mark prop-mark + local-rev last-change-rev + author + update-mark + locked-mark + with-history-mark + switched-mark + locked-repo-mark + psvn-extra-info) + "Create a new line-info from the given arguments +Anything left nil gets a sensible default. +nb: LOCKED-MARK refers to the kind of locks you get after an error, + LOCKED-REPO-MARK is the kind managed with `svn lock'" + (list (or ui (svn-status-make-ui-status)) + (or file-mark ? ) + (or prop-mark ? ) + (or path "") + (or local-rev ? ) + (or last-change-rev ? ) + (or author "") + update-mark + locked-mark + with-history-mark + switched-mark + locked-repo-mark + psvn-extra-info)) + +(defvar svn-user-names-including-blanks nil "A list of svn user names that include blanks. +To add support for the names \"feng shui\" and \"mister blank\", place the following in your .emacs: + (setq svn-user-names-including-blanks '(\"feng shui\" \"mister blank\")) + (add-hook 'svn-pre-parse-status-hook 'svn-status-parse-fixup-user-names-including-blanks) +") +;;(setq svn-user-names-including-blanks '("feng shui" "mister blank")) +;;(add-hook 'svn-pre-parse-status-hook 'svn-status-parse-fixup-user-names-including-blanks) + +(defun svn-status-parse-fixup-user-names-including-blanks () + "Helper function to allow user names that include blanks. +Add this function to the `svn-pre-parse-status-hook'. The variable +`svn-user-names-including-blanks' must be configured to hold all user names that contain +blanks. This function replaces the blanks with '-' to allow further processing with +the usual parsing functionality in `svn-parse-status-result'." + (when svn-user-names-including-blanks + (goto-char (point-min)) + (let ((search-string (concat " \\(" (mapconcat 'concat svn-user-names-including-blanks "\\|") "\\) "))) + (save-match-data + (save-excursion + (while (re-search-forward search-string (point-max) t) + (replace-match (replace-regexp-in-string " " "-" (match-string 1)) nil nil nil 1))))))) + +(defun svn-parse-status-result () + "Parse the `svn-process-buffer-name' buffer. +The results are used to build the `svn-status-info' variable." + (setq svn-status-head-revision nil) + (save-excursion + (let ((old-ui-information (svn-status-ui-information-hash-table)) + (svn-marks) + (svn-file-mark) + (svn-property-mark) + (svn-wc-locked-mark) + (svn-repo-locked-mark) + (svn-with-history-mark) + (svn-switched-mark) + (svn-update-mark) + (local-rev) + (last-change-rev) + (author) + (path) + (dir) + (revision-width svn-status-default-revision-width) + (author-width svn-status-default-author-width) + (svn-marks-length (if svn-status-verbose + (if svn-status-remote + 8 6) + (if svn-status-remote + ;; not verbose + 8 7))) + (dir-set '(".")) + (externals-map (make-hash-table :test 'equal)) + (skip-double-external-dir-entry-name nil)) + (set-buffer svn-process-buffer-name) + (setq svn-status-info nil) + (run-hooks 'svn-pre-parse-status-hook) + (goto-char (point-min)) + (while (< (point) (point-max)) + (cond + ((= (svn-point-at-eol) (svn-point-at-bol)) ;skip blank lines + nil) + ((looking-at "Status against revision:[ ]+\\([0-9]+\\)") + ;; the above message appears for the main listing plus once for each svn:externals entry + (unless svn-status-head-revision + (setq svn-status-head-revision (match-string 1)))) + ((looking-at "Performing status on external item at '\\(.*\\)'") + ;; The *next* line has info about the directory named in svn:externals + ;; [ie the directory in (match-string 1)] + ;; we should parse it, and merge the info with what we have already know + ;; but for now just ignore the line completely + ; (forward-line) + ;; Actually, this seems to not always be the case + ;; I have an example where we are in an svn:external which + ;; is itself inside a svn:external, this need not be true: + ;; the next line is not 'X dir' but just 'dir', so we + ;; actually need to parse that line, or the results will + ;; not contain dir! + ;; so we should merge lines 'X dir' with ' dir', but for now + ;; we just leave both in the results + + ;; My attempt to merge the lines uses skip-double-external-dir-entry-name + ;; and externals-map + (setq skip-double-external-dir-entry-name (svn-match-string-no-properties 1)) + ;; (message "Going to skip %s" skip-double-external-dir-entry-name) + nil) + ((looking-at "--- Changelist") ; skip svn changelist header lines + ;; See: http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt + nil) + (t + (setq svn-marks (buffer-substring (point) (+ (point) svn-marks-length)) + svn-file-mark (elt svn-marks 0) ; 1st column - M,A,C,D,G,? etc + svn-property-mark (elt svn-marks 1) ; 2nd column - M,C (properties) + svn-wc-locked-mark (elt svn-marks 2) ; 3rd column - L or blank + svn-with-history-mark (elt svn-marks 3) ; 4th column - + or blank + svn-switched-mark (elt svn-marks 4) ; 5th column - S,X or blank + svn-repo-locked-mark (elt svn-marks 5)) ; 6th column - K,O,T,B or blank + (when svn-status-remote + (setq svn-update-mark (elt svn-marks 7))) ; 8th column - * or blank + (when (eq svn-property-mark ?\ ) (setq svn-property-mark nil)) + (when (eq svn-wc-locked-mark ?\ ) (setq svn-wc-locked-mark nil)) + (when (eq svn-with-history-mark ?\ ) (setq svn-with-history-mark nil)) + (when (eq svn-switched-mark ?\ ) (setq svn-switched-mark nil)) + (when (eq svn-update-mark ?\ ) (setq svn-update-mark nil)) + (when (eq svn-repo-locked-mark ?\ ) (setq svn-repo-locked-mark nil)) + (forward-char svn-marks-length) + (skip-chars-forward " ") + ;; (message "after marks: '%s'" (buffer-substring (point) (line-end-position))) + (cond + ((looking-at "\\([-?]\\|[0-9]+\\) +\\([-?]\\|[0-9]+\\) +\\([^ ]+\\) *\\(.+\\)$") + (setq local-rev (svn-parse-rev-num (match-string 1)) + last-change-rev (svn-parse-rev-num (match-string 2)) + author (match-string 3) + path (match-string 4))) + ((looking-at "\\([-?]\\|[0-9]+\\) +\\([^ ]+\\)$") + (setq local-rev (svn-parse-rev-num (match-string 1)) + last-change-rev -1 + author "?" + path (match-string 2))) + ((looking-at "\\(.*\\)") + (setq path (match-string 1) + local-rev -1 + last-change-rev -1 + author (if (eq svn-file-mark ?X) "" "?"))) ;clear author of svn:externals dirs + (t + (error "Unknown status line format"))) + (unless path (setq path ".")) + (setq dir (file-name-directory path)) + (if (and (not svn-status-verbose) dir) + (let ((dirname (directory-file-name dir))) + (if (not (member dirname dir-set)) + (setq dir-set (cons dirname dir-set))))) + (if (and skip-double-external-dir-entry-name (string= skip-double-external-dir-entry-name path)) + ;; merge this entry to a previous saved one + (let ((info (gethash path externals-map))) + ;; (message "skip-double-external-dir-entry-name: %s - path: %s" skip-double-external-dir-entry-name path) + (if info + (progn + (svn-status-line-info->set-localrev info local-rev) + (svn-status-line-info->set-lastchangerev info last-change-rev) + (svn-status-line-info->set-author info author) + (svn-status-message 3 "merging entry for %s to %s" path info) + (setq skip-double-external-dir-entry-name nil)) + (message "psvn: %s not handled correct, please report this case." path))) + (setq svn-status-info + (cons (svn-status-make-line-info path + (gethash path old-ui-information) + svn-file-mark + svn-property-mark + local-rev + last-change-rev + author + svn-update-mark + svn-wc-locked-mark + svn-with-history-mark + svn-switched-mark + svn-repo-locked-mark + nil) ;;psvn-extra-info + svn-status-info))) + (when (eq svn-file-mark ?X) + (svn-puthash (match-string 1) (car svn-status-info) externals-map) + (svn-status-message 3 "found external: %s %S" (match-string 1) (car svn-status-info))) + (setq revision-width (max revision-width + (length (number-to-string local-rev)) + (length (number-to-string last-change-rev)))) + (setq author-width (max author-width (length author))))) + (forward-line 1)) + (unless svn-status-verbose + (setq svn-status-info (svn-status-make-dummy-dirs dir-set + old-ui-information))) + (setq svn-status-default-column + (+ 6 revision-width revision-width author-width + (if svn-status-short-mod-flag-p 3 0))) + (setq svn-status-line-format (format " %%c%%c%%c %%%ds %%%ds %%-%ds" + revision-width + revision-width + author-width)) + (setq svn-status-info (nreverse svn-status-info)) + (when svn-status-sort-status-buffer + (setq svn-status-info (sort svn-status-info 'svn-status-sort-predicate)))))) + +;;(string-lessp "." "%") => nil +;;(svn-status-sort-predicate '(t t t ".") '(t t t "%")) => t +(defun svn-status-sort-predicate (a b) + "Return t if A should appear before B in the `svn-status-buffer-name' buffer. +A and B must be line-info's." + (string-lessp (concat (svn-status-line-info->full-path a) "/") + (concat (svn-status-line-info->full-path b) "/"))) + +(defun svn-status-remove-temp-file-maybe () + "Remove any (no longer required) temporary files created by psvn.el." + (when svn-status-temp-file-to-remove + (when (file-exists-p svn-status-temp-file-to-remove) + (delete-file svn-status-temp-file-to-remove)) + (when (file-exists-p svn-status-temp-arg-file) + (delete-file svn-status-temp-arg-file)) + (setq svn-status-temp-file-to-remove nil))) + +(defun svn-status-remove-control-M () + "Remove ^M at end of line in the whole buffer." + (interactive) + (let ((buffer-read-only nil)) + (save-match-data + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\r$" (point-max) t) + (replace-match "" nil nil)))))) + +(defun svn-fixup-tramp-exit () + "Helper function to handle tramp connections stopping with an exit output." + (goto-char (point-max)) + (when (eq (svn-point-at-bol) (svn-point-at-eol)) + (forward-line -1)) + (beginning-of-line) + (when (looking-at "exit") + (delete-region (point) (svn-point-at-eol)))) + +(defun svn-fixup-tramp-output-maybe () + "Fixup leftover output when running via tramp" + (when (fboundp 'file-remote-p) + (when (file-remote-p default-directory) + (svn-fixup-tramp-exit)))) + +(condition-case nil + ;;(easy-menu-add-item nil '("tools") ["SVN Status" svn-status t] "PCL-CVS") + (easy-menu-add-item nil '("tools") ["SVN Status" svn-status t]) + (error (message "psvn: could not install menu"))) + +(defvar svn-status-mode-map () "Keymap used in `svn-status-mode' buffers.") +(put 'svn-status-mode-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-mark-map () + "Subkeymap used in `svn-status-mode' for mark commands.") +(put 'svn-status-mode-mark-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-property-map () + "Subkeymap used in `svn-status-mode' for property commands.") +(put 'svn-status-mode-property-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-options-map () + "Subkeymap used in `svn-status-mode' for option commands.") +(put 'svn-status-mode-options-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-trac-map () + "Subkeymap used in `svn-status-mode' for trac issue tracker commands.") +(put 'svn-status-mode-trac-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-extension-map () + "Subkeymap used in `svn-status-mode' for some seldom used commands.") +(put 'svn-status-mode-extension-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-branch-map () + "Subkeymap used in `svn-status-mode' for branching commands.") +(put 'svn-status-mode-extension-map 'risky-local-variable t) ;for Emacs 20.7 +(defvar svn-status-mode-search-map () + "Subkeymap used in `svn-status-mode' for search commands.") +(put 'svn-status-mode-search-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-status-mode-map) + (setq svn-status-mode-map (make-sparse-keymap)) + (suppress-keymap svn-status-mode-map) + ;; Don't use (kbd ""); it's unreachable with GNU Emacs 21.3 on a TTY. + (define-key svn-status-mode-map (kbd "RET") 'svn-status-find-file-or-examine-directory) + (define-key svn-status-mode-map (kbd "") 'svn-status-mouse-find-file-or-examine-directory) + (define-key svn-status-mode-map (kbd "^") 'svn-status-examine-parent) + (define-key svn-status-mode-map (kbd "s") 'svn-status-show-process-buffer) + (define-key svn-status-mode-map (kbd "h") 'svn-status-pop-to-partner-buffer) + (define-key svn-status-mode-map (kbd "f") 'svn-status-find-files) + (define-key svn-status-mode-map (kbd "o") 'svn-status-find-file-other-window) + (define-key svn-status-mode-map (kbd "C-o") 'svn-status-find-file-other-window-noselect) + (define-key svn-status-mode-map (kbd "v") 'svn-status-view-file-other-window) + (define-key svn-status-mode-map (kbd "e") 'svn-status-toggle-edit-cmd-flag) + (define-key svn-status-mode-map (kbd "g") 'svn-status-update) + (define-key svn-status-mode-map (kbd "M-s") 'svn-status-update) ;; PCL-CVS compatibility + (define-key svn-status-mode-map (kbd "q") 'svn-status-bury-buffer) + (define-key svn-status-mode-map (kbd "x") 'svn-status-redraw-status-buffer) + (define-key svn-status-mode-map (kbd "H") 'svn-status-use-history) + (define-key svn-status-mode-map (kbd "m") 'svn-status-set-user-mark) + (define-key svn-status-mode-map (kbd "u") 'svn-status-unset-user-mark) + ;; This matches a binding of `dired-unmark-all-files' in `dired-mode-map' + ;; of both GNU Emacs and XEmacs. It seems unreachable with XEmacs on + ;; TTY, but if that's a problem then its Dired needs fixing too. + ;; Or you could just use "*!". + (define-key svn-status-mode-map "\M-\C-?" 'svn-status-unset-all-usermarks) + ;; The key that normally deletes characters backwards should here + ;; instead unmark files backwards. In GNU Emacs, that would be (kbd + ;; "DEL") aka [?\177], but XEmacs treats those as [(delete)] and + ;; would bind a key that normally deletes forwards. [(backspace)] + ;; is unreachable with GNU Emacs on a tty. Try to recognize the + ;; dialect and act accordingly. + ;; + ;; XEmacs has a `delete-forward-p' function that checks the + ;; `delete-key-deletes-forward' option. We don't use those, for two + ;; reasons: psvn.el may be loaded before user customizations, and + ;; XEmacs allows simultaneous connections to multiple devices with + ;; different keyboards. + (define-key svn-status-mode-map + (if (member (kbd "DEL") '([(delete)] [delete])) + [(backspace)] ; XEmacs + (kbd "DEL")) ; GNU Emacs + 'svn-status-unset-user-mark-backwards) + (define-key svn-status-mode-map (kbd "$") 'svn-status-toggle-elide) + (define-key svn-status-mode-map (kbd "w") 'svn-status-copy-current-line-info) + (define-key svn-status-mode-map (kbd ".") 'svn-status-goto-root-or-return) + (define-key svn-status-mode-map (kbd "I") 'svn-status-parse-info) + (define-key svn-status-mode-map (kbd "V") 'svn-status-svnversion) + (define-key svn-status-mode-map (kbd "?") 'svn-status-toggle-hide-unknown) + (define-key svn-status-mode-map (kbd "_") 'svn-status-toggle-hide-unmodified) + (define-key svn-status-mode-map (kbd "z") 'svn-status-toggle-hide-externals) + (define-key svn-status-mode-map (kbd "a") 'svn-status-add-file) + (define-key svn-status-mode-map (kbd "A") 'svn-status-add-file-recursively) + (define-key svn-status-mode-map (kbd "+") 'svn-status-make-directory) + (define-key svn-status-mode-map (kbd "R") 'svn-status-mv) + (define-key svn-status-mode-map (kbd "C") 'svn-status-cp) + (define-key svn-status-mode-map (kbd "D") 'svn-status-rm) + (define-key svn-status-mode-map (kbd "c") 'svn-status-commit) + (define-key svn-status-mode-map (kbd "M-c") 'svn-status-cleanup) + (define-key svn-status-mode-map (kbd "k") 'svn-status-lock) + (define-key svn-status-mode-map (kbd "K") 'svn-status-unlock) + (define-key svn-status-mode-map (kbd "U") 'svn-status-update-cmd) + (define-key svn-status-mode-map (kbd "M-u") 'svn-status-update-cmd) + (define-key svn-status-mode-map (kbd "r") 'svn-status-revert) + (define-key svn-status-mode-map (kbd "l") 'svn-status-show-svn-log) + (define-key svn-status-mode-map (kbd "i") 'svn-status-info) + (define-key svn-status-mode-map (kbd "b") 'svn-status-blame) + (define-key svn-status-mode-map (kbd "=") 'svn-status-show-svn-diff) + ;; [(control ?=)] is unreachable on TTY, but you can use "*u" instead. + ;; (Is the "u" mnemonic for something?) + (define-key svn-status-mode-map (kbd "C-=") 'svn-status-show-svn-diff-for-marked-files) + (define-key svn-status-mode-map (kbd "~") 'svn-status-get-specific-revision) + (define-key svn-status-mode-map (kbd "E") 'svn-status-ediff-with-revision) + + (define-key svn-status-mode-map (kbd "n") 'svn-status-next-line) + (define-key svn-status-mode-map (kbd "p") 'svn-status-previous-line) + (define-key svn-status-mode-map (kbd "") 'svn-status-next-line) + (define-key svn-status-mode-map (kbd "") 'svn-status-previous-line) + (define-key svn-status-mode-map (kbd "C-x C-j") 'svn-status-dired-jump) + (define-key svn-status-mode-map [down-mouse-3] 'svn-status-popup-menu)) + +(when (not svn-status-mode-mark-map) + (setq svn-status-mode-mark-map (make-sparse-keymap)) + (define-key svn-status-mode-map (kbd "*") svn-status-mode-mark-map) + (define-key svn-status-mode-mark-map (kbd "!") 'svn-status-unset-all-usermarks) + (define-key svn-status-mode-mark-map (kbd "?") 'svn-status-mark-unknown) + (define-key svn-status-mode-mark-map (kbd "A") 'svn-status-mark-added) + (define-key svn-status-mode-mark-map (kbd "M") 'svn-status-mark-modified) + (define-key svn-status-mode-mark-map (kbd "P") 'svn-status-mark-modified-properties) + (define-key svn-status-mode-mark-map (kbd "D") 'svn-status-mark-deleted) + (define-key svn-status-mode-mark-map (kbd "*") 'svn-status-mark-changed) + (define-key svn-status-mode-mark-map (kbd ".") 'svn-status-mark-by-file-ext) + (define-key svn-status-mode-mark-map (kbd "%") 'svn-status-mark-filename-regexp) + (define-key svn-status-mode-mark-map (kbd "s") 'svn-status-store-usermarks) + (define-key svn-status-mode-mark-map (kbd "l") 'svn-status-load-usermarks) + (define-key svn-status-mode-mark-map (kbd "u") 'svn-status-show-svn-diff-for-marked-files)) + +(when (not svn-status-mode-search-map) + (setq svn-status-mode-search-map (make-sparse-keymap)) + (define-key svn-status-mode-search-map (kbd "g") 'svn-status-grep-files) + (define-key svn-status-mode-search-map (kbd "s") 'svn-status-search-files) + (define-key svn-status-mode-map (kbd "S") svn-status-mode-search-map)) + +(when (not svn-status-mode-property-map) + (setq svn-status-mode-property-map (make-sparse-keymap)) + (define-key svn-status-mode-property-map (kbd "l") 'svn-status-property-list) + (define-key svn-status-mode-property-map (kbd "s") 'svn-status-property-set) + (define-key svn-status-mode-property-map (kbd "d") 'svn-status-property-delete) + (define-key svn-status-mode-property-map (kbd "e") 'svn-status-property-edit-one-entry) + (define-key svn-status-mode-property-map (kbd "i") 'svn-status-property-ignore-file) + (define-key svn-status-mode-property-map (kbd "I") 'svn-status-property-ignore-file-extension) + ;; XEmacs 21.4.15 on TTY (vt420) converts `C-i' to `TAB', + ;; which [(control ?i)] won't match. Handle it separately. + ;; On GNU Emacs, the following two forms bind the same key, + ;; reducing clutter in `where-is'. + (define-key svn-status-mode-property-map [(control ?i)] 'svn-status-property-edit-svn-ignore) + (define-key svn-status-mode-property-map (kbd "TAB") 'svn-status-property-edit-svn-ignore) + (define-key svn-status-mode-property-map (kbd "Xe") 'svn-status-property-edit-svn-externals) + (define-key svn-status-mode-property-map (kbd "k") 'svn-status-property-set-keyword-list) + (define-key svn-status-mode-property-map (kbd "Ki") 'svn-status-property-set-keyword-id) + (define-key svn-status-mode-property-map (kbd "Kd") 'svn-status-property-set-keyword-date) + (define-key svn-status-mode-property-map (kbd "y") 'svn-status-property-set-eol-style) + (define-key svn-status-mode-property-map (kbd "x") 'svn-status-property-set-executable) + (define-key svn-status-mode-property-map (kbd "m") 'svn-status-property-set-mime-type) + ;; TODO: Why is `svn-status-select-line' in `svn-status-mode-property-map'? + (define-key svn-status-mode-property-map (kbd "RET") 'svn-status-select-line) + (define-key svn-status-mode-map (kbd "P") svn-status-mode-property-map)) +(when (not svn-status-mode-extension-map) + (setq svn-status-mode-extension-map (make-sparse-keymap)) + (define-key svn-status-mode-extension-map (kbd "v") 'svn-status-resolved) + (define-key svn-status-mode-extension-map (kbd "X") 'svn-status-resolve-conflicts) + (define-key svn-status-mode-extension-map (kbd "e") 'svn-status-export) + (define-key svn-status-mode-map (kbd "X") svn-status-mode-extension-map)) +(when (not svn-status-mode-options-map) + (setq svn-status-mode-options-map (make-sparse-keymap)) + (define-key svn-status-mode-options-map (kbd "s") 'svn-status-save-state) + (define-key svn-status-mode-options-map (kbd "l") 'svn-status-load-state) + (define-key svn-status-mode-options-map (kbd "x") 'svn-status-toggle-sort-status-buffer) + (define-key svn-status-mode-options-map (kbd "v") 'svn-status-toggle-svn-verbose-flag) + (define-key svn-status-mode-options-map (kbd "f") 'svn-status-toggle-display-full-path) + (define-key svn-status-mode-options-map (kbd "t") 'svn-status-set-trac-project-root) + (define-key svn-status-mode-options-map (kbd "n") 'svn-status-set-module-name) + (define-key svn-status-mode-options-map (kbd "c") 'svn-status-set-changelog-style) + (define-key svn-status-mode-options-map (kbd "b") 'svn-status-set-branch-list) + (define-key svn-status-mode-map (kbd "O") svn-status-mode-options-map)) +(when (not svn-status-mode-trac-map) + (setq svn-status-mode-trac-map (make-sparse-keymap)) + (define-key svn-status-mode-trac-map (kbd "w") 'svn-trac-browse-wiki) + (define-key svn-status-mode-trac-map (kbd "t") 'svn-trac-browse-timeline) + (define-key svn-status-mode-trac-map (kbd "m") 'svn-trac-browse-roadmap) + (define-key svn-status-mode-trac-map (kbd "r") 'svn-trac-browse-report) + (define-key svn-status-mode-trac-map (kbd "s") 'svn-trac-browse-source) + (define-key svn-status-mode-trac-map (kbd "i") 'svn-trac-browse-ticket) + (define-key svn-status-mode-trac-map (kbd "c") 'svn-trac-browse-changeset) + (define-key svn-status-mode-map (kbd "T") svn-status-mode-trac-map)) +(when (not svn-status-mode-branch-map) + (setq svn-status-mode-branch-map (make-sparse-keymap)) + (define-key svn-status-mode-branch-map (kbd "d") 'svn-branch-diff) + (define-key svn-status-mode-map (kbd "B") svn-status-mode-branch-map)) + +(easy-menu-define svn-status-mode-menu svn-status-mode-map + "'svn-status-mode' menu" + '("SVN" + ["svn status" svn-status-update t] + ["svn update" svn-status-update-cmd t] + ["svn commit" svn-status-commit t] + ["svn log" svn-status-show-svn-log t] + ["svn info" svn-status-info t] + ["svn blame" svn-status-blame t] + ("Diff" + ["svn diff current file" svn-status-show-svn-diff t] + ["svn diff marked files" svn-status-show-svn-diff-for-marked-files t] + ["svn ediff current file" svn-status-ediff-with-revision t] + ["svn resolve conflicts" svn-status-resolve-conflicts] + ) + ("Search" + ["Grep marked files" svn-status-grep-files t] + ["Search marked files" svn-status-search-files t] + ) + ["svn cat ..." svn-status-get-specific-revision t] + ["svn add" svn-status-add-file t] + ["svn add recursively" svn-status-add-file-recursively t] + ["svn mkdir..." svn-status-make-directory t] + ["svn mv..." svn-status-mv t] + ["svn cp..." svn-status-cp t] + ["svn rm..." svn-status-rm t] + ["svn export..." svn-status-export t] + ["Up Directory" svn-status-examine-parent t] + ["Elide Directory" svn-status-toggle-elide t] + ["svn revert" svn-status-revert t] + ["svn resolved" svn-status-resolved t] + ["svn cleanup" svn-status-cleanup t] + ["svn lock" svn-status-lock t] + ["svn unlock" svn-status-unlock t] + ["Show Process Buffer" svn-status-show-process-buffer t] + ("Branch" + ["diff" svn-branch-diff t] + ["Set Branch list" svn-status-set-branch-list t] + ) + ("Property" + ["svn proplist" svn-status-property-list t] + ["Set Multiple Properties..." svn-status-property-set t] + ["Edit One Property..." svn-status-property-edit-one-entry t] + ["svn propdel..." svn-status-property-delete t] + "---" + ["svn:ignore File..." svn-status-property-ignore-file t] + ["svn:ignore File Extension..." svn-status-property-ignore-file-extension t] + ["Edit svn:ignore Property" svn-status-property-edit-svn-ignore t] + "---" + ["Edit svn:externals Property" svn-status-property-edit-svn-externals t] + "---" + ["Edit svn:keywords List" svn-status-property-set-keyword-list t] + ["Add/Remove Id to/from svn:keywords" svn-status-property-set-keyword-id t] + ["Add/Remove Date to/from svn:keywords" svn-status-property-set-keyword-date t] + "---" + ["Select svn:eol-style" svn-status-property-set-eol-style t] + ["Set svn:executable" svn-status-property-set-executable t] + ["Set svn:mime-type" svn-status-property-set-mime-type t] + ) + ("Options" + ["Save Options" svn-status-save-state t] + ["Load Options" svn-status-load-state t] + ["Set Trac project root" svn-status-set-trac-project-root t] + ["Set Short module name" svn-status-set-module-name t] + ["Set Changelog style" svn-status-set-changelog-style t] + ["Set Branch list" svn-status-set-branch-list t] + ["Sort the *svn-status* buffer" svn-status-toggle-sort-status-buffer + :style toggle :selected svn-status-sort-status-buffer] + ["Use -v for svn status calls" svn-status-toggle-svn-verbose-flag + :style toggle :selected svn-status-verbose] + ["Display full path names" svn-status-toggle-display-full-path + :style toggle :selected svn-status-display-full-path] + ) + ("Trac" + ["Browse wiki" svn-trac-browse-wiki t] + ["Browse timeline" svn-trac-browse-timeline t] + ["Browse roadmap" svn-trac-browse-roadmap t] + ["Browse source" svn-trac-browse-source t] + ["Browse report" svn-trac-browse-report t] + ["Browse ticket" svn-trac-browse-ticket t] + ["Browse changeset" svn-trac-browse-changeset t] + ["Set Trac project root" svn-status-set-trac-project-root t] + ) + "---" + ["Edit Next SVN Cmd Line" svn-status-toggle-edit-cmd-flag t] + ["Work Directory History..." svn-status-use-history t] + ("Mark / Unmark" + ["Mark" svn-status-set-user-mark t] + ["Unmark" svn-status-unset-user-mark t] + ["Unmark all" svn-status-unset-all-usermarks t] + "---" + ["Mark/Unmark unknown" svn-status-mark-unknown t] + ["Mark/Unmark modified" svn-status-mark-modified t] + ["Mark/Unmark modified properties" svn-status-mark-modified-properties t] + ["Mark/Unmark added" svn-status-mark-added t] + ["Mark/Unmark deleted" svn-status-mark-deleted t] + ["Mark/Unmark modified/added/deleted" svn-status-mark-changed t] + ["Mark/Unmark filename by extension" svn-status-mark-by-file-ext t] + ["Mark/Unmark filename by regexp" svn-status-mark-filename-regexp t] + ["Store Usermarks" svn-status-store-usermarks t] + ["Load Usermarks" svn-status-load-usermarks t] + ) + ["Hide Unknown" svn-status-toggle-hide-unknown + :style toggle :selected svn-status-hide-unknown] + ["Hide Unmodified" svn-status-toggle-hide-unmodified + :style toggle :selected svn-status-hide-unmodified] + ["Hide Externals" svn-status-toggle-hide-externals + :style toggle :selected svn-status-hide-externals] + ["Show Client versions" svn-status-version t] + ["Prepare bug report" svn-prepare-bug-report t] + )) + +(defvar svn-status-file-popup-menu-list + '(["open" svn-status-find-file-other-window t] + ["svn diff" svn-status-show-svn-diff t] + ["svn commit" svn-status-commit t] + ["svn log" svn-status-show-svn-log t] + ["svn blame" svn-status-blame t] + ["mark" svn-status-set-user-mark t] + ["unmark" svn-status-unset-user-mark t] + ["svn add" svn-status-add-file t] + ["svn add recursively" svn-status-add-file-recursively t] + ["svn mv..." svn-status-mv t] + ["svn rm..." svn-status-rm t] + ["svn lock" svn-status-lock t] + ["svn unlock" svn-status-unlock t] + ["svn info" svn-status-info t] + ) "A list of menu entries for `svn-status-popup-menu'") + +;; extend svn-status-file-popup-menu-list via: +;; (add-to-list 'svn-status-file-popup-menu-list ["commit" svn-status-commit t]) + +(defun svn-status-popup-menu (event) + "Display a file specific popup menu" + (interactive "e") + (mouse-set-point event) + (let* ((line-info (svn-status-get-line-information)) + (name (svn-status-line-info->filename line-info))) + (when line-info + (easy-menu-define svn-status-actual-popup-menu nil nil + (append (list name) svn-status-file-popup-menu-list)) + (svn-status-face-set-temporary-during-popup + 'svn-status-marked-popup-face (svn-point-at-bol) (svn-point-at-eol) + svn-status-actual-popup-menu)))) + +(defun svn-status-face-set-temporary-during-popup (face begin end menu &optional prefix) + "Put FACE on BEGIN and END in the buffer during Popup MENU. +PREFIX is passed to `popup-menu'." + (let (o) + (unwind-protect + (progn + (setq o (make-overlay begin end)) + (overlay-put o 'face face) + (save-excursion (sit-for 0)) + (popup-menu menu prefix)) + (delete-overlay o)))) + +(defun svn-status-mode () + "Major mode used by psvn.el to display the output of \"svn status\". + +The Output has the following format: + FPH BASE CMTD Author em File +F = Filemark +P = Property mark +H = History mark +BASE = local base revision +CMTD = last committed revision +Author = author of change +em = \"**\" or \"(Update Available)\" [see `svn-status-short-mod-flag-p'] + if file can be updated +File = path/filename + +The following keys are defined: +\\{svn-status-mode-map}" + (interactive) + (kill-all-local-variables) + + (use-local-map svn-status-mode-map) + (easy-menu-add svn-status-mode-menu) + + (setq major-mode 'svn-status-mode) + (setq mode-name "svn-status") + (setq mode-line-process 'svn-status-mode-line-process) + (run-hooks 'svn-status-mode-hook) + (let ((view-read-only nil)) + (toggle-read-only 1))) + +(defun svn-status-update-mode-line () + (setq svn-status-mode-line-process + (concat svn-status-mode-line-process-edit-flag svn-status-mode-line-process-status)) + (force-mode-line-update)) + +(defun svn-status-bury-buffer (arg) + "Bury the buffers used by psvn.el +Currently this is: + `svn-status-buffer-name' + `svn-process-buffer-name' + `svn-log-edit-buffer-name' + *svn-property-edit* + *svn-log* + *svn-info* +When called with a prefix argument, ARG, switch back to the window configuration that was +in use before `svn-status' was called." + (interactive "P") + (cond (arg + (when svn-status-initial-window-configuration + (set-window-configuration svn-status-initial-window-configuration))) + (t + (let ((bl `(,svn-log-edit-buffer-name "*svn-property-edit*" "*svn-log*" "*svn-info*" ,svn-process-buffer-name))) + (while bl + (when (get-buffer (car bl)) + (bury-buffer (car bl))) + (setq bl (cdr bl))) + (when (string= (buffer-name) svn-status-buffer-name) + (bury-buffer)))))) + +(defun svn-status-save-some-buffers (&optional tree) + "Save all buffers visiting a file in TREE. +If TREE is not given, try `svn-status-base-dir' as TREE." + (interactive) + ;; (message "svn-status-save-some-buffers: tree1: %s" tree) + (let ((ok t) + (tree (or (svn-status-base-dir) + tree))) + ;; (message "svn-status-save-some-buffers: tree2: %s" tree) + (unless tree + (error "Not in a svn project tree")) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when (buffer-modified-p) + (let ((file (buffer-file-name))) + (when file + (let ((root (svn-status-base-dir (file-name-directory file)))) + ;; (message "svn-status-save-some-buffers: file: %s, root: %s" file root) + (when (and root + (string= root tree) + ;; buffer is modified and in the tree TREE. + (or (y-or-n-p (concat "Save buffer " (buffer-name) "? ")) + (setq ok nil))) + (save-buffer)))))))) + ok)) + +(defun svn-status-find-files () + "Open selected file(s) for editing. +See `svn-status-marked-files' for what counts as selected." + (interactive) + (let ((fnames (mapcar 'svn-status-line-info->full-path (svn-status-marked-files)))) + (mapc 'find-file fnames))) + + +(defun svn-status-find-file-other-window () + "Open the file in the other window for editing." + (interactive) + (svn-status-ensure-cursor-on-file) + (find-file-other-window (svn-status-line-info->filename + (svn-status-get-line-information)))) + +(defun svn-status-find-file-other-window-noselect () + "Open the file in the other window for editing, but don't select it." + (interactive) + (svn-status-ensure-cursor-on-file) + (display-buffer + (find-file-noselect (svn-status-line-info->filename + (svn-status-get-line-information))))) + +(defun svn-status-view-file-other-window () + "Open the file in the other window for viewing." + (interactive) + (svn-status-ensure-cursor-on-file) + (view-file-other-window (svn-status-line-info->filename + (svn-status-get-line-information)))) + +(defun svn-status-find-file-or-examine-directory () + "If point is on a directory, run `svn-status' on that directory. +Otherwise run `find-file'." + (interactive) + (svn-status-ensure-cursor-on-file) + (let ((line-info (svn-status-get-line-information))) + (if (svn-status-line-info->directory-p line-info) + (svn-status (svn-status-line-info->full-path line-info)) + (find-file (svn-status-line-info->filename line-info))))) + +(defun svn-status-examine-parent () + "Run `svn-status' on the parent of the current directory." + (interactive) + (svn-status (expand-file-name "../"))) + +(defun svn-status-mouse-find-file-or-examine-directory (event) + "Move point to where EVENT occurred, and do `svn-status-find-file-or-examine-directory' +EVENT could be \"mouse clicked\" or similar." + (interactive "e") + (mouse-set-point event) + (svn-status-find-file-or-examine-directory)) + +(defun svn-status-line-info->ui-status (line-info) + "Return the ui-status structure of LINE-INFO. +See `svn-status-make-ui-status' for information about the ui-status." + (nth 0 line-info)) + +(defun svn-status-line-info->has-usermark (line-info) (nth 0 (nth 0 line-info))) +(defun svn-status-line-info->user-elide (line-info) (nth 1 (nth 0 line-info))) + +(defun svn-status-line-info->filemark (line-info) (nth 1 line-info)) +(defun svn-status-line-info->propmark (line-info) (nth 2 line-info)) +(defun svn-status-line-info->filename (line-info) (nth 3 line-info)) +(defun svn-status-line-info->filename-nondirectory (line-info) + (file-name-nondirectory (svn-status-line-info->filename line-info))) +(defun svn-status-line-info->localrev (line-info) + (if (>= (nth 4 line-info) 0) + (nth 4 line-info) + nil)) +(defun svn-status-line-info->lastchangerev (line-info) + "Return the last revision in which LINE-INFO was modified." + (let ((l (nth 5 line-info))) + (if (and l (>= l 0)) + l + nil))) +(defun svn-status-line-info->author (line-info) + "Return the last author that changed the item that is represented in LINE-INFO." + (nth 6 line-info)) +(defun svn-status-line-info->update-available (line-info) + "Return whether LINE-INFO is out of date. +In other words, whether there is a newer version available in the +repository than the working copy." + (nth 7 line-info)) +(defun svn-status-line-info->locked (line-info) + "Return whether LINE-INFO represents a locked file. +This is column three of the `svn status' output. +The result will be nil or \"L\". +\(A file becomes locked when an operation is interrupted; run \\[svn-status-cleanup]' +to unlock it.\)" + (nth 8 line-info)) +(defun svn-status-line-info->historymark (line-info) + "Mark from column four of output from `svn status'. +This will be nil unless the file is scheduled for addition with +history, when it will be \"+\"." + (nth 9 line-info)) +(defun svn-status-line-info->switched (line-info) + "Return whether LINE-INFO is switched relative to its parent. +This is column five of the output from `svn status'. +The result will be \"S\", \"X\" or nil." + (nth 10 line-info)) +(defun svn-status-line-info->repo-locked (line-info) + "Return whether LINE-INFO contains some locking information. +This is column six of the output from `svn status'. +The result will be \"K\", \"O\", \"T\", \"B\" or nil." + (nth 11 line-info)) +(defun svn-status-line-info->psvn-extra-info (line-info) + "Return a list of extra information for psvn associated with LINE-INFO. +This list holds currently only one element: +* The action after a commit or update." + (nth 12 line-info)) + +(defun svn-status-line-info->is-visiblep (line-info) + "Return whether the line is visible or not" + (or (not (or (svn-status-line-info->hide-because-unknown line-info) + (svn-status-line-info->hide-because-unmodified line-info) + (svn-status-line-info->hide-because-externals line-info) + (svn-status-line-info->hide-because-custom-hide-function line-info) + (svn-status-line-info->hide-because-user-elide line-info))) + (svn-status-line-info->update-available line-info) ;; show the line, if an update is available + (svn-status-line-info->psvn-extra-info line-info) ;; show the line, if there is some extra info displayed on this line + )) + +(defun svn-status-line-info->hide-because-unknown (line-info) + (and svn-status-hide-unknown + (eq (svn-status-line-info->filemark line-info) ??))) + +(defun svn-status-line-info->hide-because-externals (line-info) + (and svn-status-hide-externals + (eq (svn-status-line-info->filemark line-info) ?X))) + +(defun svn-status-line-info->hide-because-custom-hide-function (line-info) + (and svn-status-custom-hide-function + (apply svn-status-custom-hide-function (list line-info)))) + +(defun svn-status-line-info->hide-because-unmodified (line-info) + ;;(message " %S %S %S %S - %s" svn-status-hide-unmodified (svn-status-line-info->propmark line-info) ?_ + ;; (svn-status-line-info->filemark line-info) (svn-status-line-info->filename line-info)) + (and svn-status-hide-unmodified + (and (or (eq (svn-status-line-info->filemark line-info) ?_) + (eq (svn-status-line-info->filemark line-info) ? )) + (or (eq (svn-status-line-info->propmark line-info) ?_) + (eq (svn-status-line-info->propmark line-info) ? ) + (eq (svn-status-line-info->propmark line-info) nil))))) + +(defun svn-status-line-info->hide-because-user-elide (line-info) + (eq (svn-status-line-info->user-elide line-info) t)) + +(defun svn-status-line-info->show-user-elide-continuation (line-info) + (eq (svn-status-line-info->user-elide line-info) 'directory)) + +;; modify the line-info +(defun svn-status-line-info->set-filemark (line-info value) + (setcar (nthcdr 1 line-info) value)) + +(defun svn-status-line-info->set-propmark (line-info value) + (setcar (nthcdr 2 line-info) value)) + +(defun svn-status-line-info->set-localrev (line-info value) + (setcar (nthcdr 4 line-info) value)) + +(defun svn-status-line-info->set-author (line-info value) + (setcar (nthcdr 6 line-info) value)) + +(defun svn-status-line-info->set-lastchangerev (line-info value) + (setcar (nthcdr 5 line-info) value)) + +(defun svn-status-line-info->set-repo-locked (line-info value) + (setcar (nthcdr 11 line-info) value)) + +(defun svn-status-line-info->set-psvn-extra-info (line-info value) + (setcar (nthcdr 12 line-info) value)) + +(defun svn-status-copy-current-line-info (arg) + "Copy the current file name at point, using `svn-status-copy-filename-as-kill'. +If no file is at point, copy everything starting from ':' to the end of line." + (interactive "P") + (if (svn-status-get-line-information) + (svn-status-copy-filename-as-kill arg) + (save-excursion + (goto-char (svn-point-at-bol)) + (when (looking-at ".+?: *\\(.+\\)$") + (kill-new (svn-match-string-no-properties 1)) + (message "Copied: %s" (svn-match-string-no-properties 1)))))) + +(defun svn-status-copy-filename-as-kill (arg) + "Copy the actual file name to the kill-ring. +When called with the prefix argument 0, use the full path name." + (interactive "P") + (let ((str (if (eq arg 0) + (svn-status-line-info->full-path (svn-status-get-line-information)) + (svn-status-line-info->filename (svn-status-get-line-information))))) + (kill-new str) + (message "Copied %s" str))) + +(defun svn-status-get-child-directories (&optional dir) + "Return a list of subdirectories for DIR" + (interactive) + (let ((this-dir (concat (expand-file-name (or dir (svn-status-line-info->filename (svn-status-get-line-information)))) "/")) + (test-dir) + (sub-dir-list)) + ;;(message "this-dir %S" this-dir) + (dolist (line-info svn-status-info) + (when (svn-status-line-info->directory-p line-info) + (setq test-dir (svn-status-line-info->full-path line-info)) + (when (string= (file-name-directory test-dir) this-dir) + (add-to-list 'sub-dir-list (file-relative-name (svn-status-line-info->full-path line-info)) t)))) + sub-dir-list)) + +(defun svn-status-toggle-elide (arg) + "Toggle eliding of the current file or directory. +When called with a prefix argument, toggle the hiding of all subdirectories for the current directory." + (interactive "P") + (if arg + (let ((cur-line (svn-status-line-info->filename (svn-status-get-line-information)))) + (when (svn-status-line-info->user-elide (svn-status-get-line-information)) + (svn-status-toggle-elide nil)) + (dolist (dir-name (svn-status-get-child-directories)) + (svn-status-goto-file-name dir-name) + (svn-status-toggle-elide nil)) + (svn-status-goto-file-name cur-line)) + (let ((st-info svn-status-info) + (fname) + (test (svn-status-line-info->filename (svn-status-get-line-information))) + (len-test) + (len-fname) + (new-elide-mark t) + (elide-mark)) + (if (member test svn-status-elided-list) + (setq svn-status-elided-list (delete test svn-status-elided-list)) + (add-to-list 'svn-status-elided-list test)) + (when (string= test ".") + (setq test "")) + (setq len-test (length test)) + (while st-info + (setq fname (svn-status-line-info->filename (car st-info))) + (setq len-fname (length fname)) + (when (and (>= len-fname len-test) + (string= (substring fname 0 len-test) test)) + (setq elide-mark new-elide-mark) + (when (or (string= fname ".") + (and (= len-fname len-test) (svn-status-line-info->directory-p (car st-info)))) + (message "Elided directory %s and all its files." fname) + (setq new-elide-mark (not (svn-status-line-info->user-elide (car st-info)))) + (setq elide-mark (if new-elide-mark 'directory nil))) + ;;(message "elide-mark: %S member: %S" elide-mark (member fname svn-status-elided-list)) + (when (and (member fname svn-status-elided-list) (not elide-mark)) + (setq svn-status-elided-list (delete fname svn-status-elided-list))) + (setcar (nthcdr 1 (svn-status-line-info->ui-status (car st-info))) elide-mark)) + (setq st-info (cdr st-info)))) + ;;(message "svn-status-elided-list: %S" svn-status-elided-list) + (svn-status-update-buffer))) + +(defun svn-status-apply-elide-list () + "Elide files/directories according to `svn-status-elided-list'." + (interactive) + (let ((st-info svn-status-info) + (fname) + (len-fname) + (test) + (len-test) + (elided-list) + (elide-mark)) + (when svn-status-elided-list + (while st-info + (setq fname (svn-status-line-info->filename (car st-info))) + (setq len-fname (length fname)) + (setq elided-list svn-status-elided-list) + (setq elide-mark nil) + (while elided-list + (setq test (car elided-list)) + (when (string= test ".") + (setq test "")) + (setq len-test (length test)) + (when (and (>= len-fname len-test) + (string= (substring fname 0 len-test) test)) + (setq elide-mark t) + (when (or (string= fname ".") + (and (= len-fname len-test) (svn-status-line-info->directory-p (car st-info)))) + (setq elide-mark 'directory))) + (setq elided-list (cdr elided-list))) + ;;(message "fname: %s elide-mark: %S" fname elide-mark) + (setcar (nthcdr 1 (svn-status-line-info->ui-status (car st-info))) elide-mark) + (setq st-info (cdr st-info))))) + (svn-status-update-buffer)) + +(defun svn-status-update-with-command-list (cmd-list) + (save-excursion + (set-buffer svn-status-buffer-name) + (let ((st-info) + (found) + (action) + (fname (svn-status-line-info->filename (svn-status-get-line-information))) + (fname-pos (point)) + (column (current-column))) + (setq cmd-list (sort cmd-list '(lambda (item1 item2) (string-lessp (car item1) (car item2))))) + (while cmd-list + (unless st-info (setq st-info svn-status-info)) + ;;(message "%S" (caar cmd-list)) + (setq found nil) + (while (and (not found) st-info) + (setq found (string= (caar cmd-list) (svn-status-line-info->filename (car st-info)))) + ;;(message "found: %S" found) + (unless found (setq st-info (cdr st-info)))) + (unless found + (svn-status-message 3 "psvn: continue to search for %s" (caar cmd-list)) + (setq st-info svn-status-info) + (while (and (not found) st-info) + (setq found (string= (caar cmd-list) (svn-status-line-info->filename (car st-info)))) + (unless found (setq st-info (cdr st-info))))) + (if found + ;;update the info line + (progn + (setq action (cadar cmd-list)) + ;;(message "found %s, action: %S" (caar cmd-list) action) + (svn-status-annotate-status-buffer-entry action (car st-info))) + (svn-status-message 3 "psvn: did not find %s" (caar cmd-list))) + (setq cmd-list (cdr cmd-list))) + (if fname + (progn + (goto-char fname-pos) + (svn-status-goto-file-name fname) + (goto-char (+ column (svn-point-at-bol)))) + (goto-char (+ (next-overlay-change (point-min)) svn-status-default-column)))))) + +(defun svn-status-annotate-status-buffer-entry (action line-info) + (let ((tag-string)) + (svn-status-goto-file-name (svn-status-line-info->filename line-info)) + (when (and (member action '(committed added)) + svn-status-commit-rev-number) + (svn-status-line-info->set-localrev line-info svn-status-commit-rev-number) + (svn-status-line-info->set-lastchangerev line-info svn-status-commit-rev-number)) + (when svn-status-last-commit-author + (svn-status-line-info->set-author line-info svn-status-last-commit-author)) + (svn-status-line-info->set-psvn-extra-info line-info (list action)) + (cond ((equal action 'committed) + (setq tag-string " ") + (when (member (svn-status-line-info->repo-locked line-info) '(?K)) + (svn-status-line-info->set-repo-locked line-info nil))) + ((equal action 'added) + (setq tag-string " ")) + ((equal action 'deleted) + (setq tag-string " ")) + ((equal action 'replaced) + (setq tag-string " ")) + ((equal action 'updated) + (setq tag-string " ")) + ((equal action 'updated-props) + (setq tag-string " ")) + ((equal action 'conflicted) + (setq tag-string " ") + (svn-status-line-info->set-filemark line-info ?C)) + ((equal action 'merged) + (setq tag-string " ")) + ((equal action 'propset) + ;;(setq tag-string " ") + (svn-status-line-info->set-propmark line-info svn-status-file-modified-after-save-flag)) + ((equal action 'added-wc) + (svn-status-line-info->set-filemark line-info ?A) + (svn-status-line-info->set-localrev line-info 0)) + ((equal action 'deleted-wc) + (svn-status-line-info->set-filemark line-info ?D)) + (t + (error "Unknown action '%s for %s" action (svn-status-line-info->filename line-info)))) + (when (and tag-string (not (member action '(conflicted merged)))) + (svn-status-line-info->set-filemark line-info ? ) + (svn-status-line-info->set-propmark line-info ? )) + (let ((buffer-read-only nil)) + (delete-region (svn-point-at-bol) (svn-point-at-eol)) + (svn-insert-line-in-status-buffer line-info) + (backward-char 1) + (when tag-string + (insert tag-string)) + (delete-char 1)))) + + + +;; (svn-status-update-with-command-list '(("++ideas" committed) ("a.txt" committed) ("alf"))) +;; (svn-status-update-with-command-list (svn-status-parse-commit-output)) + +(defun svn-status-parse-commit-output () + "Parse the output of svn commit. +Return a list that is suitable for `svn-status-update-with-command-list'" + (save-excursion + (set-buffer svn-process-buffer-name) + (let ((action) + (file-name) + (skip) + (result)) + (goto-char (point-min)) + (setq svn-status-commit-rev-number nil) + (setq skip nil) ; set to t whenever we find a line not about a committed file + (while (< (point) (point-max)) + (cond ((= (svn-point-at-eol) (svn-point-at-bol)) ;skip blank lines + (setq skip t)) + ((looking-at "Sending") + (setq action 'committed)) + ((looking-at "Adding") + (setq action 'added)) + ((looking-at "Deleting") + (setq action 'deleted)) + ((looking-at "Replacing") + (setq action 'replaced)) + ((looking-at "Transmitting file data") + (setq skip t)) + ((looking-at "Committed revision \\([0-9]+\\)") + (setq svn-status-commit-rev-number + (string-to-number (svn-match-string-no-properties 1))) + (setq skip t)) + (t ;; this should never be needed(?) + (setq action 'unknown))) + (unless skip ;found an interesting line + (forward-char 15) + (when svn-status-operated-on-dot + ;; when the commit used . as argument, delete the trailing directory + ;; from the svn output + (search-forward "/" nil t)) + (setq file-name (buffer-substring-no-properties (point) (svn-point-at-eol))) + (unless svn-status-last-commit-author + (setq svn-status-last-commit-author (car (svn-status-info-for-path (expand-file-name (concat default-directory file-name)))))) + (setq result (cons (list file-name action) + result)) + (setq skip nil)) + (forward-line 1)) + result))) +;;(svn-status-parse-commit-output) +;;(svn-status-annotate-status-buffer-entry) + +(defun svn-status-parse-ar-output () + "Parse the output of svn add|remove. +Return a list that is suitable for `svn-status-update-with-command-list'" + (save-excursion + (set-buffer svn-process-buffer-name) + (let ((action) + (name) + (skip) + (result)) + (goto-char (point-min)) + (while (< (point) (point-max)) + (cond ((= (svn-point-at-eol) (svn-point-at-bol)) ;skip blank lines + (setq skip t)) + ((looking-at "A") + (setq action 'added-wc)) + ((looking-at "D") + (setq action 'deleted-wc)) + (t ;; this should never be needed(?) + (setq action 'unknown))) + (unless skip ;found an interesting line + (forward-char 10) + (setq name (buffer-substring-no-properties (point) (svn-point-at-eol))) + (setq result (cons (list name action) + result)) + (setq skip nil)) + (forward-line 1)) + result))) +;; (svn-status-parse-ar-output) +;; (svn-status-update-with-command-list (svn-status-parse-ar-output)) + +(defun svn-status-parse-update-output () + "Parse the output of svn update. +Return a list that is suitable for `svn-status-update-with-command-list'" + (save-excursion + (set-buffer svn-process-buffer-name) + (setq svn-status-update-rev-number nil) + (let ((action) + (name) + (skip) + (result)) + (goto-char (point-min)) + (while (< (point) (point-max)) + (cond ((= (svn-point-at-eol) (svn-point-at-bol)) ;skip blank lines + (setq skip t)) + ((looking-at "Updated to revision \\([0-9]+\\)") + (setq svn-status-update-rev-number + (list t (string-to-number (svn-match-string-no-properties 1)))) + (setq skip t)) + ((looking-at "At revision \\([0-9]+\\)") + (setq svn-status-update-rev-number + (list nil (string-to-number (svn-match-string-no-properties 1)))) + (setq skip t)) + ((looking-at "U") + (setq action 'updated)) + ((looking-at "A") + (setq action 'added)) + ((looking-at "D") + (setq skip t)) + ;;(setq action 'deleted)) ;;deleted files are not displayed in the svn status output. + ((looking-at "C") + (setq action 'conflicted)) + ((looking-at "G") + (setq action 'merged)) + + ((looking-at " U") + (setq action 'updated-props)) + + (t ;; this should never be needed(?) + (setq action (concat "parse-update: '" + (buffer-substring-no-properties (point) (+ 2 (point))) "'")))) + (unless skip ;found an interesting line + (forward-char 3) + (setq name (buffer-substring-no-properties (point) (svn-point-at-eol))) + (setq result (cons (list name action) + result)) + (setq skip nil)) + (forward-line 1)) + result))) +;; (svn-status-parse-update-output) +;; (svn-status-update-with-command-list (svn-status-parse-update-output)) + +(defun svn-status-parse-property-output () + "Parse the output of svn propset. +Return a list that is suitable for `svn-status-update-with-command-list'" + (save-excursion + (set-buffer svn-process-buffer-name) + (let ((result)) + (dolist (line (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")) + (message "%s" line) + (when (string-match "property '\\(.+\\)' set on '\\(.+\\)'" line) + ;;(message "property %s - file %s" (match-string 1 line) (match-string 2 line)) + (setq result (cons (list (match-string 2 line) 'propset) result)))) + result))) + +;; (svn-status-parse-property-output) +;; (svn-status-update-with-command-list (svn-status-parse-property-output)) + + +(defun svn-status-line-info->symlink-p (line-info) + "Return non-nil if LINE-INFO refers to a symlink, nil otherwise. +The value is the name of the file to which it is linked. \(See +`file-symlink-p'.\) + +On win32 systems this won't work, even though symlinks are supported +by subversion on such systems." + ;; on win32 would need to see how svn does symlinks + (file-symlink-p (svn-status-line-info->filename line-info))) + +(defun svn-status-line-info->directory-p (line-info) + "Return t if LINE-INFO refers to a directory, nil otherwise. +Symbolic links to directories count as directories (see `file-directory-p')." + (file-directory-p (svn-status-line-info->filename line-info))) + +(defun svn-status-line-info->full-path (line-info) + "Return the full path of the file represented by LINE-INFO." + (expand-file-name + (svn-status-line-info->filename line-info))) + +;;Not convinced that this is the fastest way, but... +(defun svn-status-count-/ (string) + "Return number of \"/\"'s in STRING." + (let ((n 0) + (last 0)) + (while (setq last (string-match "/" string (1+ last))) + (setq n (1+ n))) + n)) + +(defun svn-insert-line-in-status-buffer (line-info) + "Format LINE-INFO and insert the result in the current buffer." + (let ((usermark (if (svn-status-line-info->has-usermark line-info) "*" " ")) + (update-available (if (svn-status-line-info->update-available line-info) + (svn-add-face (if svn-status-short-mod-flag-p + "** " + " (Update Available)") + 'svn-status-update-available-face) + (if svn-status-short-mod-flag-p " " ""))) + (filename ;; file or /path/to/file + (concat + (if (or svn-status-display-full-path + svn-status-hide-unmodified + svn-status-hide-externals) + (svn-add-face + (let ((dir-name (file-name-as-directory + (svn-status-line-info->directory-containing-line-info + line-info nil)))) + (if (and (<= 2 (length dir-name)) + (= ?. (aref dir-name 0)) + (= ?/ (aref dir-name 1))) + (substring dir-name 2) + dir-name)) + 'svn-status-directory-face) + ;; showing all files, so add indentation + (make-string (* svn-status-indentation (svn-status-count-/ + (svn-status-line-info->filename line-info))) + 32)) + ;;symlinks get a different face + (let ((target (svn-status-line-info->symlink-p line-info))) + (if target + ;; name -> trget + ;; name gets symlink-face, target gets file/directory face + (concat + (svn-add-face (svn-status-line-info->filename-nondirectory line-info) + 'svn-status-symlink-face) + " -> " + (svn-status-choose-face-to-add + ;; TODO: could use different faces for + ;; unversioned targets and broken symlinks? + (svn-status-line-info->directory-p line-info) + target + 'svn-status-directory-face + 'svn-status-filename-face)) + ;; else target is not a link + (svn-status-choose-face-to-add + (svn-status-line-info->directory-p line-info) + (svn-status-line-info->filename-nondirectory line-info) + 'svn-status-directory-face + 'svn-status-filename-face))) + )) + (elide-hint (if (svn-status-line-info->show-user-elide-continuation line-info) " ..." ""))) + (svn-puthash (svn-status-line-info->filename line-info) + (point) + svn-status-filename-to-buffer-position-cache) + (insert (svn-status-maybe-add-face + (svn-status-line-info->has-usermark line-info) + (concat usermark + (format svn-status-line-format + (svn-status-line-info->filemark line-info) + (or (svn-status-line-info->propmark line-info) ? ) + (or (svn-status-line-info->historymark line-info) ? ) + (or (svn-status-line-info->localrev line-info) "") + (or (svn-status-line-info->lastchangerev line-info) "") + (svn-status-line-info->author line-info)) + (when svn-status-short-mod-flag-p update-available) + filename + (unless svn-status-short-mod-flag-p update-available) + (svn-status-maybe-add-string (svn-status-line-info->locked line-info) + " [ LOCKED ]" 'svn-status-locked-face) + (svn-status-maybe-add-string (svn-status-line-info->repo-locked line-info) + (let ((flag (svn-status-line-info->repo-locked line-info))) + (cond ((eq flag ?K) " [ REPO-LOCK-HERE ]") + ((eq flag ?O) " [ REPO-LOCK-OTHER ]") + ((eq flag ?T) " [ REPO-LOCK-STOLEN ]") + ((eq flag ?B) " [ REPO-LOCK-BROKEN ]") + (t " [ REPO-LOCK-UNKNOWN ]"))) + 'svn-status-locked-face) + (svn-status-maybe-add-string (eq (svn-status-line-info->switched line-info) ?S) + " (switched)" 'svn-status-switched-face) + elide-hint) + 'svn-status-marked-face) + "\n"))) + +(defun svn-status-redraw-status-buffer () + "Redraw the `svn-status-buffer-name' buffer. +Additionally clear the psvn-extra-info field in all line-info lists." + (interactive) + (dolist (line-info svn-status-info) + (svn-status-line-info->set-psvn-extra-info line-info nil)) + (svn-status-update-buffer)) + +(defun svn-status-update-buffer () + "Update the `svn-status-buffer-name' buffer, using `svn-status-info'. + This function does not access the repository." + (interactive) + ;(message "buffer-name: %s" (buffer-name)) + (unless (string= (buffer-name) svn-status-buffer-name) + (set-buffer svn-status-buffer-name)) + (svn-status-mode) + (when svn-status-refresh-info + (when (eq svn-status-refresh-info 'once) + (setq svn-status-refresh-info nil)) + (svn-status-parse-info t)) + (let ((st-info svn-status-info) + (buffer-read-only nil) + (start-pos) + (overlay) + (unmodified-count 0) ;how many unmodified files are hidden + (unknown-count 0) ;how many unknown files are hidden + (externals-count 0) ;how many svn:externals files are hidden + (custom-hide-count 0) ;how many files are hidden via svn-status-custom-hide-function + (marked-count 0) ;how many files are elided + (user-elide-count 0) + (first-line t) + (fname (svn-status-line-info->filename (svn-status-get-line-information))) + (fname-pos (point)) + (window-line-pos (svn-status-window-line-position (get-buffer-window (current-buffer)))) + (header-line-string) + (column (current-column))) + (delete-region (point-min) (point-max)) + (insert "\n") + ;; Insert all files and directories + (while st-info + (setq start-pos (point)) + (cond ((or (svn-status-line-info->has-usermark (car st-info)) first-line) + ;; Show a marked file and the "." always + (svn-insert-line-in-status-buffer (car st-info)) + (setq first-line nil)) + ((svn-status-line-info->update-available (car st-info)) + (svn-insert-line-in-status-buffer (car st-info))) + ((and svn-status-custom-hide-function + (apply svn-status-custom-hide-function (list (car st-info)))) + (setq custom-hide-count (1+ custom-hide-count))) + ((svn-status-line-info->hide-because-user-elide (car st-info)) + (setq user-elide-count (1+ user-elide-count))) + ((svn-status-line-info->hide-because-unknown (car st-info)) + (setq unknown-count (1+ unknown-count))) + ((svn-status-line-info->hide-because-unmodified (car st-info)) + (setq unmodified-count (1+ unmodified-count))) + ((svn-status-line-info->hide-because-externals (car st-info)) + (setq externals-count (1+ externals-count))) + (t + (svn-insert-line-in-status-buffer (car st-info)))) + (when (svn-status-line-info->has-usermark (car st-info)) + (setq marked-count (+ marked-count 1))) + (setq overlay (make-overlay start-pos (point))) + (overlay-put overlay 'svn-info (car st-info)) + (overlay-put overlay 'evaporate t) + (setq st-info (cdr st-info))) + ;; Insert status information at the buffer beginning + (goto-char (point-min)) + (insert (format "svn status for directory %s%s\n" + default-directory + (if svn-status-head-revision (format " (status against revision: %s)" + svn-status-head-revision) + ""))) + (when svn-status-module-name + (insert (format "Project name: %s\n" svn-status-module-name))) + (when svn-status-branch-list + (insert (format "Branches: %s\n" svn-status-branch-list))) + (when svn-status-base-info + (insert (concat "Repository Root: " (svn-status-base-info->repository-root) "\n")) + (insert (concat "Repository Url: " (svn-status-base-info->url) "\n"))) + (when svn-status-hide-unknown + (insert + (format "%d Unknown file(s) are hidden - press `?' to toggle hiding\n" + unknown-count))) + (when svn-status-hide-unmodified + (insert + (format "%d Unmodified file(s) are hidden - press `_' to toggle hiding\n" + unmodified-count))) + (when svn-status-hide-externals + (insert + (format "%d Externals file(s) are hidden - press `z' to toggle hiding\n" + externals-count))) + (when (> custom-hide-count 0) + (insert + (format "%d file(s) are hidden via the svn-status-custom-hide-function\n" + custom-hide-count))) + (when (> user-elide-count 0) + (insert (format "%d file(s) elided\n" user-elide-count))) + (insert (format "%d file(s) marked\n" marked-count)) + (setq header-line-string (concat (format svn-status-line-format + 70 80 72 "BASE" "CMTD" "Author") + (if svn-status-short-mod-flag-p "em " "") + "File")) + (cond ((eq svn-status-use-header-line t) + (setq header-line-format (concat " " header-line-string))) + ((eq svn-status-use-header-line 'inline) + (insert "\n " header-line-string "\n"))) + (setq svn-start-of-file-list-line-number (+ (count-lines (point-min) (point)) 1)) + (if fname + (progn + (goto-char fname-pos) + (svn-status-goto-file-name fname) + (goto-char (+ column (svn-point-at-bol))) + (when window-line-pos + (recenter window-line-pos))) + (goto-char (+ (next-overlay-change (point-min)) svn-status-default-column))))) + +(defun svn-status-parse-info (arg) + "Parse the svn info output for the base directory. +Show the repository url after this call in the `svn-status-buffer-name' buffer. +When called with the prefix argument 0, reset the information to nil. +This hides the repository information again. + +When ARG is t, don't update the svn status buffer. This is useful for +non-interactive use." + (interactive "P") + (if (eq arg 0) + (setq svn-status-base-info nil) + (let ((svn-process-buffer-name "*svn-info-output*")) + (when (get-buffer svn-process-buffer-name) + (kill-buffer svn-process-buffer-name)) + (svn-run nil t 'parse-info "info" ".") + (svn-status-parse-info-result))) + (unless (eq arg t) + (svn-status-update-buffer))) + +(defun svn-status-parse-info-result () + "Parse the result from the svn info command. +Put the found values in `svn-status-base-info'." + (save-excursion + (setq svn-status-base-info ()) + (set-buffer svn-process-buffer-name) + (goto-char (point-min)) + (let ((case-fold-search t) + (key) + (val)) + (loop while (looking-at "\\(.*?\\)\\s-*:\\s-*\\(.*\\)$") + do (setq key (intern (concat ":" (downcase (subst-char-in-string ?\ ?- (match-string 1)))))) + (setq val (match-string 2)) + (setq svn-status-base-info (plist-put svn-status-base-info + key val)) + until (< 0 (forward-line)))))) + +(defun svn-status-base-info->url () + "Extract the url part from `svn-status-base-info'." + (plist-get svn-status-base-info :url)) + +(defun svn-status-base-info->repository-root () + "Extract the repository-root part from `svn-status-base-info'." + (plist-get svn-status-base-info :repository-root)) + +(defun svn-status-checkout-prefix-path () + "When only a part of the svn repository is checked out, return the file path for this checkout." + (interactive) + (svn-status-parse-info t) + (let ((root (svn-status-base-info->repository-root)) + (url (svn-status-base-info->url)) + (p) + (base-dir (svn-status-base-dir)) + (wc-checkout-prefix)) + (setq p (substring url (length root))) + (setq wc-checkout-prefix (file-relative-name default-directory base-dir)) + (when (string= wc-checkout-prefix "./") + (setq wc-checkout-prefix "")) + ;; (message "svn-status-checkout-prefix-path: wc-checkout-prefix: '%s' p: '%s' base-dir: %s" wc-checkout-prefix p base-dir) + (setq p (substring p 0 (- (length p) (length wc-checkout-prefix)))) + (when (interactive-p) + (message "svn-status-checkout-prefix-path: '%s'" p)) + p)) + +(defun svn-status-ls (path &optional synchron) + "Run svn ls PATH." + (interactive "sPath for svn ls: ") + (svn-run (not synchron) t 'ls "ls" path) + (when synchron + (split-string (with-current-buffer svn-process-buffer-name + (buffer-substring-no-properties (point-min) (point-max)))))) + +(defun svn-status-ls-branches () + "Show, which branches exist for the actual working copy. +Note: this command assumes the proposed standard svn repository layout." + (interactive) + (svn-status-parse-info t) + (svn-status-ls (concat (svn-status-base-info->repository-root) "/branches"))) + +(defun svn-status-ls-tags () + "Show, which tags exist for the actual working copy. +Note: this command assumes the proposed standard svn repository layout." + (interactive) + (svn-status-parse-info t) + (svn-status-ls (concat (svn-status-base-info->repository-root) "/tags"))) + +(defun svn-status-toggle-edit-cmd-flag (&optional reset) + "Allow the user to edit the parameters for the next svn command. +This command toggles between +* editing the next command parameters (EditCmd) +* editing all all command parameters (EditCmd#) +* don't edit the command parameters () +The string in parentheses is shown in the status line to show the state." + (interactive) + (cond ((or reset (eq svn-status-edit-svn-command 'sticky)) + (setq svn-status-edit-svn-command nil)) + ((eq svn-status-edit-svn-command nil) + (setq svn-status-edit-svn-command t)) + ((eq svn-status-edit-svn-command t) + (setq svn-status-edit-svn-command 'sticky))) + (cond ((eq svn-status-edit-svn-command t) + (setq svn-status-mode-line-process-edit-flag " EditCmd")) + ((eq svn-status-edit-svn-command 'sticky) + (setq svn-status-mode-line-process-edit-flag " EditCmd#")) + (t + (setq svn-status-mode-line-process-edit-flag ""))) + (svn-status-update-mode-line)) + +(defun svn-status-goto-root-or-return () + "Bounce point between the root (\".\") and the current line." + (interactive) + (if (string= (svn-status-line-info->filename (svn-status-get-line-information)) ".") + (when svn-status-root-return-info + (svn-status-goto-file-name + (svn-status-line-info->filename svn-status-root-return-info))) + (setq svn-status-root-return-info (svn-status-get-line-information)) + (svn-status-goto-file-name "."))) + +(defun svn-status-next-line (nr-of-lines) + "Go to the next line that holds a file information. +When called with a prefix argument advance the given number of lines." + (interactive "p") + (while (progn + (forward-line nr-of-lines) + (and (not (eobp)) + (not (svn-status-get-line-information))))) + (when (svn-status-get-line-information) + (goto-char (+ (svn-point-at-bol) svn-status-default-column)))) + +(defun svn-status-previous-line (nr-of-lines) + "Go to the previous line that holds a file information. +When called with a prefix argument go back the given number of lines." + (interactive "p") + (while (progn + (forward-line (- nr-of-lines)) + (and (not (bobp)) + (not (svn-status-get-line-information))))) + (when (svn-status-get-line-information) + (goto-char (+ (svn-point-at-bol) svn-status-default-column)))) + +(defun svn-status-dired-jump () + "Jump to a dired buffer, containing the file at point." + (interactive) + (let* ((line-info (svn-status-get-line-information)) + (file-full-path (if line-info + (svn-status-line-info->full-path line-info) + default-directory))) + (let ((default-directory + (file-name-as-directory + (expand-file-name (if line-info + (svn-status-line-info->directory-containing-line-info line-info t) + default-directory))))) + (if (fboundp 'dired-jump-back) (dired-jump-back) (dired-jump))) ;; Xemacs uses dired-jump-back + (dired-goto-file file-full-path))) + +(defun svn-status-possibly-negate-meaning-of-arg (arg &optional command) + "Negate arg, if this-command is a member of svn-status-possibly-negate-meaning-of-arg." + (unless command + (setq command this-command)) + (if (member command svn-status-negate-meaning-of-arg-commands) + (not arg) + arg)) + +(defun svn-status-update (&optional arg) + "Run 'svn status -v'. +When called with a prefix argument run 'svn status -vu'." + (interactive "P") + (unless (interactive-p) + (save-excursion + (set-buffer svn-process-buffer-name) + (setq svn-status-update-previous-process-output + (buffer-substring (point-min) (point-max))))) + (svn-status default-directory arg)) + +(defun svn-status-get-line-information () + "Find out about the file under point. +The result may be parsed with the various `svn-status-line-info->...' functions." + (if (eq major-mode 'svn-status-mode) + (let ((svn-info nil)) + (dolist (overlay (overlays-at (point))) + (setq svn-info (or svn-info + (overlay-get overlay 'svn-info)))) + svn-info) + ;; different mode, means called not from the *svn-status* buffer + (if svn-status-get-line-information-for-file + (svn-status-make-line-info (if (eq svn-status-get-line-information-for-file 'relative) + (file-relative-name (buffer-file-name) (svn-status-base-dir)) + (buffer-file-name))) + (svn-status-make-line-info ".")))) + + +(defun svn-status-get-file-list (use-marked-files) + "Get either the selected files or the file under point. +USE-MARKED-FILES decides which we do. +See `svn-status-marked-files' for what counts as selected." + (if use-marked-files + (svn-status-marked-files) + (list (svn-status-get-line-information)))) + +(defun svn-status-get-file-list-names (use-marked-files) + (mapcar 'svn-status-line-info->filename (svn-status-get-file-list use-marked-files))) + +(defun svn-status-get-file-information () + "Find out about the file under point. +The result may be parsed with the various `svn-status-line-info->...' functions. +When called from a *svn-status* buffer, do the same as `svn-status-get-line-information'. +When called from a file buffer provide a structure that contains the filename." + (cond ((eq major-mode 'svn-status-mode) + (svn-status-get-line-information)) + (t + ;; a fake structure that contains the buffername for the current buffer + (svn-status-make-line-info (buffer-file-name (current-buffer)))))) + +(defun svn-status-select-line () + "Return information about the file under point. +\(Only used for debugging\)" + (interactive) + (let ((info (svn-status-get-line-information))) + (if info + (message "%S hide-because-unknown: %S hide-because-unmodified: %S hide-because-externals: %S" info + (svn-status-line-info->hide-because-unknown info) + (svn-status-line-info->hide-because-unmodified info) + (svn-status-line-info->hide-because-externals info)) + (message "No file on this line")))) + (defun svn-status-ensure-cursor-on-file () + "Raise an error unless point is on a valid file." + (unless (svn-status-get-line-information) + (error "No file on the current line"))) + +(defun svn-status-directory-containing-point (allow-self) + "Find the (full path of) directory containing the file under point. + +If ALLOW-SELF and the file is a directory, return that directory, +otherwise return the directory containing the file under point." + ;;the first `or' below is because s-s-g-l-i returns `nil' if + ;;point was outside the file list, but we need + ;;s-s-l-i->f to return a string to add to `default-directory'. + (let ((line-info (or (svn-status-get-line-information) + (svn-status-make-line-info)))) + (file-name-as-directory + (expand-file-name + (svn-status-line-info->directory-containing-line-info line-info allow-self))))) + +(defun svn-status-line-info->directory-containing-line-info (line-info allow-self) + "Find the directory containing for LINE-INFO. + +If ALLOW-SELF is t and LINE-INFO refers to a directory then return the +directory itself, in all other cases find the parent directory" + (if (and allow-self (svn-status-line-info->directory-p line-info)) + (svn-status-line-info->filename line-info) + ;;The next `or' is because (file-name-directory "file") returns nil + (or (file-name-directory (svn-status-line-info->filename line-info)) + "."))) + +(defun svn-status-set-user-mark (arg) + "Set a user mark on the current file or directory. +If the cursor is on a file this file is marked and the cursor advances to the next line. +If the cursor is on a directory all files in this directory are marked. + +If this function is called with a prefix argument, only the current line is +marked, even if it is a directory." + (interactive "P") + (setq arg (svn-status-possibly-negate-meaning-of-arg arg 'svn-status-set-user-mark)) + (let ((info (svn-status-get-line-information))) + (if info + (progn + (svn-status-apply-usermark t arg) + (svn-status-next-line 1)) + (message "No file on this line - cannot set a mark")))) + +(defun svn-status-unset-user-mark (arg) + "Remove a user mark on the current file or directory. +If the cursor is on a file, this file is unmarked and the cursor advances to the next line. +If the cursor is on a directory, all files in this directory are unmarked. + +If this function is called with a prefix argument, only the current line is +unmarked, even if is a directory." + (interactive "P") + (setq arg (svn-status-possibly-negate-meaning-of-arg arg 'svn-status-set-user-mark)) + (let ((info (svn-status-get-line-information))) + (if info + (progn + (svn-status-apply-usermark nil arg) + (svn-status-next-line 1)) + (message "No file on this line - cannot unset a mark")))) + +(defun svn-status-unset-user-mark-backwards () + "Remove a user mark from the previous file. +Then move to that line." + ;; This is consistent with `dired-unmark-backward' and + ;; `cvs-mode-unmark-up'. + (interactive) + (let ((info (save-excursion + (svn-status-next-line -1) + (svn-status-get-line-information)))) + (if info + (progn + (svn-status-next-line -1) + (svn-status-apply-usermark nil t)) + (message "No file on previous line - cannot unset a mark")))) + +(defun svn-status-apply-usermark (set-mark only-this-line) + "Do the work for the various marking/unmarking functions." + (let* ((st-info svn-status-info) + (mark-count 0) + (line-info (svn-status-get-line-information)) + (file-name (svn-status-line-info->filename line-info)) + (sub-file-regexp (if (file-directory-p file-name) + (concat "^" (regexp-quote + (file-name-as-directory file-name))) + nil)) + (newcursorpos-fname) + (i-fname) + (first-line t) + (current-line svn-start-of-file-list-line-number)) + (while st-info + (when (or (svn-status-line-info->is-visiblep (car st-info)) first-line) + (setq current-line (1+ current-line)) + (setq first-line nil)) + (setq i-fname (svn-status-line-info->filename (car st-info))) + (when (or (string= file-name i-fname) + (when sub-file-regexp + (string-match sub-file-regexp i-fname))) + (when (svn-status-line-info->is-visiblep (car st-info)) + (when (or (not only-this-line) (string= file-name i-fname)) + (setq newcursorpos-fname i-fname) + (unless (eq (car (svn-status-line-info->ui-status (car st-info))) set-mark) + (setcar (svn-status-line-info->ui-status (car st-info)) set-mark) + (setq mark-count (+ 1 mark-count)) + (save-excursion + (let ((buffer-read-only nil)) + (goto-line current-line) + (delete-region (svn-point-at-bol) (svn-point-at-eol)) + (svn-insert-line-in-status-buffer (car st-info)) + (delete-char 1))) + (message "%s %s" (if set-mark "Marked" "Unmarked") i-fname))))) + (setq st-info (cdr st-info))) + ;;(svn-status-update-buffer) + (svn-status-goto-file-name newcursorpos-fname) + (when (> mark-count 1) + (message "%s %d files" (if set-mark "Marked" "Unmarked") mark-count)))) + +(defun svn-status-apply-usermark-checked (check-function set-mark) + "Mark or unmark files, whether a given function returns t. +The function is called with the line information. Therefore the +svn-status-line-info->* functions can be used in the check." + (let ((st-info svn-status-info) + (mark-count 0)) + (while st-info + (when (apply check-function (list (car st-info))) + (unless (eq (svn-status-line-info->has-usermark (car st-info)) set-mark) + (setq mark-count (+ 1 mark-count)) + (message "%s %s" + (if set-mark "Marked" "Unmarked") + (svn-status-line-info->filename (car st-info)))) + (setcar (svn-status-line-info->ui-status (car st-info)) set-mark)) + (setq st-info (cdr st-info))) + (svn-status-update-buffer) + (when (> mark-count 1) + (message "%s %d files" (if set-mark "Marked" "Unmarked") mark-count)))) + +(defun svn-status-mark-unknown (arg) + "Mark all unknown files. +These are the files marked with '?' in the `svn-status-buffer-name' buffer. +If the function is called with a prefix arg, unmark all these files." + (interactive "P") + (svn-status-apply-usermark-checked + '(lambda (info) (eq (svn-status-line-info->filemark info) ??)) (not arg))) + +(defun svn-status-mark-added (arg) + "Mark all added files. +These are the files marked with 'A' in the `svn-status-buffer-name' buffer. +If the function is called with a prefix ARG, unmark all these files." + (interactive "P") + (svn-status-apply-usermark-checked + '(lambda (info) (eq (svn-status-line-info->filemark info) ?A)) (not arg))) + +(defun svn-status-mark-modified (arg) + "Mark all modified files. +These are the files marked with 'M' in the `svn-status-buffer-name' buffer. +Changed properties are considered. +If the function is called with a prefix ARG, unmark all these files." + (interactive "P") + (svn-status-apply-usermark-checked + '(lambda (info) (or (eq (svn-status-line-info->filemark info) ?M) + (eq (svn-status-line-info->filemark info) + svn-status-file-modified-after-save-flag) + (eq (svn-status-line-info->propmark info) ?M))) + (not arg))) + +(defun svn-status-mark-modified-properties (arg) + "Mark all files and directories with modified properties. +If the function is called with a prefix ARG, unmark all these entries." + (interactive "P") + (svn-status-apply-usermark-checked + '(lambda (info) (or (eq (svn-status-line-info->propmark info) ?M))) + (not arg))) + +(defun svn-status-mark-deleted (arg) + "Mark all files scheduled for deletion. +These are the files marked with 'D' in the `svn-status-buffer-name' buffer. +If the function is called with a prefix ARG, unmark all these files." + (interactive "P") + (svn-status-apply-usermark-checked + '(lambda (info) (eq (svn-status-line-info->filemark info) ?D)) (not arg))) + +(defun svn-status-mark-changed (arg) + "Mark all files that could be committed. +This means we mark +* all modified files +* all files scheduled for addition +* all files scheduled for deletion +* all files with modified properties + +The last two categories include all copied and moved files. +If called with a prefix ARG, unmark all such files." + (interactive "P") + (svn-status-mark-added arg) + (svn-status-mark-modified arg) + (svn-status-mark-deleted arg) + (svn-status-mark-modified-properties arg)) + +(defun svn-status-unset-all-usermarks () + (interactive) + (svn-status-apply-usermark-checked '(lambda (info) t) nil)) + +(defun svn-status-store-usermarks (arg) + "Store the current usermarks in `svn-status-usermark-storage'. +When called with a prefix argument it is possible to store different sets of marks." + (interactive "P") + (let ((file-list (svn-status-get-file-list-names t))) + (svn-puthash arg file-list svn-status-usermark-storage) + (message "psvn stored %d user marks" (length file-list)))) + +(defun svn-status-load-usermarks (arg) + "Load previously stored user marks from `svn-status-usermark-storage'. +When called with a prefix argument it is possible to store/load different sets of marks." + (interactive "P") + (let ((file-list (gethash arg svn-status-usermark-storage))) + (svn-status-apply-usermark-checked + '(lambda (info) (member (svn-status-line-info->filename info) file-list)) t))) + +(defvar svn-status-regexp-history nil + "History list of regular expressions used in svn status commands.") + +(defun svn-status-read-regexp (prompt) + (read-from-minibuffer prompt nil nil nil 'svn-status-regexp-history)) + +(defun svn-status-mark-filename-regexp (regexp &optional unmark) + "Mark all files matching REGEXP. +If the function is called with a prefix arg, unmark all these files." + (interactive + (list (svn-status-read-regexp (concat (if current-prefix-arg "Unmark" "Mark") + " files (regexp): ")) + (if current-prefix-arg t nil))) + (svn-status-apply-usermark-checked + '(lambda (info) (string-match regexp (svn-status-line-info->filename-nondirectory info))) (not unmark))) + +(defun svn-status-mark-by-file-ext (ext &optional unmark) + "Mark all files matching the given file extension EXT. +If the function is called with a prefix arg, unmark all these files." + (interactive + (list (read-string (concat (if current-prefix-arg "Unmark" "Mark") + " files with extensions: ")) + (if current-prefix-arg t nil))) + (svn-status-apply-usermark-checked + '(lambda (info) (let ((case-fold-search nil)) + (string-match (concat "\\." ext "$") (svn-status-line-info->filename-nondirectory info)))) (not unmark))) + +(defun svn-status-toggle-hide-unknown () + (interactive) + (setq svn-status-hide-unknown (not svn-status-hide-unknown)) + (svn-status-update-buffer)) + +(defun svn-status-toggle-hide-unmodified () + (interactive) + (setq svn-status-hide-unmodified (not svn-status-hide-unmodified)) + (svn-status-update-buffer)) + +(defun svn-status-toggle-hide-externals () + (interactive) + (setq svn-status-hide-externals (not svn-status-hide-externals)) + (svn-status-update-buffer)) + +(defun svn-status-get-file-name-buffer-position (name) + "Find the buffer position for a file. +If the file is not found, return nil." + (let ((start-pos (let ((cached-pos (gethash name + svn-status-filename-to-buffer-position-cache))) + (when cached-pos + (goto-char (previous-overlay-change cached-pos))) + (point))) + (found)) + ;; performance optimization: search from point to end of buffer + (while (and (not found) (< (point) (point-max))) + (goto-char (next-overlay-change (point))) + (when (string= name (svn-status-line-info->filename + (svn-status-get-line-information))) + (setq start-pos (+ (point) svn-status-default-column)) + (setq found t))) + ;; search from buffer start to point + (goto-char (point-min)) + (while (and (not found) (< (point) start-pos)) + (goto-char (next-overlay-change (point))) + (when (string= name (svn-status-line-info->filename + (svn-status-get-line-information))) + (setq start-pos (+ (point) svn-status-default-column)) + (setq found t))) + (and found start-pos))) + +(defun svn-status-goto-file-name (name) + "Move the cursor the the line that displays NAME." + (let ((pos (svn-status-get-file-name-buffer-position name))) + (if pos + (goto-char pos) + (svn-status-message 7 "Note: svn-status-goto-file-name: %s not found" name)))) + +(defun svn-status-find-info-for-file-name (name) + (let* ((st-info svn-status-info) + (info)) + (while st-info + (when (string= name (svn-status-line-info->filename (car st-info))) + (setq info (car st-info)) + (setq st-info nil)) ; terminate loop + (setq st-info (cdr st-info))) + info)) + +(defun svn-status-marked-files () + "Return all files marked by `svn-status-set-user-mark', +or (if no files were marked) the file under point." + (if (eq major-mode 'svn-status-mode) + (let* ((st-info svn-status-info) + (file-list)) + (while st-info + (when (svn-status-line-info->has-usermark (car st-info)) + (setq file-list (append file-list (list (car st-info))))) + (setq st-info (cdr st-info))) + (or file-list + (if (svn-status-get-line-information) + (list (svn-status-get-line-information)) + nil))) + ;; different mode, means called not from the *svn-status* buffer + (if svn-status-get-line-information-for-file + (list (svn-status-make-line-info (if (eq svn-status-get-line-information-for-file 'relative) + (file-relative-name (buffer-file-name) (svn-status-base-dir)) + (buffer-file-name)))) + (list (svn-status-make-line-info "."))))) + +(defun svn-status-marked-file-names () + (mapcar 'svn-status-line-info->filename (svn-status-marked-files))) + +(defun svn-status-some-files-marked-p () + "Return non-nil iff a file has been marked by `svn-status-set-user-mark'. +Unlike `svn-status-marked-files', this does not select the file under point +if no files have been marked." + ;; `some' would be shorter but requires cl-seq at runtime. + ;; (Because it accepts both lists and vectors, it is difficult to inline.) + (loop for line-info in svn-status-info + thereis (svn-status-line-info->has-usermark line-info))) + +(defun svn-status-only-dirs-or-nothing-marked-p () + "Return non-nil iff only dirs has been marked by `svn-status-set-user-mark'." + ;; `some' would be shorter but requires cl-seq at runtime. + ;; (Because it accepts both lists and vectors, it is difficult to inline.) + (loop for line-info in svn-status-info + thereis (and (not (svn-status-line-info->directory-p line-info)) + (svn-status-line-info->has-usermark line-info)))) + +(defun svn-status-ui-information-hash-table () + (let ((st-info svn-status-info) + (svn-status-ui-information (make-hash-table :test 'equal))) + (while st-info + (svn-puthash (svn-status-line-info->filename (car st-info)) + (svn-status-line-info->ui-status (car st-info)) + svn-status-ui-information) + (setq st-info (cdr st-info))) + svn-status-ui-information)) + + +(defun svn-status-create-arg-file (file-info-list) + "Create an svn client argument file" + ;; create the arg file on the remote host when we will run svn on this host! + (let ((file-name (svn-expand-filename-for-remote-access svn-status-temp-arg-file))) + ;; (message "svn-status-create-arg-file %s: %s" default-directory file-name) + (with-temp-file file-name + (let ((st-info file-info-list)) + (while st-info + (insert (svn-status-line-info->filename (car st-info))) + (insert "\n") + (setq st-info (cdr st-info))) + (setq svn-arg-file-content (buffer-substring-no-properties (point-min) (point-max))))))) + +(defun svn-status-show-process-buffer-internal (&optional scroll-to-top) + (let ((cur-buff (current-buffer))) + (unless svn-status-preserve-window-configuration + (when (string= (buffer-name) svn-status-buffer-name) + (delete-other-windows))) + (pop-to-buffer svn-process-buffer-name) + (svn-process-mode) + (when scroll-to-top + (goto-char (point-min))) + (pop-to-buffer cur-buff))) + +(defun svn-status-show-process-output (cmd &optional scroll-to-top) + "Display the result of a svn command. +Consider svn-status-window-alist to choose the buffer name." + (let ((window-mode (cadr (assoc cmd svn-status-window-alist))) + (process-default-directory)) + (cond ((eq window-mode nil) ;; use *svn-process* buffer + (setq svn-status-last-output-buffer-name svn-process-buffer-name)) + ((eq window-mode t) ;; use *svn-info* buffer + (setq svn-status-last-output-buffer-name "*svn-info*")) + ((eq window-mode 'invisible) ;; don't display the buffer + (setq svn-status-last-output-buffer-name nil)) + (t + (setq svn-status-last-output-buffer-name window-mode))) + (when svn-status-last-output-buffer-name + (if window-mode + (progn + (unless svn-status-preserve-window-configuration + (when (string= (buffer-name) svn-status-buffer-name) + (delete-other-windows))) + (pop-to-buffer svn-process-buffer-name) + (setq process-default-directory default-directory) + (switch-to-buffer (get-buffer-create svn-status-last-output-buffer-name)) + (setq default-directory process-default-directory) + (let ((buffer-read-only nil)) + (delete-region (point-min) (point-max)) + (insert-buffer-substring svn-process-buffer-name) + (when scroll-to-top + (goto-char (point-min)))) + (when (eq window-mode t) ;; *svn-info* buffer + (svn-info-mode)) + (other-window 1)) + (svn-status-show-process-buffer-internal scroll-to-top))))) + +(defun svn-status-svn-log-switches (arg) + (cond ((eq arg 0) '()) + ((or (eq arg -1) (eq arg '-)) '("-q")) + (arg '("-v")) + (t svn-status-default-log-arguments))) + +(defun svn-status-show-svn-log (arg) + "Run `svn log' on selected files. +The output is put into the *svn-log* buffer +The optional prefix argument ARG determines which switches are passed to `svn log': + no prefix --- use whatever is in the list `svn-status-default-log-arguments' + prefix argument of -1: --- use the -q switch (quiet) + prefix argument of 0 --- use no arguments + other prefix arguments: --- use the -v switch (verbose) + +See `svn-status-marked-files' for what counts as selected." + (interactive "P") + (let ((switches (svn-status-svn-log-switches arg)) + (svn-status-get-line-information-for-file t)) + ;; (message "svn-status-show-svn-log %S" arg) + (svn-status-create-arg-file (svn-status-marked-files)) + (svn-run t t 'log "log" "--targets" svn-status-temp-arg-file switches))) + +(defun svn-status-version () + "Show the version numbers for psvn.el and the svn command line client. +The version number of the client is cached in `svn-client-version'." + (interactive) + (let ((window-conf (current-window-configuration)) + (version-string)) + (if (or (interactive-p) (not svn-status-cached-version-string)) + (progn + (svn-run nil t 'version "--version") + (when (interactive-p) + (svn-status-show-process-output 'info t)) + (with-current-buffer svn-status-last-output-buffer-name + (goto-char (point-min)) + (setq svn-client-version + (when (re-search-forward "svn, version \\([0-9\.]+\\)" nil t) + (mapcar 'string-to-number (split-string (match-string 1) "\\.")))) + (let ((buffer-read-only nil)) + (goto-char (point-min)) + (insert (format "psvn.el revision: %s\n\n" svn-psvn-revision))) + (setq version-string (buffer-substring-no-properties (point-min) (point-max)))) + (setq svn-status-cached-version-string version-string)) + (setq version-string svn-status-cached-version-string) + (unless (interactive-p) + (set-window-configuration window-conf) + version-string)))) + +(defun svn-compute-svn-client-version () + "Ensure that svn-client-version is available." + (unless svn-client-version + (svn-status-version))) + +(defun svn-status-info () + "Run `svn info' on all selected files. +See `svn-status-marked-files' for what counts as selected." + (interactive) + (svn-status-create-arg-file (svn-status-marked-files)) + (svn-run t t 'info "info" "--targets" svn-status-temp-arg-file)) + +(defun svn-status-info-for-path (path) + "Run svn info on the given PATH. +Return some interesting parts of the resulting output. +At the moment a list containing the last changed author is returned." + (let ((svn-process-buffer-name "*svn-info-output*") + (last-changed-author)) + (svn-run nil t 'info "info" path) + (with-current-buffer svn-process-buffer-name + (goto-char (point-min)) + (when (search-forward "last changed author: " nil t) + (setq last-changed-author (buffer-substring-no-properties (point) (svn-point-at-eol))))) + (svn-status-message 7 "last-changed-author for '%s': %s" path last-changed-author) + (list last-changed-author))) + +(defun svn-status-blame (revision &optional file-name) + "Run `svn blame' on the current file. +When called with a prefix argument, ask the user for the REVISION to use. +When called from a file buffer, go to the current line in the resulting blame output." + (interactive "P") + (when current-prefix-arg + (setq revision (svn-status-read-revision-string "Blame for version: " "BASE"))) + (unless revision (setq revision "BASE")) + (setq svn-status-blame-revision revision) + (setq svn-status-blame-file-name (if file-name + file-name + (svn-status-line-info->filename (svn-status-get-file-information)))) + (svn-run t t 'blame "blame" svn-status-default-blame-arguments "-r" revision svn-status-blame-file-name)) + +(defun svn-blame-blame-again (arg) + "Run svn blame again, using the revision before the change at point. +When point is at revision 3472, run it with 3471." + (interactive "P") + (let ((rev (svn-blame-rev-at-point))) + (setq rev (number-to-string (- (string-to-number rev) 1))) + (when current-prefix-arg + (setq rev (svn-status-read-revision-string (format "Svn blame for rev#? ") rev))) + (svn-status-blame rev svn-status-blame-file-name))) + +(defun svn-status-show-svn-diff (arg) + "Run `svn diff' on the current file. +If the current file is a directory, compare it recursively. +If there is a newer revision in the repository, the diff is done against HEAD, +otherwise compare the working copy with BASE. +If ARG then prompt for revision to diff against (unless arg is '-) +When called with a negative prefix argument, do a non recursive diff." + (interactive "P") + (let ((non-recursive (or (and (numberp arg) (< arg 0)) (eq arg '-))) + (revision (if (and (not (eq arg '-)) arg) :ask :auto))) + (svn-status-ensure-cursor-on-file) + (svn-status-show-svn-diff-internal (list (svn-status-get-line-information)) (not non-recursive) + revision))) + +(defun svn-file-show-svn-diff (arg) + "Run `svn diff' on the current file. +If there is a newer revision in the repository, the diff is done against HEAD, +otherwise compare the working copy with BASE. +If ARG then prompt for revision to diff against." + (interactive "P") + (svn-status-show-svn-diff-internal (list (svn-status-make-line-info buffer-file-name)) nil + (if arg :ask :auto))) + +(defun svn-status-show-svn-diff-for-marked-files (arg) + "Run `svn diff' on all selected files. +If some files have been marked, compare those non-recursively; +this is because marking a directory with \\[svn-status-set-user-mark] +normally marks all of its files as well. +If no files have been marked, compare recursively the file at point. +If ARG then prompt for revision to diff against, else compare working copy with BASE." + (interactive "P") + (svn-status-show-svn-diff-internal (svn-status-marked-files) + (not (svn-status-some-files-marked-p)) + (if arg :ask "BASE"))) + +(defun svn-status-diff-show-changeset (rev &optional user-confirmation rev-against) + "Show the changeset for a given log entry. +When called with a prefix argument, ask the user for the revision." + (let* ((upper-rev (if rev-against rev-against rev)) + (lower-rev (if rev-against rev (number-to-string (- (string-to-number upper-rev) 1)))) + (rev-arg (concat lower-rev ":" upper-rev))) + (when user-confirmation + (setq rev-arg (read-string "Revision for changeset: " rev-arg))) + (svn-run nil t 'diff "diff" svn-status-default-diff-arguments (concat "-r" rev-arg)) + (svn-status-activate-diff-mode))) + +(defun svn-status-show-svn-diff-internal (line-infos recursive revision) + ;; REVISION must be one of: + ;; - a string: whatever the -r option allows. + ;; - `:ask': asks the user to specify the revision, which then becomes + ;; saved in `minibuffer-history' rather than in `command-history'. + ;; - `:auto': use "HEAD" if an update is known to exist, "BASE" otherwise. + ;; In the future, `nil' might mean omit the -r option entirely; + ;; but that currently seems to imply "BASE", so we just use that. + (when (eq revision :ask) + (setq revision (svn-status-read-revision-string + "Diff with files for version: " "PREV"))) + + (setq svn-status-last-diff-options (list line-infos recursive revision)) + + (let ((clear-buf t) + (beginning nil)) + (dolist (line-info line-infos) + (svn-run nil clear-buf 'diff "diff" svn-status-default-diff-arguments + "-r" (if (eq revision :auto) + (if (svn-status-line-info->update-available line-info) + "HEAD" "BASE") + revision) + (unless recursive "--non-recursive") + (svn-status-line-info->filename line-info)) + (setq clear-buf nil) + + ;; "svn diff --non-recursive" skips only subdirectories, not files. + ;; But a non-recursive diff via psvn should skip files too, because + ;; the user would have marked them if he wanted them to be compared. + ;; So we'll look for the "Index: foo" line that marks the first file + ;; in the diff output, and delete it and everything that follows. + ;; This is made more complicated by the fact that `svn-status-activate-diff-mode' + ;; expects the output to be left in the *svn-process* buffer. + (unless recursive + ;; Check `directory-p' relative to the `default-directory' of the + ;; "*svn-status*" buffer, not that of the svn-process-buffer-name buffer. + (let ((directory-p (svn-status-line-info->directory-p line-info))) + (with-current-buffer svn-process-buffer-name + (when directory-p + (goto-char (or beginning (point-min))) + (when (re-search-forward "^Index: " nil t) + (delete-region (match-beginning 0) (point-max)))) + (goto-char (setq beginning (point-max)))))))) + (svn-status-activate-diff-mode)) + +(defun svn-status-diff-save-current-defun-as-kill () + "Copy the function name for the change at point to the kill-ring. +That function uses `add-log-current-defun'" + (interactive) + (let ((func-name (add-log-current-defun))) + (if func-name + (progn + (kill-new func-name) + (message "Copied %S" func-name)) + (message "No current defun detected.")))) + +(defun svn-status-diff-pop-to-commit-buffer () + "Temporary switch to the `svn-status-buffer-name' buffer and start a commit from there." + (interactive) + (let ((window-conf (current-window-configuration))) + (svn-status-switch-to-status-buffer) + (svn-status-commit) + (set-window-configuration window-conf) + (setq svn-status-pre-commit-window-configuration window-conf) + (pop-to-buffer svn-log-edit-buffer-name))) + +(defun svn-status-activate-diff-mode () + "Show the `svn-process-buffer-name' buffer, using the diff-mode." + (svn-status-show-process-output 'diff t) + (let ((working-directory default-directory)) + (save-excursion + (set-buffer svn-status-last-output-buffer-name) + (setq default-directory working-directory) + (svn-status-diff-mode) + (setq buffer-read-only t)))) + +(define-derived-mode svn-status-diff-mode fundamental-mode "svn-diff" + "Major mode to display svn diffs. Derives from `diff-mode'. + +Commands: +\\{svn-status-diff-mode-map} +" + (let ((diff-mode-shared-map (copy-keymap svn-status-diff-mode-map)) + major-mode mode-name) + (diff-mode) + (set (make-local-variable 'revert-buffer-function) 'svn-status-diff-update))) + +(defun svn-status-diff-update (arg noconfirm) + "Rerun the last svn diff command and update the *svn-diff* buffer." + (interactive) + (svn-status-save-some-buffers) + (save-window-excursion + (apply 'svn-status-show-svn-diff-internal svn-status-last-diff-options))) + +(defun svn-status-show-process-buffer () + "Show the content of the `svn-process-buffer-name' buffer" + (interactive) + (svn-status-show-process-output nil)) + +(defun svn-status-pop-to-partner-buffer () + "Pop to the `svn-status-partner-buffer' if that variable is set." + (interactive) + (when svn-status-partner-buffer + (let ((cur-buf (current-buffer))) + (pop-to-buffer svn-status-partner-buffer) + (setq svn-status-partner-buffer cur-buf)))) + +(defun svn-status-pop-to-new-partner-buffer (buffer) + "Call `pop-to-buffer' and register the current buffer as partner buffer for BUFFER." + (let ((cur-buf (current-buffer))) + (pop-to-buffer buffer) + (setq svn-status-partner-buffer cur-buf))) + +(defun svn-status-add-file-recursively (arg) + "Run `svn add' on all selected files. +When a directory is added, add files recursively. +See `svn-status-marked-files' for what counts as selected. +When this function is called with a prefix argument, use the actual file instead." + (interactive "P") + (message "adding: %S" (svn-status-get-file-list-names (not arg))) + (svn-status-create-arg-file (svn-status-get-file-list (not arg))) + (svn-run t t 'add "add" "--targets" svn-status-temp-arg-file)) + +(defun svn-status-add-file (arg) + "Run `svn add' on all selected files. +When a directory is added, don't add the files of the directory + (svn add --non-recursive is called). +See `svn-status-marked-files' for what counts as selected. +When this function is called with a prefix argument, use the actual file instead." + (interactive "P") + (message "adding: %S" (svn-status-get-file-list-names (not arg))) + (svn-status-create-arg-file (svn-status-get-file-list (not arg))) + (svn-run t t 'add "add" "--non-recursive" "--targets" svn-status-temp-arg-file)) + +(defun svn-status-lock (arg) + "Run `svn lock' on all selected files. +See `svn-status-marked-files' for what counts as selected." + (interactive "P") + (message "locking: %S" (svn-status-get-file-list-names t)) + (svn-status-create-arg-file (svn-status-get-file-list t)) + (svn-run t t 'lock "lock" "--targets" svn-status-temp-arg-file)) + +(defun svn-status-unlock (arg) + "Run `svn unlock' on all selected files. +See `svn-status-marked-files' for what counts as selected." + (interactive "P") + (message "unlocking: %S" (svn-status-get-file-list-names t)) + (svn-status-create-arg-file (svn-status-get-file-list t)) + (svn-run t t 'unlock "unlock" "--targets" svn-status-temp-arg-file)) + +(defun svn-status-make-directory (dir) + "Run `svn mkdir DIR'." + ;; TODO: Allow entering a URI interactively. + ;; Currently, `read-file-name' corrupts it. + (interactive (list (read-file-name "Make directory: " + (svn-status-directory-containing-point t)))) + (unless (string-match "^[^:/]+://" dir) ; Is it a URI? + (setq dir (file-relative-name dir))) + (svn-run t t 'mkdir "mkdir" "--" dir)) + +(defun svn-status-mv () + "Prompt for a destination, and `svn mv' selected files there. +See `svn-status-marked-files' for what counts as `selected'. + +If one file was selected then the destination DEST should be a +filename to rename the selected file to, or a directory to move the +file into; if multiple files were selected then DEST should be a +directory to move the selected files into. + +The default DEST is the directory containing point. + +BUG: If we've marked some directory containging a file as well as the +file itself, then we should just mv the directory, but this implementation +doesn't check for that. +SOLUTION: for each dir, umark all its contents (but not the dir +itself) before running mv." + (interactive) + (svn-status-mv-cp "mv" "Rename" "Move" "mv")) + +(defun svn-status-cp () + "See `svn-status-mv'" + (interactive) + (svn-status-mv-cp "cp" "Copy" "Copy" "cp")) + +(defun svn-status-mv-cp (command singleprompt manyprompt fallback) + "Run svn COMMAND on marked files, prompting for destination + +This function acts on `svn-status-marked-files': at the prompt the +user can enter a new file name, or an existing directory: this is used as the argument for svn COMMAND. + COMMAND --- string saying what to do: \"mv\" or \"cp\" + SINGLEPROMPT --- string at start of prompt when one file marked + MANYPROMPT --- string at start of prompt when multiple files marked + FALLBACK --- If any marked file is unversioned, use this instead of 'svn COMMAND'" + (let* ((marked-files (svn-status-marked-files)) + (num-of-files (length marked-files)) + dest) + (if (= 1 num-of-files) + ;; one file to act on: new name, or directory to hold results + (setq dest (read-file-name + (format "%s %s to: " singleprompt + (svn-status-line-info->filename (car marked-files))) + (svn-status-directory-containing-point t) + (svn-status-line-info->full-path (car marked-files)))) + ;;TODO: (when file-exists-p but-no-dir-p dest (error "%s already exists" dest)) + ;;multiple files selected, so prompt for existing directory to mv them into. + (setq dest (expand-file-name + (svn-read-directory-name + (format "%s %d files to directory: " manyprompt num-of-files) + (svn-status-directory-containing-point t) nil t))) + (unless (file-directory-p dest) + (error "%s is not a directory" dest))) + (when (string= dest "") + (error "No destination entered")) + (unless (string-match "^[^:/]+://" dest) ; Is it a URI? + (setq dest (file-relative-name dest))) + + ;;do the move: svn mv only lets us move things once at a time, so + ;;we need to run svn mv once for each file (hence second arg to + ;;svn-run is nil.) + + ;;TODO: before doing any moving, For every marked directory, + ;;ensure none of its contents are also marked, since we dont want + ;;to move both file *and* its parent... + ;; what about elided files? what if user marks a dir+contents, then presses `_' ? +;; ;one solution: +;; (dolist (original marked-files) +;; (when (svn-status-line-info->directory-p original) +;; ;; run svn-status-goto-file-name to move point to line of file +;; ;; run svn-status-unset-user-mark to unmark dir+all contents +;; ;; run svn-status-set-user-mark to remark dir +;; ;; maybe check for local mods here, and unmark if user does't say --force? +;; )) + (dolist (original marked-files) + (let ((original-name (svn-status-line-info->filename original)) + (original-filemarks (svn-status-line-info->filemark original)) + (original-propmarks (svn-status-line-info->propmark original)) + (moved nil)) + (cond + ((or (eq original-filemarks ?M) ;local mods: maybe do `svn mv --force' + (eq original-propmarks ?M)) ;local prop mods: maybe do `svn mv --force' + (if (yes-or-no-p + (format "%s has local modifications; use `--force' to really move it? " original-name)) + (progn + (svn-status-run-mv-cp command original-name dest t) + (setq moved t)) + (message "Not acting on %s" original-name))) + ((eq original-filemarks ??) ;original is unversioned: use fallback + (if (yes-or-no-p (format "%s is unversioned. Use `%s -i -- %s %s'? " + original-name fallback original-name dest)) + ;; TODO: consider svn-call-process-function here also... + (progn (call-process fallback nil (get-buffer-create svn-process-buffer-name) nil + "-i" "--" original-name dest) + (setq moved t)) + ;;new files created by fallback are not in *svn-status* now, + ;;TODO: so call (svn-status-update) here? + (message "Not acting on %s" original-name))) + + ((eq original-filemarks ?A) ;;`A' (`svn add'ed, but not committed) + (message "Not acting on %s (commit it first)" original-name)) + + ((eq original-filemarks ? ) ;original is unmodified: can proceed + (svn-status-run-mv-cp command original-name dest) + (setq moved t)) + + ;;file has some other mark (eg conflicted) + (t + (if (yes-or-no-p + (format "The status of %s looks scary. Risk moving it anyway? " + original-name)) + (progn + (svn-status-run-mv-cp command original-name dest) + (setq moved t)) + (message "Not acting on %s" original-name)))) + (when moved + (message "psvn: did '%s' from %s to %s" command original-name dest) + ;; Silently rename the visited file of any buffer visiting this file. + (when (get-file-buffer original-name) + (with-current-buffer (get-file-buffer original-name) + (set-visited-file-name dest nil t)))))) + (svn-status-update))) + +(defun svn-status-run-mv-cp (command original destination &optional force) + "Actually run svn mv or svn cp. +This is just to prevent duplication in `svn-status-prompt-and-act-on-files'" + (if force + (svn-run nil t (intern command) command "--force" "--" original destination) + (svn-run nil t (intern command) command "--" original destination)) +;;;TODO: use something like the following instead of calling svn-status-update +;;; at the end of svn-status-mv-cp. +;; (let ((output (svn-status-parse-ar-output)) +;; newfile +;; buffer-read-only) ; otherwise insert-line-in-status-buffer fails +;; (dolist (new-file output) +;; (when (eq (cadr new-file) 'added-wc) +;; ;; files with 'wc-added action do not exist in *svn-status* +;; ;; buffer yet, so give each of them their own line-info +;; ;; TODO: need to insert the new line-info in a sensible place, ie in the correct directory! [svn-status-filename-to-buffer-position-cache might help?] + +;; (svn-insert-line-in-status-buffer +;; (svn-status-make-line-info (car new-file))))) +;; (svn-status-update-with-command-list output)) + ) + +(defun svn-status-revert () + "Run `svn revert' on all selected files. +See `svn-status-marked-files' for what counts as selected." + (interactive) + (let* ((marked-files (svn-status-marked-files)) + (num-of-files (length marked-files))) + (when (yes-or-no-p + (if (= 1 num-of-files) + (format "Revert %s? " (svn-status-line-info->filename (car marked-files))) + (format "Revert %d files? " num-of-files))) + (message "reverting: %S" (svn-status-marked-file-names)) + (svn-status-create-arg-file (svn-status-marked-files)) + (svn-run t t 'revert "revert" "--targets" svn-status-temp-arg-file)))) + +(defun svn-file-revert () + "Run `svn revert' on the current file." + (interactive) + (when (y-or-n-p (format "Revert %s? " buffer-file-name)) + (svn-run t t 'revert "revert" buffer-file-name))) + +(defun svn-status-rm (force) + "Run `svn rm' on all selected files. +See `svn-status-marked-files' for what counts as selected. +When called with a prefix argument add the command line switch --force. + +Forcing the deletion can also be used to delete files not under svn control." + (interactive "P") + (let* ((marked-files (svn-status-marked-files)) + (num-of-files (length marked-files))) + (when (yes-or-no-p + (if (= 1 num-of-files) + (format "%sRemove %s? " (if force "Force " "") (svn-status-line-info->filename (car marked-files))) + (format "%sRemove %d files? " (if force "Force " "") num-of-files))) + (message "removing: %S" (svn-status-marked-file-names)) + (svn-status-create-arg-file (svn-status-marked-files)) + (if force + (save-excursion + (svn-run t t 'rm "rm" "--force" "--targets" svn-status-temp-arg-file) + (dolist (to-delete (svn-status-marked-files)) + (when (eq (svn-status-line-info->filemark to-delete) ??) + (svn-status-goto-file-name (svn-status-line-info->filename to-delete)) + (let ((buffer-read-only nil)) + (delete-region (svn-point-at-bol) (+ 1 (svn-point-at-eol))) + (delete to-delete svn-status-info))))) + (svn-run t t 'rm "rm" "--targets" svn-status-temp-arg-file))))) + +(defun svn-status-update-cmd (arg) + "Run svn update. +When called with a prefix argument, ask the user for the revision to update to. +When called with a negative prefix argument, only update the selected files." + (interactive "P") + (let* ((selective-update (or (and (numberp arg) (< arg 0)) (eq arg '-))) + (update-extra-arg) + (rev (when arg (svn-status-read-revision-string + (if selective-update + (format "Selected entries: Run svn update -r ") + (format "Directory: %s: Run svn update -r " default-directory)) + (if selective-update "HEAD" nil))))) + (svn-compute-svn-client-version) + (if (and (<= (car svn-client-version) 1) (< (cadr svn-client-version) 5)) + (setq update-extra-arg (list "--non-interactive")) ;; svn version < 1.5 + (setq update-extra-arg (list "--accept" "postpone"))) ;; svn version >= 1.5 + (if selective-update + (progn + (message "Running svn-update for %s" (svn-status-marked-file-names)) + (svn-run t t 'update "update" + (when rev (list "-r" rev)) + update-extra-arg + (svn-status-marked-file-names))) + (message "Running svn-update for %s" default-directory) + (svn-run t t 'update "update" + (when rev (list "-r" rev)) + update-extra-arg + (svn-local-filename-for-remote-access (expand-file-name default-directory)))))) + +(defun svn-status-commit () + "Commit selected files. +If some files have been marked, commit those non-recursively; +this is because marking a directory with \\[svn-status-set-user-mark] +normally marks all of its files as well. +If no files have been marked, commit recursively the file at point." + (interactive) + (svn-status-save-some-buffers) + (let* ((selected-files (svn-status-marked-files))) + (setq svn-status-files-to-commit selected-files + svn-status-recursive-commit (not (svn-status-only-dirs-or-nothing-marked-p))) + (svn-log-edit-show-files-to-commit) + (svn-status-pop-to-commit-buffer) + (when svn-log-edit-insert-files-to-commit + (svn-log-edit-insert-files-to-commit)) + (when svn-log-edit-show-diff-for-commit + (svn-log-edit-svn-diff nil)))) + +(defun svn-status-pop-to-commit-buffer () + "Pop to the svn commit buffer. +If a saved log message exists in `svn-log-edit-file-name' insert it in the buffer." + (interactive) + (setq svn-status-pre-commit-window-configuration (current-window-configuration)) + (let* ((use-existing-buffer (get-buffer svn-log-edit-buffer-name)) + (commit-buffer (get-buffer-create svn-log-edit-buffer-name)) + (dir default-directory) + (log-edit-file-name)) + (pop-to-buffer commit-buffer) + (setq default-directory dir) + (setq log-edit-file-name (svn-log-edit-file-name)) + (unless use-existing-buffer + (when (and log-edit-file-name (file-readable-p log-edit-file-name)) + (insert-file-contents log-edit-file-name))) + (svn-log-edit-mode))) + +(defun svn-status-switch-to-status-buffer () + "Switch to the `svn-status-buffer-name' buffer." + (interactive) + (switch-to-buffer svn-status-buffer-name)) + +(defun svn-status-pop-to-status-buffer () + "Pop to the `svn-status-buffer-name' buffer." + (interactive) + (pop-to-buffer svn-status-buffer-name)) + +(defun svn-status-via-bookmark (bookmark) + "Allows a quick selection of a bookmark in `svn-bookmark-list'. +Run `svn-status' on the selected bookmark." + (interactive + (list + (let ((completion-ignore-case t)) + (funcall svn-status-completing-read-function "SVN status bookmark: " svn-bookmark-list)))) + (unless bookmark + (error "No bookmark specified")) + (let ((directory (cdr (assoc bookmark svn-bookmark-list)))) + (if (file-directory-p directory) + (svn-status directory) + (error "%s is not a directory" directory)))) + +(defun svn-status-export () + "Run `svn export' for the current working copy. +Ask the user for the destination path. +`svn-status-default-export-directory' is suggested as export directory." + (interactive) + (let* ((src default-directory) + (dir1-name (nth 1 (nreverse (split-string src "/")))) + (dest (read-file-name (format "Export %s to " src) (concat svn-status-default-export-directory dir1-name)))) + (svn-run t t 'export "export" (expand-file-name src) (expand-file-name dest)) + (message "svn-status-export %s %s" src dest))) + +(defun svn-status-cleanup (arg) + "Run `svn cleanup' on all selected files. +See `svn-status-marked-files' for what counts as selected. +When this function is called with a prefix argument, use the actual file instead." + (interactive "P") + (let ((file-names (svn-status-get-file-list-names (not arg)))) + (if file-names + (progn + (message "svn-status-cleanup %S" file-names) + (svn-run t t 'cleanup (append (list "cleanup") file-names))) + (message "No valid file selected - No status cleanup possible")))) + +(defun svn-status-resolved () + "Run `svn resolved' on all selected files. +See `svn-status-marked-files' for what counts as selected." + (interactive) + (let* ((marked-files (svn-status-marked-files)) + (num-of-files (length marked-files))) + (when (yes-or-no-p + (if (= 1 num-of-files) + (format "Resolve %s? " (svn-status-line-info->filename (car marked-files))) + (format "Resolve %d files? " num-of-files))) + (message "resolving: %S" (svn-status-marked-file-names)) + (svn-status-create-arg-file (svn-status-marked-files)) + (svn-run t t 'resolved "resolved" "--targets" svn-status-temp-arg-file)))) + + +(defun svn-status-svnversion () + "Run svnversion on the directory that contains the file at point." + (interactive) + (svn-status-ensure-cursor-on-file) + (let ((simple-path (svn-status-line-info->filename (svn-status-get-line-information))) + (full-path (svn-status-line-info->full-path (svn-status-get-line-information))) + (version)) + (unless (file-directory-p simple-path) + (setq simple-path (or (file-name-directory simple-path) ".")) + (setq full-path (file-name-directory full-path))) + (setq version (shell-command-to-string (concat "svnversion -n " full-path))) + (message "svnversion for '%s': %s" simple-path version) + version)) + +;; -------------------------------------------------------------------------------- +;; Update the `svn-status-buffer-name' buffer, when a file is saved +;; -------------------------------------------------------------------------------- + +(defvar svn-status-file-modified-after-save-flag ?m + "Flag shown whenever a file is modified and saved in Emacs. +The flag is shown in the `svn-status-buffer-name' buffer. +Recommended values are ?m or ?M.") +(defun svn-status-after-save-hook () + "Set a modified indication, when a file is saved from a svn working copy." + (let* ((svn-dir (car-safe svn-status-directory-history)) + (svn-dir (when svn-dir (expand-file-name svn-dir))) + (file-dir (file-name-directory (buffer-file-name))) + (svn-dir-len (length (or svn-dir ""))) + (file-dir-len (length file-dir)) + (file-name)) + (when (and (get-buffer svn-status-buffer-name) + svn-dir + (>= file-dir-len svn-dir-len) + (string= (substring file-dir 0 svn-dir-len) svn-dir)) + (setq file-name (substring (buffer-file-name) svn-dir-len)) + ;;(message "In svn-status directory %S" file-name) + (let ((st-info svn-status-info) + (i-fname)) + (while st-info + (setq i-fname (svn-status-line-info->filename (car st-info))) + ;;(message "i-fname=%S" i-fname) + (when (and (string= file-name i-fname) + (not (eq (svn-status-line-info->filemark (car st-info)) ??))) + (svn-status-line-info->set-filemark (car st-info) + svn-status-file-modified-after-save-flag) + (save-window-excursion + (set-buffer svn-status-buffer-name) + (save-excursion + (let ((buffer-read-only nil) + (pos (svn-status-get-file-name-buffer-position i-fname))) + (if pos + (progn + (goto-char pos) + (delete-region (svn-point-at-bol) (svn-point-at-eol)) + (svn-insert-line-in-status-buffer (car st-info)) + (delete-char 1)) + (svn-status-message 3 "psvn: file %s not found, updating %s buffer content..." + i-fname svn-status-buffer-name) + (svn-status-update-buffer)))))) + (setq st-info (cdr st-info)))))) + nil) + +(add-hook 'after-save-hook 'svn-status-after-save-hook) + +;; -------------------------------------------------------------------------------- +;; vc-svn integration +;; -------------------------------------------------------------------------------- +(defvar svn-status-state-mark-modeline t) ; modeline mark display or not +(defvar svn-status-state-mark-tooltip nil) ; modeline tooltip display + +(defun svn-status-state-mark-modeline-dot (color) + (propertize " " + 'help-echo 'svn-status-state-mark-tooltip + 'display + `(image :type xpm + :data ,(format "/* XPM */ +static char * data[] = { +\"18 13 3 1\", +\" c None\", +\"+ c #000000\", +\". c %s\", +\" \", +\" +++++ \", +\" +.....+ \", +\" +.......+ \", +\" +.........+ \", +\" +.........+ \", +\" +.........+ \", +\" +.........+ \", +\" +.........+ \", +\" +.......+ \", +\" +.....+ \", +\" +++++ \", +\" \"};" + color) + :ascent center))) + +(defun svn-status-install-state-mark-modeline (color) + (push `(svn-status-state-mark-modeline + ,(svn-status-state-mark-modeline-dot color)) + mode-line-format) + (force-mode-line-update t)) + +(defun svn-status-uninstall-state-mark-modeline () + (setq mode-line-format + (remove-if #'(lambda (mode) (eq (car-safe mode) + 'svn-status-state-mark-modeline)) + mode-line-format)) + (force-mode-line-update t)) + +(defun svn-status-update-state-mark-tooltip (tooltip) + (setq svn-status-state-mark-tooltip tooltip)) + +(defun svn-status-update-state-mark (color) + (svn-status-uninstall-state-mark-modeline) + (svn-status-install-state-mark-modeline color)) + +(defsubst svn-status-in-vc-mode? () + "Is vc-svn active?" + (cond + ((fboundp 'vc-backend) + (eq 'SVN (vc-backend buffer-file-name))) + ((and (boundp 'vc-mode) vc-mode) + (string-match "^ SVN" (svn-substring-no-properties vc-mode))))) + +(when svn-status-fancy-file-state-in-modeline + (defadvice vc-find-file-hook (after svn-status-vc-svn-find-file-hook activate) + "vc-find-file-hook advice for synchronizing psvn with vc-svn interface" + (when (svn-status-in-vc-mode?) (svn-status-update-modeline))) + + (defadvice vc-after-save (after svn-status-vc-svn-after-save activate) + "vc-after-save advice for synchronizing psvn when saving buffer" + (when (svn-status-in-vc-mode?) (svn-status-update-modeline))) + + (defadvice ediff-refresh-mode-lines + (around svn-modeline-ediff-fixup activate compile) + "Fixup svn file status in the modeline when using ediff" + (ediff-with-current-buffer ediff-buffer-A + (svn-status-uninstall-state-mark-modeline)) + (ediff-with-current-buffer ediff-buffer-B + (svn-status-uninstall-state-mark-modeline)) + ad-do-it + (ediff-with-current-buffer ediff-buffer-A + (svn-status-update-modeline)) + (ediff-with-current-buffer ediff-buffer-B + (svn-status-update-modeline)))) + +(defun svn-status-update-modeline () + "Update modeline state dot mark properly" + (when (and buffer-file-name (svn-status-in-vc-mode?)) + (svn-status-update-state-mark + (svn-status-interprete-state-mode-color + (vc-svn-state buffer-file-name))))) + +(defsubst svn-status-interprete-state-mode-color (stat) + "Interpret vc-svn-state symbol to mode line color" + (case stat + ('edited "tomato" ) + ('up-to-date "GreenYellow" ) + ;; what is missing here?? + ;; ('unknown "gray" ) + ;; ('added "blue" ) + ;; ('deleted "red" ) + ;; ('unmerged "purple" ) + (t "red"))) + +;; -------------------------------------------------------------------------------- +;; Getting older revisions +;; -------------------------------------------------------------------------------- + +(defun svn-status-get-specific-revision (arg) + "Retrieve older revisions. +The older revisions are stored in backup files named F.~REVISION~. + +When the function is called without a prefix argument: get all marked files. +With a prefix argument: get only the actual file." + (interactive "P") + (svn-status-get-specific-revision-internal + (svn-status-get-file-list (not arg)) :ask t)) + +(defun svn-status-get-specific-revision-internal (line-infos revision handle-relative-svn-status-dir) + "Retrieve older revisions of files. +LINE-INFOS is a list of line-info structures (see +`svn-status-get-line-information'). +REVISION is one of: +- a string: whatever the -r option allows. +- `:ask': asks the user to specify the revision, which then becomes + saved in `minibuffer-history' rather than in `command-history'. +- `:auto': Use \"HEAD\" if an update is known to exist, \"BASE\" otherwise. + +After the call, `svn-status-get-revision-file-info' will be an alist +\((WORKING-FILE-NAME . RETRIEVED-REVISION-FILE-NAME) ...). These file +names are relative to the directory where `svn-status' was run." + ;; In `svn-status-show-svn-diff-internal', there is a comment + ;; that REVISION `nil' might mean omitting the -r option entirely. + ;; That doesn't seem like a good idea with svn cat. + + ;; (message "svn-status-get-specific-revision-internal: %S %S" line-infos revision) + + (when (eq revision :ask) + (setq revision (svn-status-read-revision-string + "Get files for version: " "PREV"))) + + (let ((count (length line-infos))) + (if (= count 1) + (let ((line-info (car line-infos))) + (message "Getting revision %s of %s" + (if (eq revision :auto) + (if (svn-status-line-info->update-available line-info) + "HEAD" "BASE") + revision) + (svn-status-line-info->filename line-info))) + ;; We could compute "Getting HEAD of 8 files and BASE of 11 files" + ;; but that'd be more bloat than it's worth. + (message "Getting revision %s of %d files" + (if (eq revision :auto) "HEAD or BASE" revision) + count))) + + (let ((svn-status-get-specific-revision-file-info '())) + (dolist (line-info line-infos) + (let* ((revision (if (eq revision :auto) + (if (svn-status-line-info->update-available line-info) + "HEAD" "BASE") + revision)) ;must be a string by this point + (file-name (svn-status-line-info->filename line-info)) + ;; If REVISION is e.g. "HEAD", should we find out the actual + ;; revision number and save "foo.~123~" rather than "foo.~HEAD~"? + ;; OTOH, `auto-mode-alist' already ignores ".~HEAD~" suffixes, + ;; and if users often want to know the revision numbers of such + ;; files, they can use svn:keywords. + (file-name-with-revision (concat (file-name-nondirectory file-name) ".~" revision "~")) + (default-directory (concat (svn-status-base-dir) + (if handle-relative-svn-status-dir + (file-relative-name default-directory (svn-status-base-dir)) + "") + (file-name-directory file-name)))) + ;; `add-to-list' would unnecessarily check for duplicates. + (push (cons file-name (concat (file-name-directory file-name) file-name-with-revision)) + svn-status-get-specific-revision-file-info) + (svn-status-message 3 "svn-status-get-specific-revision-internal: file: %s, default-directory: %s" + file-name default-directory) + (svn-status-message 3 "svn-status-get-specific-revision-internal: file-name-with-revision: %s %S" + file-name-with-revision (file-exists-p file-name-with-revision)) + (save-excursion + (if (or (not (file-exists-p file-name-with-revision)) ;; file does not exist + (not (string= (number-to-string (string-to-number revision)) revision))) ;; revision is not a number + (progn + (message "Getting revision %s of %s, target: %s" revision file-name + (expand-file-name(concat default-directory file-name-with-revision))) + (svn-compute-svn-client-version) + (let ((content + (with-temp-buffer + (if (and (and (<= (car svn-client-version) 1) (< (cadr svn-client-version) 7)) + (string= revision "BASE")) + ;; Shortcut: Take the file from the file system when using svn client < v1.7 + (insert-file-contents (concat (svn-wc-adm-dir-name) + "/text-base/" + (file-name-nondirectory file-name) + ".svn-base")) + (progn + (svn-run nil t 'cat "cat" "-r" revision + (concat default-directory (file-name-nondirectory file-name))) + ;;todo: error processing + ;;svn: Filesystem has no item + ;;svn: file not found: revision `15', path `/trunk/file.txt' + (insert-buffer-substring svn-process-buffer-name))) + (buffer-string)))) + (find-file file-name-with-revision) + (setq buffer-read-only nil) + (erase-buffer) ;Widen, because we'll save the whole buffer. + (insert content) + (goto-char (point-min)) + (let ((write-file-functions nil) + (require-final-newline nil)) + (save-buffer)))) + (find-file file-name-with-revision))))) + ;;(message "default-directory: %s revision-file-info: %S" default-directory svn-status-get-specific-revision-file-info) + (nreverse svn-status-get-specific-revision-file-info))) + +(defun svn-status-ediff-with-revision (arg) + "Run ediff on the current file with a different revision. +If there is a newer revision in the repository, the diff is done against HEAD, +otherwise compare the working copy with BASE. +If ARG then prompt for revision to diff against." + (interactive "P") + (let* ((svn-status-get-specific-revision-file-info + (svn-status-get-specific-revision-internal + (list (svn-status-make-line-info + (file-relative-name + (svn-status-line-info->full-path (svn-status-get-line-information)) + (svn-status-base-dir)) + nil nil nil nil nil nil + (svn-status-line-info->update-available (svn-status-get-line-information)))) + (if arg :ask :auto) + nil)) + (ediff-after-quit-destination-buffer (current-buffer)) + (default-directory (svn-status-base-dir)) + (my-buffer (find-file-noselect (caar svn-status-get-specific-revision-file-info))) + (base-buff (find-file-noselect (cdar svn-status-get-specific-revision-file-info))) + (svn-transient-buffers (list my-buffer base-buff)) + (startup-hook '(svn-ediff-startup-hook))) + (ediff-buffers base-buff my-buffer startup-hook))) + +(defun svn-ediff-startup-hook () + ;; (message "svn-ediff-startup-hook: ediff-after-quit-hook-internal: %S" ediff-after-quit-hook-internal) + (add-hook 'ediff-after-quit-hook-internal + `(lambda () + (svn-ediff-exit-hook + ',ediff-after-quit-destination-buffer ',svn-transient-buffers)) + nil 'local)) + +(defun svn-ediff-exit-hook (svn-buf tmp-bufs) + ;; (message "svn-ediff-exit-hook: svn-buf: %s, tmp-bufs: %s" svn-buf tmp-bufs) + ;; kill the temp buffers (and their associated windows) + (dolist (tb tmp-bufs) + (when (and tb (buffer-live-p tb) (not (buffer-modified-p tb))) + (let* ((win (get-buffer-window tb t)) + (file-name (buffer-file-name tb)) + (is-temp-file (numberp (string-match "~\\([0-9]+\\|BASE\\)~" file-name)))) + ;; (message "svn-ediff-exit-hook - is-temp-file: %s, temp-buf:: %s - %s " is-temp-file (current-buffer) file-name) + (when (and win (> (count-windows) 1) + (delete-window win))) + (kill-buffer tb) + (when (and is-temp-file svn-status-ediff-delete-temporary-files) + (when (or (eq svn-status-ediff-delete-temporary-files t) + (y-or-n-p (format "Delete File '%s' ? " file-name))) + (delete-file file-name)))))) + ;; switch back to the *svn* buffer + (when (and svn-buf (buffer-live-p svn-buf) + (not (get-buffer-window svn-buf t))) + (ignore-errors (switch-to-buffer svn-buf)))) + + +(defun svn-status-read-revision-string (prompt &optional default-value) + "Prompt the user for a svn revision number." + (interactive) + (read-string prompt default-value)) + +(defun svn-file-show-svn-ediff (arg) + "Run ediff on the current file with a previous revision. +If ARG then prompt for revision to diff against." + (interactive "P") + (let ((svn-status-get-line-information-for-file 'relative) + (default-directory (svn-status-base-dir))) + (svn-status-ediff-with-revision arg))) + +;; -------------------------------------------------------------------------------- +;; SVN process handling +;; -------------------------------------------------------------------------------- + +(defun svn-process-kill () + "Kill the current running svn process." + (interactive) + (let ((process (get-process "svn"))) + (if process + (delete-process process) + (message "No running svn process")))) + +(defun svn-process-send-string (string &optional send-passwd) + "Send a string to the running svn process. +This is useful, if the running svn process asks the user a question. +Note: use C-q C-j to send a line termination character." + (interactive "sSend string to svn process: ") + (save-excursion + (set-buffer svn-process-buffer-name) + (goto-char (point-max)) + (let ((buffer-read-only nil)) + (insert (if send-passwd (make-string (length string) ?.) string))) + (set-marker (process-mark (get-process "svn")) (point))) + (process-send-string "svn" string)) + +(defun svn-process-send-string-and-newline (string &optional send-passwd) + "Send a string to the running svn process. +Just call `svn-process-send-string' with STRING and an end of line termination. +When called with a prefix argument, read the data from user as password." + (interactive (let* ((use-passwd current-prefix-arg) + (s (if use-passwd + (read-passwd "Send secret line to svn process: ") + (read-string "Send line to svn process: ")))) + (list s use-passwd))) + (svn-process-send-string (concat string "\n") send-passwd)) + +;; -------------------------------------------------------------------------------- +;; Search interface +;; -------------------------------------------------------------------------------- + +(defun svn-status-grep-files (regexp) + "Run grep on selected file(s). +See `svn-status-marked-files' for what counts as selected." + (interactive "sGrep files for: ") + (unless grep-command + (grep-compute-defaults)) + (grep (format "%s %s %s" grep-command (shell-quote-argument regexp) + (mapconcat 'identity (svn-status-marked-file-names) " ")))) + +(defun svn-status-search-files (search-string) + "Search selected file(s) for a fixed SEARCH-STRING. +See `svn-status-marked-files' for what counts as selected." + (interactive "sSearch files for: ") + (svn-status-grep-files (regexp-quote search-string))) + +;; -------------------------------------------------------------------------------- +;; Property List stuff +;; -------------------------------------------------------------------------------- + +(defun svn-status-property-list () + (interactive) + (let ((file-names (svn-status-marked-file-names))) + (if file-names + (progn + (svn-run t t 'proplist (append (list "proplist" "-v") file-names))) + (message "No valid file selected - No property listing possible")))) + +(defun svn-status-proplist-start () + (svn-status-ensure-cursor-on-file) + (svn-run t t 'proplist-parse "proplist" (svn-status-line-info->filename + (svn-status-get-line-information)))) +(defun svn-status-property-edit-one-entry (arg) + "Edit a property. +When called with a prefix argument, it is possible to enter a new property." + (interactive "P") + (setq svn-status-property-edit-must-match-flag (not arg)) + (svn-status-proplist-start)) + +(defun svn-status-property-set () + (interactive) + (setq svn-status-property-edit-must-match-flag nil) + (svn-status-proplist-start)) + +(defun svn-status-property-delete () + (interactive) + (setq svn-status-property-edit-must-match-flag t) + (svn-status-proplist-start)) + +(defun svn-status-property-parse-property-names () + ;(svn-status-show-process-buffer-internal t) + (message "svn-status-property-parse-property-names") + (let ((pl) + (prop-name) + (prop-value)) + (save-excursion + (set-buffer svn-process-buffer-name) + (goto-char (point-min)) + (forward-line 1) + (while (looking-at " \\(.+\\)") + (setq pl (append pl (list (match-string 1)))) + (forward-line 1))) + ;(cond last-command: svn-status-property-set, svn-status-property-edit-one-entry + (cond ((eq last-command 'svn-status-property-edit-one-entry) + ;;(message "svn-status-property-edit-one-entry") + (setq prop-name + (completing-read "Set Property - Name: " (mapcar 'list pl) + nil svn-status-property-edit-must-match-flag)) + (unless (string= prop-name "") + (save-excursion + (set-buffer svn-status-buffer-name) + (svn-status-property-edit (list (svn-status-get-line-information)) + prop-name)))) + ((eq last-command 'svn-status-property-set) + (message "svn-status-property-set") + (setq prop-name + (completing-read "Set Property - Name: " (mapcar 'list pl) nil nil)) + (setq prop-value (read-from-minibuffer "Property value: ")) + (unless (string= prop-name "") + (save-excursion + (set-buffer svn-status-buffer-name) + (message "Setting property %s := %s for %S" prop-name prop-value + (svn-status-marked-file-names)) + (let ((file-names (svn-status-marked-file-names))) + (when file-names + (svn-run nil t 'propset + (append (list "propset" prop-name prop-value) file-names)) + ) + ) + (message "propset finished.") + ))) + ((eq last-command 'svn-status-property-delete) + (setq prop-name + (completing-read "Delete Property - Name: " (mapcar 'list pl) nil t)) + (unless (string= prop-name "") + (save-excursion + (set-buffer svn-status-buffer-name) + (let ((file-names (svn-status-marked-file-names))) + (when file-names + (message "Going to delete prop %s for %s" prop-name file-names) + (svn-run t t 'propdel + (append (list "propdel" prop-name) file-names)))))))))) + +(defun svn-status-property-edit (file-info-list prop-name &optional new-prop-value remove-values) + (let* ((commit-buffer (get-buffer-create "*svn-property-edit*")) + (dir default-directory) + ;; now only one file is implemented ... + (file-name (svn-status-line-info->filename (car file-info-list))) + (prop-value)) + (message "Edit property %s for file %s" prop-name file-name) + (svn-run nil t 'propget-parse "propget" prop-name file-name) + (save-excursion + (set-buffer svn-process-buffer-name) + (setq prop-value (if (> (point-max) 1) + (buffer-substring (point-min) (- (point-max) 1)) + ""))) + (setq svn-status-propedit-property-name prop-name) + (setq svn-status-propedit-file-list file-info-list) + (setq svn-status-pre-propedit-window-configuration (current-window-configuration)) + (pop-to-buffer commit-buffer) + ;; If the buffer has been narrowed, `svn-prop-edit-done' will use + ;; only the accessible part. So we need not erase the rest here. + (delete-region (point-min) (point-max)) + (setq default-directory dir) + (insert prop-value) + (svn-status-remove-control-M) + (when new-prop-value + (when (listp new-prop-value) + (if remove-values + (message "Remove prop values %S " new-prop-value) + (message "Adding new prop values %S " new-prop-value)) + (while new-prop-value + (goto-char (point-min)) + (if (re-search-forward (concat "^" (regexp-quote (car new-prop-value)) "$") nil t) + (when remove-values + (kill-whole-line 1)) + (unless remove-values + (goto-char (point-max)) + (when (> (current-column) 0) (insert "\n")) + (insert (car new-prop-value)))) + (setq new-prop-value (cdr new-prop-value))))) + (svn-prop-edit-mode))) + +(defun svn-status-property-set-property (file-info-list prop-name prop-value) + "Set a property on a given file list." + (save-excursion + (set-buffer (get-buffer-create "*svn-property-edit*")) + ;; If the buffer has been narrowed, `svn-prop-edit-do-it' will use + ;; only the accessible part. So we need not erase the rest here. + (delete-region (point-min) (point-max)) + (insert prop-value)) + (setq svn-status-propedit-file-list (svn-status-marked-files)) + (setq svn-status-propedit-property-name prop-name) + (svn-prop-edit-do-it nil) + (svn-status-update)) + + +(defun svn-status-get-directory (line-info) + (let* ((file-name (svn-status-line-info->filename line-info)) + (file-dir (file-name-directory file-name))) + ;;(message "file-dir: %S" file-dir) + (if file-dir + (substring file-dir 0 (- (length file-dir) 1)) + "."))) + +(defun svn-status-get-file-list-per-directory (files) + ;;(message "%S" files) + (let ((dir-list nil) + (i files) + (j) + (dir)) + (while i + (setq dir (svn-status-get-directory (car i))) + (setq j (assoc dir dir-list)) + (if j + (progn + ;;(message "dir already present %S %s" j dir) + (setcdr j (append (cdr j) (list (car i))))) + (setq dir-list (append dir-list (list (list dir (car i)))))) + (setq i (cdr i))) + ;;(message "svn-status-get-file-list-per-directory: %S" dir-list) + dir-list)) + +(defun svn-status-property-ignore-file () + (interactive) + (let ((d-list (svn-status-get-file-list-per-directory (svn-status-marked-files))) + (dir) + (f-info) + (ext-list)) + (while d-list + (setq dir (caar d-list)) + (setq f-info (cdar d-list)) + (setq ext-list (mapcar '(lambda (i) + (svn-status-line-info->filename-nondirectory i)) f-info)) + ;;(message "ignore in dir %s: %S" dir f-info) + (save-window-excursion + (when (y-or-n-p (format "Ignore %S for %s? " ext-list dir)) + (svn-status-property-edit + (list (svn-status-find-info-for-file-name dir)) "svn:ignore" ext-list) + (svn-prop-edit-do-it nil))) ; synchronous + (setq d-list (cdr d-list))) + (svn-status-update))) + +(defun svn-status-property-ignore-file-extension () + (interactive) + (let ((d-list (svn-status-get-file-list-per-directory (svn-status-marked-files))) + (dir) + (f-info) + (ext-list)) + (while d-list + (setq dir (caar d-list)) + (setq f-info (cdar d-list)) + ;;(message "ignore in dir %s: %S" dir f-info) + (setq ext-list nil) + (while f-info + (add-to-list 'ext-list (concat "*." + (file-name-extension + (svn-status-line-info->filename (car f-info))))) + (setq f-info (cdr f-info))) + ;;(message "%S" ext-list) + (save-window-excursion + (when (y-or-n-p (format "Ignore %S for %s? " ext-list dir)) + (svn-status-property-edit + (list (svn-status-find-info-for-file-name dir)) "svn:ignore" + ext-list) + (svn-prop-edit-do-it nil))) + (setq d-list (cdr d-list))) + (svn-status-update))) + +(defun svn-status-property-edit-svn-ignore () + (interactive) + (let* ((line-info (svn-status-get-line-information)) + (dir (if (svn-status-line-info->directory-p line-info) + (svn-status-line-info->filename line-info) + (svn-status-get-directory line-info)))) + (svn-status-property-edit + (list (svn-status-find-info-for-file-name dir)) "svn:ignore") + (message "Edit svn:ignore on %s" dir))) + + +(defun svn-status-property-edit-svn-externals () + (interactive) + (let* ((line-info (svn-status-get-line-information)) + (dir (if (svn-status-line-info->directory-p line-info) + (svn-status-line-info->filename line-info) + (svn-status-get-directory line-info)))) + (svn-status-property-edit + (list (svn-status-find-info-for-file-name dir)) "svn:externals") + (message "Edit svn:externals on %s" dir))) + + +(defun svn-status-property-set-keyword-list () + "Edit the svn:keywords property on the marked files." + (interactive) + ;;(message "Set svn:keywords for %S" (svn-status-marked-file-names)) + (svn-status-property-edit (svn-status-marked-files) "svn:keywords")) + +(defun svn-status-property-set-keyword-id (arg) + "Set/Remove Id from the svn:keywords property. +Normally Id is added to the svn:keywords property. + +When called with the prefix arg -, remove Id from the svn:keywords property." + (interactive "P") + (svn-status-property-edit (svn-status-marked-files) "svn:keywords" '("Id") (eq arg '-)) + (svn-prop-edit-do-it nil)) + +(defun svn-status-property-set-keyword-date (arg) + "Set/Remove Date from the svn:keywords property. +Normally Date is added to the svn:keywords property. + +When called with the prefix arg -, remove Date from the svn:keywords property." + (interactive "P") + (svn-status-property-edit (svn-status-marked-files) "svn:keywords" '("Date") (eq arg '-)) + (svn-prop-edit-do-it nil)) + + +(defun svn-status-property-set-eol-style () + "Edit the svn:eol-style property on the marked files." + (interactive) + (svn-status-property-set-property + (svn-status-marked-files) "svn:eol-style" + (completing-read "Set svn:eol-style for the marked files: " + (mapcar 'list '("native" "CRLF" "LF" "CR")) + nil t))) + +(defun svn-status-property-set-executable (&optional unset) + "Set the svn:executable property on the marked files. +When called with a prefix argument: unset the svn:executable property." + (interactive "P") + (if unset + (progn + (svn-run nil t 'propdel (append (list "propdel" "svn:executable") (svn-status-marked-file-names))) + (message "Unset the svn:executable property for %s" (svn-status-marked-file-names)) + (svn-status-update)) + (svn-status-property-set-property (svn-status-marked-files) "svn:executable" "*"))) + +(defun svn-status-property-set-mime-type () + "Set the svn:mime-type property on the marked files." + (interactive) + (require 'mailcap nil t) + (let ((completion-ignore-case t) + (mime-types (when (fboundp 'mailcap-mime-types) + (mailcap-mime-types)))) + (svn-status-property-set-property + (svn-status-marked-files) "svn:mime-type" + (funcall svn-status-completing-read-function "Set svn:mime-type for the marked files: " + (mapcar (lambda (x) (cons x x)) ; for Emacs 21 + (sort mime-types 'string<)))))) + +;; -------------------------------------------------------------------------------- +;; svn-prop-edit-mode: +;; -------------------------------------------------------------------------------- + +(defvar svn-prop-edit-mode-map () "Keymap used in `svn-prop-edit-mode' buffers.") +(put 'svn-prop-edit-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-prop-edit-mode-map) + (setq svn-prop-edit-mode-map (make-sparse-keymap)) + (define-key svn-prop-edit-mode-map [(control ?c) (control ?c)] 'svn-prop-edit-done) + (define-key svn-prop-edit-mode-map [(control ?c) (control ?d)] 'svn-prop-edit-svn-diff) + (define-key svn-prop-edit-mode-map [(control ?c) (control ?s)] 'svn-prop-edit-svn-status) + (define-key svn-prop-edit-mode-map [(control ?c) (control ?l)] 'svn-prop-edit-svn-log) + (define-key svn-prop-edit-mode-map [(control ?c) (control ?q)] 'svn-prop-edit-abort)) + +(easy-menu-define svn-prop-edit-mode-menu svn-prop-edit-mode-map +"'svn-prop-edit-mode' menu" + '("SVN-PropEdit" + ["Commit" svn-prop-edit-done t] + ["Show Diff" svn-prop-edit-svn-diff t] + ["Show Status" svn-prop-edit-svn-status t] + ["Show Log" svn-prop-edit-svn-log t] + ["Abort" svn-prop-edit-abort t])) + +(defun svn-prop-edit-mode () + "Major Mode to edit file properties of files under svn control. +Commands: +\\{svn-prop-edit-mode-map}" + (interactive) + (kill-all-local-variables) + (use-local-map svn-prop-edit-mode-map) + (easy-menu-add svn-prop-edit-mode-menu) + (setq major-mode 'svn-prop-edit-mode) + (setq mode-name "svn-prop-edit")) + +(defun svn-prop-edit-abort () + (interactive) + (bury-buffer) + (set-window-configuration svn-status-pre-propedit-window-configuration)) + +(defun svn-prop-edit-done () + (interactive) + (svn-prop-edit-do-it t)) + +(defun svn-prop-edit-do-it (async) + "Run svn propset `svn-status-propedit-property-name' with the content of the +*svn-property-edit* buffer." + (message "svn propset %s on %s" + svn-status-propedit-property-name + (mapcar 'svn-status-line-info->filename svn-status-propedit-file-list)) + (save-excursion + (set-buffer (get-buffer "*svn-property-edit*")) + (when (fboundp 'set-buffer-file-coding-system) + (set-buffer-file-coding-system svn-status-svn-file-coding-system nil)) + (let ((svn-propedit-file-name (concat svn-status-temp-dir "svn-prop-edit.txt" svn-temp-suffix))) + (setq svn-status-temp-file-to-remove (svn-expand-filename-for-remote-access svn-propedit-file-name)) + (write-region (point-min) (point-max) svn-status-temp-file-to-remove nil 1) + (when svn-status-propedit-file-list ; there are files to change properties + (svn-status-create-arg-file svn-status-propedit-file-list) + (setq svn-status-propedit-file-list nil) + (svn-run async t 'propset "propset" + svn-status-propedit-property-name + "--targets" svn-status-temp-arg-file + (when (eq svn-status-svn-file-coding-system 'utf-8) + '("--encoding" "UTF-8")) + "-F" svn-propedit-file-name) + (unless async (svn-status-remove-temp-file-maybe))) + (when svn-status-pre-propedit-window-configuration + (set-window-configuration svn-status-pre-propedit-window-configuration))))) + +(defun svn-prop-edit-svn-diff (arg) + (interactive "P") + (set-buffer svn-status-buffer-name) + ;; Because propedit is not recursive in our use, neither is this diff. + (svn-status-show-svn-diff-internal svn-status-propedit-file-list nil + (if arg :ask "BASE"))) + +(defun svn-prop-edit-svn-log (arg) + (interactive "P") + (set-buffer svn-status-buffer-name) + (svn-status-show-svn-log arg)) + +(defun svn-prop-edit-svn-status () + (interactive) + (pop-to-buffer svn-status-buffer-name) + (other-window 1)) + +;; -------------------------------------------------------------------------------- +;; svn-log-edit-mode: +;; -------------------------------------------------------------------------------- + +(defvar svn-log-edit-mode-map () "Keymap used in `svn-log-edit-mode' buffers.") +(put 'svn-log-edit-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(defvar svn-log-edit-mode-menu) ;really defined with `easy-menu-define' below. + +(defun svn-log-edit-common-setup () + (set (make-local-variable 'paragraph-start) svn-log-edit-paragraph-start) + (set (make-local-variable 'paragraph-separate) svn-log-edit-paragraph-separate)) + +(if svn-log-edit-use-log-edit-mode + (define-derived-mode svn-log-edit-mode log-edit-mode "svn-log-edit" + "Wrapper around `log-edit-mode' for psvn.el" + (easy-menu-add svn-log-edit-mode-menu) + (setq svn-log-edit-update-log-entry nil) + (set (make-local-variable 'log-edit-callback) 'svn-log-edit-done) + (set (make-local-variable 'log-edit-listfun) 'svn-log-edit-files-to-commit) + (set (make-local-variable 'log-edit-initial-files) (log-edit-files)) + (svn-log-edit-common-setup) + (message "Press %s when you are done editing." + (substitute-command-keys "\\[log-edit-done]")) + ) + (defun svn-log-edit-mode () + "Major Mode to edit svn log messages. +Commands: +\\{svn-log-edit-mode-map}" + (interactive) + (kill-all-local-variables) + (use-local-map svn-log-edit-mode-map) + (easy-menu-add svn-log-edit-mode-menu) + (setq major-mode 'svn-log-edit-mode) + (setq mode-name "svn-log-edit") + (setq svn-log-edit-update-log-entry nil) + (svn-log-edit-common-setup) + (run-hooks 'svn-log-edit-mode-hook))) + +(when (not svn-log-edit-mode-map) + (setq svn-log-edit-mode-map (make-sparse-keymap)) + (unless svn-log-edit-use-log-edit-mode + (define-key svn-log-edit-mode-map (kbd "C-c C-c") 'svn-log-edit-done)) + (define-key svn-log-edit-mode-map (kbd "C-c C-d") 'svn-log-edit-svn-diff) + (define-key svn-log-edit-mode-map (kbd "C-c C-s") 'svn-log-edit-save-message) + (define-key svn-log-edit-mode-map (kbd "C-c C-i") 'svn-log-edit-svn-status) + (define-key svn-log-edit-mode-map (kbd "C-c C-l") 'svn-log-edit-svn-log) + (define-key svn-log-edit-mode-map (kbd "C-c C-?") 'svn-log-edit-show-files-to-commit) + (define-key svn-log-edit-mode-map (kbd "C-c C-z") 'svn-log-edit-erase-edit-buffer) + (define-key svn-log-edit-mode-map (kbd "C-c C-q") 'svn-log-edit-abort)) + +(easy-menu-define svn-log-edit-mode-menu svn-log-edit-mode-map +"'svn-log-edit-mode' menu" + '("SVN-Log" + ["Save to disk" svn-log-edit-save-message t] + ["Commit" svn-log-edit-done t] + ["Show Diff" svn-log-edit-svn-diff t] + ["Show Status" svn-log-edit-svn-status t] + ["Show Log" svn-log-edit-svn-log t] + ["Show files to commit" svn-log-edit-show-files-to-commit t] + ["Erase buffer" svn-log-edit-erase-edit-buffer] + ["Abort" svn-log-edit-abort t])) +(put 'svn-log-edit-mode-menu 'risky-local-variable t) + +(defun svn-log-edit-abort () + (interactive) + (bury-buffer) + (set-window-configuration svn-status-pre-commit-window-configuration)) + +(defun svn-log-edit-done () + "Finish editing the log message and run svn commit." + (interactive) + (svn-status-save-some-buffers) + (let ((svn-logedit-file-name)) + (save-excursion + (set-buffer (get-buffer svn-log-edit-buffer-name)) + (when svn-log-edit-insert-files-to-commit + (svn-log-edit-remove-comment-lines)) + (when (fboundp 'set-buffer-file-coding-system) + (set-buffer-file-coding-system svn-status-svn-file-coding-system nil)) + (when (or svn-log-edit-update-log-entry svn-status-files-to-commit) + (setq svn-log-edit-file-name (concat svn-status-temp-dir "svn-log-edit.txt" svn-temp-suffix)) + (setq svn-status-temp-file-to-remove (svn-expand-filename-for-remote-access svn-log-edit-file-name)) + (write-region (point-min) (point-max) svn-status-temp-file-to-remove nil 1)) + (bury-buffer)) + (if svn-log-edit-update-log-entry + (when (y-or-n-p "Update the log entry? ") + ;; svn propset svn:log --revprop -r11672 -F file + (svn-run nil t 'propset "propset" "svn:log" "--revprop" + (concat "-r" svn-log-edit-update-log-entry) + "-F" svn-log-edit-file-name) + (save-excursion + (set-buffer svn-process-buffer-name) + (message "%s" (buffer-substring (point-min) (- (point-max) 1))))) + (when svn-status-files-to-commit ; there are files to commit + (setq svn-status-operated-on-dot + (and (= 1 (length svn-status-files-to-commit)) + (string= "." (svn-status-line-info->filename (car svn-status-files-to-commit))))) + (svn-status-create-arg-file svn-status-files-to-commit) + (svn-run t t 'commit "commit" + (unless svn-status-recursive-commit "--non-recursive") + "--targets" svn-status-temp-arg-file + "-F" svn-log-edit-file-name + (when (eq svn-status-svn-file-coding-system 'utf-8) + '("--encoding" "UTF-8")) + svn-status-default-commit-arguments)) + (set-window-configuration svn-status-pre-commit-window-configuration) + (message "svn-log editing done")))) + +(defun svn-log-edit-svn-diff (arg) + "Show the diff we are about to commit. +If ARG then show diff between some other version of the selected files." + (interactive "P") + (set-buffer svn-status-buffer-name) ; TODO: is this necessary? + ;; This call is very much like `svn-status-show-svn-diff-for-marked-files' + ;; but uses commit-specific variables instead of the current marks. + (svn-status-show-svn-diff-internal svn-status-files-to-commit + svn-status-recursive-commit + (if arg :ask "BASE"))) + +(defun svn-log-edit-svn-log (arg) + (interactive "P") + (set-buffer svn-status-buffer-name) + (svn-status-show-svn-log arg)) + +(defun svn-log-edit-svn-status () + (interactive) + (pop-to-buffer svn-status-buffer-name) + (other-window 1)) + +(defun svn-log-edit-files-to-commit () + (mapcar 'svn-status-line-info->filename svn-status-files-to-commit)) + +(defun svn-log-edit-show-files-to-commit () + (interactive) + (message "Files to commit%s: %S" + (if svn-status-recursive-commit " recursively" "") + (svn-log-edit-files-to-commit))) + +(defun svn-log-edit-save-message () + "Save the current log message to the file `svn-log-edit-file-name'." + (interactive) + (let ((log-edit-file-name (svn-log-edit-file-name))) + (if (string= buffer-file-name log-edit-file-name) + (save-buffer) + (write-region (point-min) (point-max) log-edit-file-name)))) + +(defun svn-log-edit-erase-edit-buffer () + "Delete everything in the `svn-log-edit-buffer-name' buffer." + (interactive) + (set-buffer svn-log-edit-buffer-name) + (erase-buffer)) + +(defun svn-log-edit-insert-files-to-commit () + (interactive) + (svn-log-edit-remove-comment-lines) + (let ((buf-size (- (point-max) (point-min)))) + (save-excursion + (goto-char (point-min)) + (insert svn-log-edit-header) + (insert "## File(s) to commit" + (if svn-status-recursive-commit " recursively" "") ":\n") + (let ((file-list svn-status-files-to-commit)) + (while file-list + (insert (concat "## " (svn-status-line-info->filename (car file-list)) "\n")) + (setq file-list (cdr file-list))))) + (when (= 0 buf-size) + (goto-char (point-max))))) + +(defun svn-log-edit-remove-comment-lines () + (interactive) + (save-excursion + (goto-char (point-min)) + (flush-lines "^## .*"))) + +(defun svn-file-add-to-changelog (prefix-arg) + "Create a changelog entry for the function at point. +The variable `svn-status-changelog-style' allows to select the used changlog style" + (interactive "P") + (cond ((eq svn-status-changelog-style 'changelog) + (svn-file-add-to-log-changelog-style prefix-arg)) + ((eq svn-status-changelog-style 'svn-dev) + (svn-file-add-to-log-svn-dev-style prefix-arg)) + ((fboundp svn-status-changelog-style) + (funcall svn-status-changelog-style prefix-arg)) + (t + (error "Invalid setting for `svn-status-changelog-style'")))) + +(defun svn-file-add-to-log-changelog-style (curdir) + "Create a changelog entry for the function at point. +`add-change-log-entry-other-window' creates the header information. +If CURDIR, save the log file in the current directory, otherwise in the base directory of this working copy." + (interactive "P") + (add-change-log-entry-other-window nil (svn-log-edit-file-name curdir)) + (svn-log-edit-mode)) + +;; taken from svn-dev.el: svn-log-path-derive +(defun svn-dev-log-path-derive (path) + "Derive a relative directory path for absolute PATH, for a log entry." + (save-match-data + (let ((base (file-name-nondirectory path)) + (chop-spot (string-match + "\\(code/\\)\\|\\(src/\\)\\|\\(projects/\\)" + path))) + (if chop-spot + (progn + (setq path (substring path (match-end 0))) + ;; Kluge for Subversion developers. + (if (string-match "subversion/" path) + (substring path (+ (match-beginning 0) 11)) + path)) + (string-match (expand-file-name "~/") path) + (substring path (match-end 0)))))) + +;; taken from svn-dev.el: svn-log-message +(defun svn-file-add-to-log-svn-dev-style (prefix-arg) + "Add to an in-progress log message, based on context around point. +If PREFIX-ARG is negative, then use basenames only in +log messages, otherwise use full paths. The current defun name is +always used. + +If PREFIX-ARG is a list (e.g. by using C-u), save the log file in +the current directory, otherwise in the base directory of this +working copy. + +If the log message already contains material about this defun, then put +point there, so adding to that material is easy. + +Else if the log message already contains material about this file, put +point there, and push onto the kill ring the defun name with log +message dressing around it, plus the raw defun name, so yank and +yank-next are both useful. + +Else if there is no material about this defun nor file anywhere in the +log message, then put point at the end of the message and insert a new +entry for file with defun. +" + (interactive "P") + (let* ((short-file-names (and (numberp prefix-arg) (< prefix-arg 0))) + (curdir (listp prefix-arg)) + (this-file (if short-file-names + (file-name-nondirectory buffer-file-name) + (svn-dev-log-path-derive buffer-file-name))) + (this-defun (or (add-log-current-defun) + (save-excursion + (save-match-data + (if (eq major-mode 'c-mode) + (progn + (if (fboundp 'c-beginning-of-statement-1) + (c-beginning-of-statement-1) + (c-beginning-of-statement)) + (search-forward "(" nil t) + (forward-char -1) + (forward-sexp -1) + (buffer-substring + (point) + (progn (forward-sexp 1) (point))))))))) + (log-file (svn-log-edit-file-name curdir))) + (find-file log-file) + (goto-char (point-min)) + ;; Strip text properties from strings + (set-text-properties 0 (length this-file) nil this-file) + (set-text-properties 0 (length this-defun) nil this-defun) + ;; If log message for defun already in progress, add to it + (if (and + this-defun ;; we have a defun to work with + (search-forward this-defun nil t) ;; it's in the log msg already + (save-excursion ;; and it's about the same file + (save-match-data + (if (re-search-backward ; Ick, I want a real filename regexp! + "^\\*\\s-+\\([a-zA-Z0-9-_.@=+^$/%!?(){}<>]+\\)" nil t) + (string-equal (match-string 1) this-file) + t)))) + (if (re-search-forward ":" nil t) + (if (looking-at " ") (forward-char 1))) + ;; Else no log message for this defun in progress... + (goto-char (point-min)) + ;; But if log message for file already in progress, add to it. + (if (search-forward this-file nil t) + (progn + (if this-defun (progn + (kill-new (format "(%s): " this-defun)) + (kill-new this-defun))) + (search-forward ")" nil t) + (if (looking-at " ") (forward-char 1))) + ;; Found neither defun nor its file, so create new entry. + (goto-char (point-max)) + (if (not (bolp)) (insert "\n")) + (insert (format "\n* %s (%s): " this-file (or this-defun ""))) + ;; Finally, if no derived defun, put point where the user can + ;; type it themselves. + (if (not this-defun) (forward-char -3)))))) + +;; -------------------------------------------------------------------------------- +;; svn-log-view-mode: +;; -------------------------------------------------------------------------------- + +(defvar svn-log-view-mode-map () "Keymap used in `svn-log-view-mode' buffers.") +(put 'svn-log-view-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-log-view-mode-map) + (setq svn-log-view-mode-map (make-sparse-keymap)) + (suppress-keymap svn-log-view-mode-map) + (define-key svn-log-view-mode-map (kbd "p") 'svn-log-view-prev) + (define-key svn-log-view-mode-map (kbd "n") 'svn-log-view-next) + (define-key svn-log-view-mode-map (kbd "~") 'svn-log-get-specific-revision) + (define-key svn-log-view-mode-map (kbd "f") 'svn-log-get-specific-revision) + (define-key svn-log-view-mode-map (kbd "E") 'svn-log-ediff-specific-revision) + (define-key svn-log-view-mode-map (kbd "=") 'svn-log-view-diff) + (define-key svn-log-view-mode-map (kbd "#") 'svn-log-mark-partner-revision) + (define-key svn-log-view-mode-map (kbd "x") 'svn-log-exchange-partner-mark-with-point) + (define-key svn-log-view-mode-map (kbd "TAB") 'svn-log-next-link) + (define-key svn-log-view-mode-map [backtab] 'svn-log-prev-link) + (define-key svn-log-view-mode-map (kbd "RET") 'svn-log-find-file-at-point) + (define-key svn-log-view-mode-map (kbd "e") 'svn-log-edit-log-entry) + (define-key svn-log-view-mode-map (kbd "q") 'bury-buffer)) + +(defvar svn-log-view-popup-menu-map () + "Keymap used to show popup menu in `svn-log-view-mode' buffers.") +(put 'svn-log-view-popup-menu-map 'risky-local-variable t) ;for Emacs 20.7 +(when (not svn-log-view-popup-menu-map) + (setq svn-log-view-popup-menu-map (make-sparse-keymap)) + (suppress-keymap svn-log-view-popup-menu-map) + (define-key svn-log-view-popup-menu-map [down-mouse-3] 'svn-log-view-popup-menu)) + +(easy-menu-define svn-log-view-mode-menu svn-log-view-mode-map +"'svn-log-view-mode' menu" + '("SVN-LogView" + ["Show Changeset" svn-log-view-diff t] + ["Ediff file at point" svn-log-ediff-specific-revision t] + ["Find file at point" svn-log-find-file-at-point t] + ["Mark as diff against revision" svn-log-mark-partner-revision t] + ["Get older revision for file at point" svn-log-get-specific-revision t] + ["Edit log message" svn-log-edit-log-entry t])) + +(defun svn-log-view-popup-menu (event) + (interactive "e") + (mouse-set-point event) + (let* ((rev (svn-log-revision-at-point))) + (when rev + (svn-status-face-set-temporary-during-popup + 'svn-status-marked-popup-face (svn-point-at-bol) (svn-point-at-eol) + svn-log-view-mode-menu)))) + +(defvar svn-log-view-font-lock-basic-keywords + '(("^r[0-9]+ .+" (0 `(face font-lock-keyword-face + mouse-face highlight + keymap ,svn-log-view-popup-menu-map)))) + "Basic keywords in `svn-log-view-mode'.") +(put 'svn-log-view-font-basic-lock-keywords 'risky-local-variable t) ;for Emacs 20.7 + +(defvar svn-log-view-font-lock-keywords) +(define-derived-mode svn-log-view-mode fundamental-mode "svn-log-view" + "Major Mode to show the output from svn log. +Commands: +\\{svn-log-view-mode-map} +" + (use-local-map svn-log-view-mode-map) + (easy-menu-add svn-log-view-mode-menu) + (set (make-local-variable 'svn-log-view-font-lock-keywords) svn-log-view-font-lock-basic-keywords) + (dolist (lh svn-log-link-handlers) + (add-to-list 'svn-log-view-font-lock-keywords (gethash lh svn-log-registered-link-handlers))) + (set (make-local-variable 'font-lock-defaults) '(svn-log-view-font-lock-keywords t))) + +(defun svn-log-view-next () + (interactive) + (when (re-search-forward "^r[0-9]+" nil t) + (beginning-of-line 2) + (unless (looking-at "Changed paths:") + (beginning-of-line 1)))) + +(defun svn-log-view-prev () + (interactive) + (when (re-search-backward "^r[0-9]+" nil t 2) + (beginning-of-line 2) + (unless (looking-at "Changed paths:") + (beginning-of-line 1)))) + +(defun svn-log-mark-partner-revision () + "Mark the revision at point to be used as diff against revision." + (interactive) + (let ((start-pos) + (point-at-partner-rev) + (overlay)) + (dolist (ov (overlays-in (point-min) (point-max))) + (when (overlay-get ov 'svn-log-partner-revision) + (setq point-at-partner-rev (and (>= (point) (overlay-start ov)) + (<= (point) (overlay-end ov)))) + (delete-overlay ov))) + (unless point-at-partner-rev + (save-excursion + (when (re-search-backward "^r[0-9]+" nil t 1) + (setq start-pos (point)) + (re-search-forward "^---------------") + (setq overlay (make-overlay start-pos (line-beginning-position 0))) + (overlay-put overlay 'face 'svn-log-partner-highlight-face) + (overlay-put overlay 'svn-log-partner-revision t)))))) + +(defun svn-log-exchange-partner-mark-with-point () + (interactive) + (let ((cur-pos (point)) + (dest-pos)) + (dolist (ov (overlays-in (point-min) (point-max))) + (when (overlay-get ov 'svn-log-partner-revision) + (setq dest-pos (overlay-start ov)))) + (when dest-pos + (svn-log-mark-partner-revision) + (goto-char dest-pos) + (forward-line 3) + (svn-log-view-prev) + (svn-log-view-next)))) + +(defun svn-log-revision-for-diff () + (let ((rev)) + (dolist (ov (overlays-in (point-min) (point-max))) + (when (overlay-get ov 'svn-log-partner-revision) + (save-excursion + (unless (and (>= (point) (overlay-start ov)) + (<= (point) (overlay-end ov))) + (goto-char (overlay-start ov)) + (setq rev (svn-log-revision-at-point)))))) + rev)) + +(defun svn-log-revision-at-point () + (save-excursion + (end-of-line) + (re-search-backward "^r\\([0-9]+\\)") + (svn-match-string-no-properties 1))) + +(defun svn-log-file-name-at-point (respect-checkout-prefix-path) + (let ((full-file-name) + (file-name) + (checkout-prefix-path (if respect-checkout-prefix-path + (url-unhex-string + (svn-status-checkout-prefix-path)) + ""))) + (save-excursion + (beginning-of-line) + (when (looking-at " [MA] /\\(.+\\)$") + (setq full-file-name (svn-match-string-no-properties 1)))) + (when (string= checkout-prefix-path "") + (setq checkout-prefix-path "/")) + (if (null full-file-name) + (progn + (message "No file at point") + nil) + (setq file-name + (if (eq (string-match (regexp-quote (substring checkout-prefix-path 1)) full-file-name) 0) + (substring full-file-name (- (length checkout-prefix-path) (if (string= checkout-prefix-path "/") 1 0))) + full-file-name)) + ;; (message "svn-log-file-name-at-point %s prefix: '%s', full-file-name: %s" file-name checkout-prefix-path full-file-name) + file-name))) + +(defun svn-log-find-file-at-point () + (interactive) + (let ((file-name (svn-log-file-name-at-point t))) + (when file-name + (let ((default-directory (svn-status-base-dir))) + ;;(message "svn-log-file-name-at-point: %s, default-directory: %s" file-name default-directory) + (find-file file-name))))) + +(defun svn-log-next-link () + "Jump to the next external link in this buffer" + (interactive) + (let ((start-pos (if (get-text-property (point) 'link-handler) + (next-single-property-change (point) 'link-handler) + (point)))) + (goto-char (or (next-single-property-change start-pos 'link-handler) (point))))) + +(defun svn-log-prev-link () + "Jump to the previous external link in this buffer" + (interactive) + (let ((start-pos (if (get-text-property (point) 'link-handler) + (previous-single-property-change (point) 'link-handler) + (point)))) + (goto-char (or (previous-single-property-change (or start-pos (point)) 'link-handler) (point))))) + +(defun svn-log-view-diff (arg) + "Show the changeset for a given log entry. +When called with a prefix argument, ask the user for the revision." + (interactive "P") + (svn-status-diff-show-changeset (svn-log-revision-at-point) arg (svn-log-revision-for-diff))) + +(defun svn-log-get-specific-revision () + "Get an older revision of the file at point via svn cat." + (interactive) + ;; (message "%S" (svn-status-make-line-info (svn-log-file-name-at-point t))) + (let ((default-directory (svn-status-base-dir)) + (file-name (svn-log-file-name-at-point t))) + (if file-name + (svn-status-get-specific-revision-internal + (list (svn-status-make-line-info file-name)) + (svn-log-revision-at-point) + nil) + (message "No file at point")))) + +(defun svn-log-ediff-specific-revision (&optional user-confirmation) + "Call ediff for the file at point to view a changeset. +When called with a prefix argument, ask the user for the revision." + (interactive "P") + ;; (message "svn-log-ediff-specific-revision: %s" (svn-log-file-name-at-point t)) + (let* ((cur-buf (current-buffer)) + (diff-rev (svn-log-revision-for-diff)) + (upper-rev (if diff-rev + diff-rev + (svn-log-revision-at-point))) + (lower-rev (if diff-rev + (svn-log-revision-at-point) + (number-to-string (- (string-to-number upper-rev) 1)))) + (file-name (svn-log-file-name-at-point t)) + (default-directory (svn-status-base-dir)) + (upper-rev-file-name) + (lower-rev-file-name) + (rev-arg)) + (when user-confirmation + (setq rev-arg (read-string "Revision for changeset: " (concat lower-rev ":" upper-rev))) + (setq lower-rev (car (split-string rev-arg ":"))) + (setq upper-rev (cadr (split-string rev-arg ":")))) + ;;(message "lower-rev: %s, upper-rev: %s" lower-rev upper-rev) + (setq upper-rev-file-name (when file-name + (cdar (svn-status-get-specific-revision-internal + (list (svn-status-make-line-info file-name)) upper-rev nil)))) + (setq lower-rev-file-name (when file-name + (cdar (svn-status-get-specific-revision-internal + (list (svn-status-make-line-info file-name)) lower-rev nil)))) + ;;(message "%S %S" upper-rev-file-name lower-rev-file-name) + (if file-name + (let* ((ediff-after-quit-destination-buffer cur-buf) + (newer-buffer (find-file-noselect upper-rev-file-name)) + (base-buff (find-file-noselect lower-rev-file-name)) + (svn-transient-buffers (list base-buff newer-buffer)) + (startup-hook '(svn-ediff-startup-hook))) + (ediff-buffers base-buff newer-buffer startup-hook)) + (message "No file at point")))) + +(defun svn-log-edit-log-entry () + "Edit the given log entry." + (interactive) + (let ((rev (svn-log-revision-at-point)) + (log-message)) + (svn-run nil t 'propget-parse "propget" "--revprop" (concat "-r" rev) "svn:log") + (save-excursion + (set-buffer svn-process-buffer-name) + (setq log-message (if (> (point-max) 1) + (buffer-substring (point-min) (- (point-max) 1)) + ""))) + (svn-status-pop-to-commit-buffer) + ;; If the buffer has been narrowed, `svn-log-edit-done' will use + ;; only the accessible part. So we need not erase the rest here. + (delete-region (point-min) (point-max)) + (insert log-message) + (goto-char (point-min)) + (setq svn-log-edit-update-log-entry rev))) + + +;; allow additional hyperlinks in log view buffers +(defvar svn-log-link-keymap () + "Keymap used to resolve links `svn-log-view-mode' buffers.") +(put 'svn-log-link-keymap 'risky-local-variable t) ;for Emacs 20.7 +(when (not svn-log-link-keymap) + (setq svn-log-link-keymap (make-sparse-keymap)) + (suppress-keymap svn-log-link-keymap) + (define-key svn-log-link-keymap [mouse-2] 'svn-log-resolve-mouse-link) + (define-key svn-log-link-keymap (kbd "RET") 'svn-log-resolve-link)) + +(defun svn-log-resolve-mouse-link (event) + (interactive "e") + (mouse-set-point event) + (svn-log-resolve-link)) + +(defun svn-log-resolve-link () + (interactive) + (let* ((point-adjustment (if (not (get-text-property (- (point) 1) 'link-handler)) 1 + (if (not (get-text-property (+ (point) 1) 'link-handler)) -1 0))) + (link-name (buffer-substring-no-properties (previous-single-property-change (+ (point) point-adjustment) 'link-handler) + (next-single-property-change (+ (point) point-adjustment) 'link-handler)))) + ;; (message "svn-log-resolve-link '%s'" link-name) + (funcall (get-text-property (point) 'link-handler) link-name))) + +(defun svn-log-register-link-handler (handler-id link-regexp handler-function) + "Register a link handler for external links in *svn-log* buffers +HANDLER-ID is a symbolic name for this handler. The link handler is active when HANDLER-ID +is registered in `svn-log-link-handlers'. +LINK-REGEXP specifies a regular expression that matches the external link. +HANDLER-FUNCTION is called with the match of LINK-REGEXP when the user clicks at the external link." + (let ((font-lock-desc (list link-regexp '(0 `(face font-lock-function-name-face + mouse-face highlight + link-handler invalid-handler-function + keymap ,svn-log-link-keymap))))) + ;; no idea, how to use handler-function in invalid-handler-function above, so set it here + (setcar (nthcdr 5 (nth 1 (nth 1 (nth 1 font-lock-desc)))) handler-function) + (svn-puthash handler-id font-lock-desc svn-log-registered-link-handlers))) + +;; example: add support for ditrack links and handle them via svn-log-resolve-ditrack +;;(svn-log-register-link-handler 'ditrack-issue "i#[0-9]+" 'svn-log-resolve-ditrack) +;;(defun svn-log-resolve-ditrack (link-name) +;; (interactive) +;; (message "svn-log-resolve-ditrack %s" link-name)) + + +(defun svn-log-resolve-trac-ticket-short (link-name) + "Show the trac ticket specified by LINK-NAME via `svn-trac-browse-ticket'." + (interactive) + (let ((ticket-nr (string-to-number (svn-substring-no-properties link-name 1)))) + (svn-trac-browse-ticket ticket-nr))) + +;; register the out of the box provided link handlers +(svn-log-register-link-handler 'trac-ticket-short "#[0-9]+" 'svn-log-resolve-trac-ticket-short) + +;; the actually used link handlers are specified in svn-log-link-handlers + +;; -------------------------------------------------------------------------------- +;; svn-info-mode +;; -------------------------------------------------------------------------------- +(defvar svn-info-mode-map () "Keymap used in `svn-info-mode' buffers.") +(put 'svn-info-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-info-mode-map) + (setq svn-info-mode-map (make-sparse-keymap)) + (define-key svn-info-mode-map [?s] 'svn-status-pop-to-status-buffer) + (define-key svn-info-mode-map (kbd "h") 'svn-status-pop-to-partner-buffer) + (define-key svn-info-mode-map (kbd "n") 'next-line) + (define-key svn-info-mode-map (kbd "p") 'previous-line) + (define-key svn-info-mode-map (kbd "RET") 'svn-info-show-context) + (define-key svn-info-mode-map [?q] 'bury-buffer)) + +(defun svn-info-mode () + "Major Mode to view informative output from svn." + (interactive) + (kill-all-local-variables) + (use-local-map svn-info-mode-map) + (setq major-mode 'svn-info-mode) + (setq mode-name "svn-info") + (toggle-read-only 1)) + +(defun svn-info-show-context () + "Show the context for a line in the info buffer. +Currently is the output from the svn update command known." + (interactive) + (cond ((save-excursion + (goto-char (point-max)) + (forward-line -1) + (beginning-of-line) + (looking-at "Updated to revision")) + ;; svn-info contains info from an svn update + (let ((cur-pos (point)) + (file-name (buffer-substring-no-properties + (progn (beginning-of-line) (re-search-forward ".. +") (point)) + (line-end-position))) + (pos)) + (when (eq system-type 'windows-nt) + (setq file-name (replace-regexp-in-string "\\\\" "/" file-name))) + (goto-char cur-pos) + (with-current-buffer svn-status-buffer-name + (setq pos (svn-status-get-file-name-buffer-position file-name))) + (when pos + (svn-status-pop-to-new-partner-buffer svn-status-buffer-name) + (goto-char pos)))))) + +;; -------------------------------------------------------------------------------- +;; svn blame minor mode +;; -------------------------------------------------------------------------------- + +(unless (assq 'svn-blame-mode minor-mode-alist) + (setq minor-mode-alist + (cons (list 'svn-blame-mode " SvnBlame") + minor-mode-alist))) + +(defvar svn-blame-mode-map () "Keymap used in `svn-blame-mode' buffers.") +(put 'svn-blame-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-blame-mode-map) + (setq svn-blame-mode-map (make-sparse-keymap)) + (define-key svn-blame-mode-map [?s] 'svn-status-pop-to-status-buffer) + (define-key svn-blame-mode-map (kbd "n") 'next-line) + (define-key svn-blame-mode-map (kbd "p") 'previous-line) + (define-key svn-blame-mode-map (kbd "RET") 'svn-blame-open-source-file) + (define-key svn-blame-mode-map (kbd "a") 'svn-blame-highlight-author) + (define-key svn-blame-mode-map (kbd "r") 'svn-blame-highlight-revision) + (define-key svn-blame-mode-map (kbd "=") 'svn-blame-show-changeset) + (define-key svn-blame-mode-map (kbd "l") 'svn-blame-show-log) + (define-key svn-blame-mode-map (kbd "b") 'svn-blame-blame-again) + (define-key svn-blame-mode-map (kbd "s") 'svn-blame-show-statistics) + (define-key svn-blame-mode-map [?q] 'bury-buffer)) + +(easy-menu-define svn-blame-mode-menu svn-blame-mode-map +"svn blame minor mode menu" + '("SvnBlame" + ["Jump to source location" svn-blame-open-source-file t] + ["Show changeset" svn-blame-show-changeset t] + ["Show log" svn-blame-show-log t] + ["Show blame again" svn-blame-blame-again t] + ["Show statistics" svn-blame-show-statistics t] + ["Highlight by author" svn-blame-highlight-author t] + ["Highlight by revision" svn-blame-highlight-revision t])) + +(or (assq 'svn-blame-mode minor-mode-map-alist) + (setq minor-mode-map-alist + (cons (cons 'svn-blame-mode svn-blame-mode-map) minor-mode-map-alist))) + +(make-variable-buffer-local 'svn-blame-mode) + +(defun svn-blame-mode (&optional arg) + "Toggle svn blame minor mode. +With ARG, turn svn blame minor mode on if ARG is positive, off otherwise. + +Key bindings: +\\{svn-blame-mode-map}" + (interactive "P") + (setq svn-blame-mode (if (null arg) + (not svn-blame-mode) + (> (prefix-numeric-value arg) 0))) + (if svn-blame-mode + (progn + (easy-menu-add svn-blame-mode-menu) + (toggle-read-only 1)) + (easy-menu-remove svn-blame-mode-menu)) + (force-mode-line-update)) + +(defun svn-status-activate-blame-mode () + "Activate the svn blame minor in the current buffer. +The current buffer must contain a valid output from svn blame" + (save-excursion + (goto-char (point-min)) + (let ((buffer-read-only nil) + (line (svn-line-number-at-pos)) + (limit (point-max)) + (info-end-col (save-excursion (forward-word 2) (+ (current-column) 1))) + (s) + ov) + ;; remove the old overlays (only for testing) + ;; (dolist (ov (overlays-in (point) limit)) + ;; (when (overlay-get ov 'svn-blame-line-info) + ;; (delete-overlay ov))) + (while (and (not (eobp)) (< (point) limit)) + (setq s (buffer-substring-no-properties (svn-point-at-bol) (+ (svn-point-at-bol) info-end-col))) + (delete-region (svn-point-at-bol) (+ (svn-point-at-bol) info-end-col)) + (setq ov (make-overlay (point) (point))) + (overlay-put ov 'svn-blame-line-info t) + (overlay-put ov 'before-string (propertize s 'face 'svn-status-blame-rev-number-face)) + (overlay-put ov 'rev-info (delete "" (split-string s " "))) + (forward-line) + (setq line (1+ line))))) + (let* ((buf-name (format "*svn-blame: %s <%s>*" + (file-relative-name svn-status-blame-file-name) + svn-status-blame-revision)) + (buffer (get-buffer buf-name))) + (when buffer + (kill-buffer buffer)) + (rename-buffer buf-name)) + ;; use the correct mode for the displayed blame output + (let ((buffer-file-name svn-status-blame-file-name)) + (normal-mode) + (set (make-local-variable 'svn-status-blame-file-name) svn-status-blame-file-name)) + (font-lock-fontify-buffer) + (svn-blame-mode 1)) + +(defun svn-blame-open-source-file () + "Jump to the source file location for the current position in the svn blame buffer" + (interactive) + (let ((src-line-number (svn-line-number-at-pos)) + (src-line-col (current-column))) + (find-file-other-window svn-status-blame-file-name) + (goto-line src-line-number) + (forward-char src-line-col))) + +(defun svn-blame-rev-at-point () + (let ((rev)) + (dolist (ov (overlays-in (svn-point-at-bol) (line-end-position))) + (when (overlay-get ov 'svn-blame-line-info) + (setq rev (car (overlay-get ov 'rev-info))))) + rev)) + +(defun svn-blame-show-changeset (arg) + "Show a diff for the revision at point. +When called with a prefix argument, allow the user to edit the revision." + (interactive "P") + (svn-status-diff-show-changeset (svn-blame-rev-at-point) arg)) + +(defun svn-blame-show-log (arg) + "Show the log for the revision at point. +The output is put into the *svn-log* buffer +The optional prefix argument ARG determines which switches are passed to `svn log': + no prefix --- use whatever is in the list `svn-status-default-log-arguments' + prefix argument of -1: --- use the -q switch (quiet) + prefix argument of 0 --- use no arguments + other prefix arguments: --- use the -v switch (verbose)" + (interactive "P") + (let ((switches (svn-status-svn-log-switches arg)) + (rev (svn-blame-rev-at-point))) + (svn-run t t 'log "log" "--revision" rev switches))) + +(defun svn-blame-highlight-line-maybe (compare-func) + (let ((reference-value) + (is-highlighted) + (consider-this-line) + (hl-ov)) + (dolist (ov (overlays-in (svn-point-at-bol) (line-end-position))) + (when (overlay-get ov 'svn-blame-line-info) + (setq reference-value (funcall compare-func ov))) + (when (overlay-get ov 'svn-blame-highlighted) + (setq is-highlighted t))) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (setq consider-this-line nil) + (dolist (ov (overlays-in (svn-point-at-bol) (line-end-position))) + (when (overlay-get ov 'svn-blame-line-info) + (when (string= reference-value (funcall compare-func ov)) + (setq consider-this-line t)))) + (when consider-this-line + (dolist (ov (overlays-in (svn-point-at-bol) (line-end-position))) + (when (and (overlay-get ov 'svn-blame-highlighted) is-highlighted) + (delete-overlay ov)) + (unless is-highlighted + (setq hl-ov (make-overlay (svn-point-at-bol) (line-end-position))) + (overlay-put hl-ov 'svn-blame-highlighted t) + (overlay-put hl-ov 'face 'svn-status-blame-highlight-face)))) + (forward-line))))) + +(defun svn-blame-show-statistics () + "Show statistics for the current blame buffer." + (interactive) + (let ((author-map (make-hash-table :test 'equal)) + (revision-map (make-hash-table :test 'equal)) + (rev-info) + (author-list) + (author) + (revision-list) + (revision)) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (dolist (ov (overlays-in (svn-point-at-bol) (line-end-position))) + (when (overlay-get ov 'svn-blame-line-info) + (setq rev-info (overlay-get ov 'rev-info)) + (setq author (cadr rev-info)) + (setq revision (string-to-number (car rev-info))) + (svn-puthash author (+ (gethash author author-map 0) 1) author-map) + (svn-puthash revision (+ (gethash revision revision-map 0) 1) revision-map))) + (forward-line)) + (maphash '(lambda (key value) (add-to-list 'author-list (list key value))) author-map) + (maphash '(lambda (key value) (add-to-list 'revision-list (list key value))) revision-map) + (pop-to-buffer (get-buffer-create (replace-regexp-in-string "svn-blame:" "svn-blame-statistics:" (buffer-name)))) + (erase-buffer) + (insert (propertize "Authors:\n" 'face 'font-lock-function-name-face)) + (dolist (line (sort author-list '(lambda (v1 v2) (> (cadr v1) (cadr v2))))) + (insert (format "%s: %s line%s\n" (car line) (cadr line) (if (eq (cadr line) 1) "" "s")))) + (insert (propertize "\nRevisions:\n" 'face 'font-lock-function-name-face)) + (dolist (line (sort revision-list '(lambda (v1 v2) (< (car v1) (car v2))))) + (insert (format "%s: %s line%s\n" (car line) (cadr line) (if (eq (cadr line) 1) "" "s")))) + (goto-char (point-min))))) + +(defun svn-blame-highlight-author-field (ov) + (cadr (overlay-get ov 'rev-info))) + +(defun svn-blame-highlight-author () + "(Un)Highlight all lines with the same author." + (interactive) + (svn-blame-highlight-line-maybe 'svn-blame-highlight-author-field)) + +(defun svn-blame-highlight-revision-field (ov) + (car (overlay-get ov 'rev-info))) + +(defun svn-blame-highlight-revision () + "(Un)Highlight all lines with the same revision." + (interactive) + (svn-blame-highlight-line-maybe 'svn-blame-highlight-revision-field)) + +;; -------------------------------------------------------------------------------- +;; svn-process-mode +;; -------------------------------------------------------------------------------- +(defvar svn-process-mode-map () "Keymap used in `svn-process-mode' buffers.") +(put 'svn-process-mode-map 'risky-local-variable t) ;for Emacs 20.7 + +(when (not svn-process-mode-map) + (setq svn-process-mode-map (make-sparse-keymap)) + (define-key svn-process-mode-map (kbd "RET") 'svn-process-send-string-and-newline) + (define-key svn-process-mode-map [?s] 'svn-process-send-string) + (define-key svn-process-mode-map [?q] 'bury-buffer)) + +(easy-menu-define svn-process-mode-menu svn-process-mode-map +"'svn-process-mode' menu" + '("SvnProcess" + ["Send line to process" svn-process-send-string-and-newline t] + ["Send raw string to process" svn-process-send-string t] + ["Bury process buffer" bury-buffer t])) + +(defun svn-process-mode () + "Major Mode to view process output from svn. + +You can send a new line terminated string to the process via \\[svn-process-send-string-and-newline] +You can send raw data to the process via \\[svn-process-send-string]." + (interactive) + (kill-all-local-variables) + (use-local-map svn-process-mode-map) + (easy-menu-add svn-log-view-mode-menu) + (setq major-mode 'svn-process-mode) + (setq mode-name "svn-process")) + +;; -------------------------------------------------------------------------------- +;; svn status persistent options +;; -------------------------------------------------------------------------------- + +(defun svn-status-repo-for-path (directory) + "Find the repository root for DIRECTORY." + (let ((old-process-default-dir)) + (with-current-buffer (get-buffer-create svn-process-buffer-name) + (setq old-process-default-dir default-directory) + (setq default-directory directory)) ;; update the default-directory for the *svn-process* buffer + (svn-status-parse-info t) + (or (plist-get svn-status-base-info :repository-root) + (if (plist-get svn-status-base-info :repository-uuid) + (concat "Svn Repo UUID: " (plist-get svn-status-base-info :repository-uuid)) + (message "psvn.el: Detected an old svn working copy in '%s'. Please check it out again to get a 'Repository Root' entry in the svn info output." + default-directory))))) + +(defun svn-status-base-dir (&optional start-directory) + "Find the svn root directory for the current working copy. +Return nil, if not in a svn working copy." + (let* ((start-dir (expand-file-name (or start-directory default-directory))) + (base-dir (gethash start-dir svn-status-base-dir-cache 'not-found))) + ;;(message "svn-status-base-dir: %S %S" start-dir base-dir) + (if (not (eq base-dir 'not-found)) + base-dir + ;; (message "calculating base-dir for %s" start-dir) + (svn-compute-svn-client-version) + ;; (message "repository-root: %s start-dir: %s" repository-root start-dir) + (cond + ((and (<= (car svn-client-version) 1) (< (cadr svn-client-version) 3)) + (setq base-dir (svn-status-base-dir-for-ancient-svn-client start-dir))) ;; svn version < 1.3 + ((and (<= (car svn-client-version) 1) (< (cadr svn-client-version) 7)) + (setq base-dir (svn-status-base-dir-for-old-svn-client start-dir))) ;; svn version < 1.7 + (t + (setq base-dir (svn-status-base-dir-1 start-dir)))) + (when base-dir + (svn-puthash start-dir base-dir svn-status-base-dir-cache)) + (svn-status-message 7 "svn-status-base-dir %s => %s" start-dir base-dir) + base-dir))) + +(defun svn-status-base-dir-1 (&optional start-directory) + "Find the svn root directory for the current working copy. +Return nil, if not in a svn working copy. +This function is used for svn clients version 1.7 and up." + (let ((default-directory (if start-directory + (expand-file-name start-directory) + (symbol-value 'default-directory))) + parent + wc-root) + (when (svn-version-controlled-dir-p default-directory) + (svn-status-parse-info t) + (setq wc-root (file-name-as-directory (plist-get svn-status-base-info :working-copy-root-path))) + (when wc-root + ;; traversing up the hierarchy shortens the path name. Stop if + ;; it doesn't, e.g we reached / already. + (setq parent (expand-file-name (concat wc-root ".."))) + (or (and (< (length parent) (length wc-root)) + (svn-status-base-dir-1 (expand-file-name (concat wc-root "..")))) + wc-root))))) + +(defun svn-status-base-dir-for-old-svn-client (&optional start-directory) + "Find the svn root directory for the current working copy. +Return nil, if not in a svn working copy. +This function is used for svn clients version 1.6 and below." + (let* ((base-dir (expand-file-name (or start-directory default-directory))) + (repository-root (svn-status-repo-for-path base-dir)) + (dot-svn-dir (concat base-dir (svn-wc-adm-dir-name))) + (in-tree (and repository-root (file-exists-p dot-svn-dir))) + (dir-below (expand-file-name base-dir))) + (while (when (and dir-below (file-exists-p dot-svn-dir)) + (setq base-dir (file-name-directory dot-svn-dir)) + (string-match "\\(.+/\\).+/" dir-below) + (setq dir-below + (and (string-match "\\(.*/\\)[^/]+/" dir-below) + (match-string 1 dir-below))) + ;; (message "base-dir: %s, dir-below: %s, dot-svn-dir: %s in-tree: %s" base-dir dir-below dot-svn-dir in-tree) + (when dir-below + (if (string= (svn-status-repo-for-path dir-below) repository-root) + (setq dot-svn-dir (concat dir-below (svn-wc-adm-dir-name))) + (setq dir-below nil))))) + (and in-tree base-dir))) + +(defun svn-status-base-dir-for-ancient-svn-client (&optional start-directory) + "Find the svn root directory for the current working copy. +Return nil, if not in a svn working copy. +This function is used for svn clients version 1.2 and below." + (let* ((base-dir (expand-file-name (or start-directory default-directory))) + (dot-svn-dir (concat base-dir (svn-wc-adm-dir-name))) + (in-tree (file-exists-p dot-svn-dir)) + (dir-below (expand-file-name default-directory))) + (while (when (and dir-below (file-exists-p dot-svn-dir)) + (setq base-dir (file-name-directory dot-svn-dir)) + (string-match "\\(.+/\\).+/" dir-below) + (setq dir-below + (and (string-match "\\(.*/\\)[^/]+/" dir-below) + (match-string 1 dir-below))) + (setq dot-svn-dir (concat dir-below (svn-wc-adm-dir-name))))) + (and in-tree base-dir))) + +(defun svn-status-save-state () + "Save psvn persistent options for this working copy to a file." + (interactive) + (let ((buf (find-file (concat (svn-status-base-dir) "++psvn.state")))) + (erase-buffer) ;Widen, because we'll save the whole buffer. + ;; TO CHECK: why is svn-status-options a global variable?? + (setq svn-status-options + (list + (list "svn-trac-project-root" svn-trac-project-root) + (list "sort-status-buffer" svn-status-sort-status-buffer) + (list "elide-list" svn-status-elided-list) + (list "module-name" svn-status-module-name) + (list "branch-list" svn-status-branch-list) + (list "changelog-style" svn-status-changelog-style) + )) + (insert (pp-to-string svn-status-options)) + (save-buffer) + (kill-buffer buf))) + +(defun svn-status-load-state (&optional no-error) + "Load psvn persistent options for this working copy from a file." + (interactive) + (let ((file (concat (svn-status-base-dir) "++psvn.state"))) + (if (file-readable-p file) + (with-temp-buffer + (insert-file-contents file) + (setq svn-status-options (read (current-buffer))) + (setq svn-status-sort-status-buffer + (nth 1 (assoc "sort-status-buffer" svn-status-options))) + (setq svn-trac-project-root + (nth 1 (assoc "svn-trac-project-root" svn-status-options))) + (setq svn-status-elided-list + (nth 1 (assoc "elide-list" svn-status-options))) + (setq svn-status-module-name + (nth 1 (assoc "module-name" svn-status-options))) + (setq svn-status-branch-list + (nth 1 (assoc "branch-list" svn-status-options))) + (setq svn-status-changelog-style + (nth 1 (assoc "changelog-style" svn-status-options))) + (when (and (interactive-p) svn-status-elided-list (svn-status-apply-elide-list))) + (message "psvn.el: loaded %s" file)) + (if no-error + (setq svn-trac-project-root nil + svn-status-elided-list nil + svn-status-module-name nil + svn-status-branch-list nil + svn-status-changelog-style 'changelog) + (error "psvn.el: %s is not readable." file))))) + +(defun svn-status-toggle-sort-status-buffer () + "Toggle sorting of the *svn-status* buffer. + +If you turn off sorting, you can speed up \\[svn-status]. However, +the buffer is not correctly sorted then. This function will be +removed again, when a faster parsing and display routine for +`svn-status' is available." + (interactive) + (setq svn-status-sort-status-buffer (not svn-status-sort-status-buffer)) + (message "The %s buffer will %sbe sorted." svn-status-buffer-name + (if svn-status-sort-status-buffer "" "not "))) + +(defun svn-status-toggle-svn-verbose-flag () + "Toggle `svn-status-verbose'. " + (interactive) + (setq svn-status-verbose (not svn-status-verbose)) + (message "svn status calls will %suse the -v flag." (if svn-status-verbose "" "not "))) + +(defun svn-status-toggle-display-full-path () + "Toggle displaying the full path in the `svn-status-buffer-name' buffer" + (interactive) + (setq svn-status-display-full-path (not svn-status-display-full-path)) + (message "The %s buffer will%s use full path names." svn-status-buffer-name + (if svn-status-display-full-path "" " not")) + (svn-status-update-buffer)) + +(defun svn-status-set-trac-project-root () + (interactive) + (setq svn-trac-project-root + (read-string "Trac project root (e.g.: http://projects.edgewall.com/trac/): " + svn-trac-project-root)) + (when (yes-or-no-p "Save the new setting for svn-trac-project-root to disk? ") + (svn-status-save-state))) + +(defun svn-status-set-module-name () + "Interactively set `svn-status-module-name'." + (interactive) + (setq svn-status-module-name + (read-string "Short Unit Name (e.g.: MyProject): " + svn-status-module-name)) + (when (yes-or-no-p "Save the new setting for svn-status-module-name to disk? ") + (svn-status-save-state))) + +(defun svn-status-set-changelog-style () + "Interactively set `svn-status-changelog-style'." + (interactive) + (setq svn-status-changelog-style + (intern (funcall svn-status-completing-read-function "svn-status on directory: " '("changelog" "svn-dev" "other")))) + (when (string= svn-status-changelog-style 'other) + (setq svn-status-changelog-style (car (find-function-read)))) + (when (yes-or-no-p "Save the new setting for svn-status-changelog-style to disk? ") + (svn-status-save-state))) + +(defun svn-status-set-branch-list () + "Interactively set `svn-status-branch-list'." + (interactive) + (setq svn-status-branch-list + (split-string (read-string "Branch list: " + (mapconcat 'identity svn-status-branch-list " ")))) + (when (yes-or-no-p "Save the new setting for svn-status-branch-list to disk? ") + (svn-status-save-state))) + +(defun svn-browse-url (url) + "Call `browse-url', using `svn-browse-url-function'." + (let ((browse-url-browser-function (or svn-browse-url-function + browse-url-browser-function))) + (browse-url url))) + +;; -------------------------------------------------------------------------------- +;; svn status trac integration +;; -------------------------------------------------------------------------------- +(defun svn-trac-browse-wiki () + "Open the trac wiki view for the current svn repository." + (interactive) + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "wiki"))) + +(defun svn-trac-browse-timeline () + "Open the trac timeline view for the current svn repository." + (interactive) + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "timeline"))) + +(defun svn-trac-browse-roadmap () + "Open the trac roadmap view for the current svn repository." + (interactive) + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "roadmap"))) + +(defun svn-trac-browse-source () + "Open the trac source browser for the current svn repository." + (interactive) + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "browser"))) + +(defun svn-trac-browse-report (arg) + "Open the trac report view for the current svn repository. +When called with a prefix argument, display the given report number." + (interactive "P") + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "report" (if (numberp arg) (format "/%s" arg) "")))) + +(defun svn-trac-browse-changeset (changeset-nr) + "Show a changeset in the trac issue tracker." + (interactive (list (read-number "Browse changeset number: " (number-at-point)))) + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "changeset/" (number-to-string changeset-nr)))) + +(defun svn-trac-browse-ticket (ticket-nr) + "Show a ticket in the trac issue tracker." + (interactive (list (read-number "Browse ticket number: " (number-at-point)))) + (unless svn-trac-project-root + (svn-status-set-trac-project-root)) + (svn-browse-url (concat svn-trac-project-root "ticket/" (number-to-string ticket-nr)))) + +;;;------------------------------------------------------------ +;;; resolve conflicts using ediff +;;;------------------------------------------------------------ +(defun svn-resolve-conflicts-ediff (&optional name-A name-B) + "Invoke ediff to resolve conflicts in the current buffer. +The conflicts must be marked with rcsmerge conflict markers." + (interactive) + (let* ((found nil) + (file-name (file-name-nondirectory buffer-file-name)) + (your-buffer (generate-new-buffer + (concat "*" file-name + " " (or name-A "WORKFILE") "*"))) + (other-buffer (generate-new-buffer + (concat "*" file-name + " " (or name-B "CHECKED-IN") "*"))) + (result-buffer (current-buffer))) + (save-excursion + (set-buffer your-buffer) + (erase-buffer) + (insert-buffer-substring result-buffer) + (goto-char (point-min)) + (while (re-search-forward "^<<<<<<< .\\(mine\\|working\\)\n" nil t) + (setq found t) + (replace-match "") + (if (not (re-search-forward "^=======\n" nil t)) + (error "Malformed conflict marker")) + (replace-match "") + (let ((start (point))) + (if (not (re-search-forward "^>>>>>>> .\\(r[0-9]+\\|merge.*\\)\n" nil t)) + (error "Malformed conflict marker")) + (delete-region start (point)))) + (if (not found) + (progn + (kill-buffer your-buffer) + (kill-buffer other-buffer) + (error "No conflict markers found"))) + (set-buffer other-buffer) + (erase-buffer) + (insert-buffer-substring result-buffer) + (goto-char (point-min)) + (while (re-search-forward "^<<<<<<< .\\(mine\\|working\\)\n" nil t) + (let ((start (match-beginning 0))) + (if (not (re-search-forward "^=======\n" nil t)) + (error "Malformed conflict marker")) + (delete-region start (point)) + (if (not (re-search-forward "^>>>>>>> .\\(r[0-9]+\\|merge.*\\)\n" nil t)) + (error "Malformed conflict marker")) + (replace-match ""))) + (let ((config (current-window-configuration)) + (ediff-default-variant 'default-B)) + + ;; Fire up ediff. + + (set-buffer (ediff-merge-buffers your-buffer other-buffer)) + + ;; Ediff is now set up, and we are in the control buffer. + ;; Do a few further adjustments and take precautions for exit. + + (make-local-variable 'svn-ediff-windows) + (setq svn-ediff-windows config) + (make-local-variable 'svn-ediff-result) + (setq svn-ediff-result result-buffer) + (make-local-variable 'ediff-quit-hook) + (setq ediff-quit-hook + (lambda () + (let ((buffer-A ediff-buffer-A) + (buffer-B ediff-buffer-B) + (buffer-C ediff-buffer-C) + (result svn-ediff-result) + (windows svn-ediff-windows)) + (ediff-cleanup-mess) + (set-buffer result) + (erase-buffer) + (insert-buffer-substring buffer-C) + (kill-buffer buffer-A) + (kill-buffer buffer-B) + (kill-buffer buffer-C) + (set-window-configuration windows) + (message "Conflict resolution finished; you may save the buffer")))) + (message "Please resolve conflicts now; exit ediff when done") + nil)))) + +(defun svn-resolve-conflicts (filename) + (let ((buff (find-file-noselect filename))) + (if buff + (progn (switch-to-buffer buff) + (svn-resolve-conflicts-ediff)) + (error "can not open file %s" filename)))) + +(defun svn-status-resolve-conflicts () + "Resolve conflict in the selected file" + (interactive) + (let ((file-info (svn-status-get-line-information))) + (or (and file-info + (= ?C (svn-status-line-info->filemark file-info)) + (svn-resolve-conflicts + (svn-status-line-info->full-path file-info))) + (error "can not resolve conflicts at this point")))) + + +;; -------------------------------------------------------------------------------- +;; Working with branches +;; -------------------------------------------------------------------------------- + +(defun svn-branch-select (&optional prompt) + "Select a branch interactively from `svn-status-branch-list'" + (interactive) + (unless prompt + (setq prompt "Select branch: ")) + (let* ((branch (funcall svn-status-completing-read-function prompt svn-status-branch-list)) + (directory) + (base-url)) + (when (string-match "#\\(1#\\)?\\(.+\\)" branch) + (setq directory (match-string 2 branch)) + (setq base-url (concat (svn-status-base-info->repository-root) "/" directory)) + (save-match-data + (svn-status-parse-info t)) + (if (eq (length (match-string 1 branch)) 0) + (setq branch base-url) + (let ((svn-status-branch-list (svn-status-ls base-url t))) + (setq branch (concat (svn-status-base-info->repository-root) "/" + directory "/" + (svn-branch-select (format "Select branch from '%s': " directory))))))) + branch)) + +(defun svn-branch-diff (branch1 branch2) + "Show the diff between two svn repository urls. +When called interactively, use `svn-branch-select' to choose two branches from `svn-status-branch-list'." + (interactive + (let* ((branch1 (svn-branch-select "svn diff branch1: ")) + (branch2 (svn-branch-select (format "svn diff %s against: " branch1)))) + (list branch1 branch2))) + (svn-run t t 'diff "diff" svn-status-default-diff-arguments branch1 branch2)) + +;; -------------------------------------------------------------------------------- +;; svnadmin interface +;; -------------------------------------------------------------------------------- +(defun svn-admin-create (dir) + "Run svnadmin create DIR." + (interactive (list (expand-file-name + (svn-read-directory-name "Create a svn repository at: " + svn-admin-default-create-directory nil nil)))) + (shell-command-to-string (concat "svnadmin create " dir)) + (setq svn-admin-last-repository-dir (concat "file://" dir)) + (message "Svn repository created at %s" dir) + (run-hooks 'svn-admin-create-hook)) + +;; - Import an empty directory +;; cd to an empty directory +;; svn import -m "Initial import" . file:///home/stefan/svn_repos/WaldiConfig/trunk +(defun svn-admin-create-trunk-directory () + "Import an empty trunk directory to `svn-admin-last-repository-dir'. +Set `svn-admin-last-repository-dir' to the new created trunk url." + (interactive) + (let ((empty-temp-dir-name (make-temp-name svn-status-temp-dir))) + (make-directory empty-temp-dir-name t) + (setq svn-admin-last-repository-dir (concat svn-admin-last-repository-dir "/trunk")) + (svn-run nil t 'import "import" "-m" "Created trunk directory" + empty-temp-dir-name svn-admin-last-repository-dir) + (delete-directory empty-temp-dir-name))) + +(defun svn-admin-start-import () + "Start to import the current working directory in a subversion repository. +The user is asked to perform the following two steps: +1. Create a local repository +2. Add a trunk directory to that repository + +After that step the empty base directory (either the root directory or +the trunk directory of the selected repository) is checked out in the current +working directory." + (interactive) + (if (y-or-n-p "Create local repository? ") + (progn + (call-interactively 'svn-admin-create) + (when (y-or-n-p "Add a trunk directory? ") + (svn-admin-create-trunk-directory))) + (setq svn-admin-last-repository-dir (read-string "Repository Url: "))) + (svn-checkout svn-admin-last-repository-dir ".")) + +;; -------------------------------------------------------------------------------- +;; svn status profiling +;; -------------------------------------------------------------------------------- +;;; Note about profiling psvn: +;; (load-library "elp") +;; M-x elp-reset-all +;; (elp-instrument-package "svn-") +;; M-x svn-status +;; M-x elp-results + +(defun svn-status-elp-init () + (interactive) + (require 'elp) + (elp-reset-all) + (elp-instrument-package "svn-") + (message "Run the desired svn command (e.g. M-x svn-status), then use M-x elp-results.")) + +(defun svn-status-last-commands (&optional string-prefix) + "Return a string with the last executed svn commands" + (interactive) + (unless string-prefix + (setq string-prefix "")) + (with-output-to-string + (dolist (e (ring-elements svn-last-cmd-ring)) + (princ (format "%s%s: svn %s <%s>\n" string-prefix (nth 0 e) (mapconcat 'concat (nth 1 e) " ") (nth 2 e))) + (when (nth 3 e) + (princ (format "%s\n" string-prefix)) + (princ (nth 3 e)) + (princ (format "%s\n" string-prefix)))))) + +;; -------------------------------------------------------------------------------- +;; reporting bugs +;; -------------------------------------------------------------------------------- +(defun svn-insert-indented-lines (text) + "Helper function to insert TEXT, indented by two characters." + (dolist (line (split-string text "\n")) + (insert (format " %s\n" line)))) + +(defun svn-prepare-bug-report () + "Create the buffer *psvn-bug-report*. This buffer can be useful to debug problems with psvn.el" + (interactive) + (let* ((last-output-buffer-name (or svn-status-last-output-buffer-name svn-process-buffer-name)) + (last-svn-cmd-output (with-current-buffer last-output-buffer-name + (buffer-substring-no-properties (point-min) (point-max))))) + (switch-to-buffer "*psvn-bug-report*") + (delete-region (point-min) (point-max)) + (insert "This buffer holds some debug informations for psvn.el\n") + (insert "Please enter a description of the observed and the wanted behaviour\n") + (insert "and send it to the author (stefan@xsteve.at) to allow easier debugging\n\n") + (insert "Revisions:\n") + (svn-insert-indented-lines (svn-status-version)) + (insert "Language environment:\n") + (dolist (elem (svn-process-environment)) + (when (member (car (split-string elem "=")) '("LC_MESSAGES" "LC_ALL" "LANG")) + (insert (format " %s\n" elem)))) + (when svn-process-handle-error-msg + (insert "\nsvn client error message:\n") + (svn-insert-indented-lines svn-process-handle-error-msg)) + (insert "\nLast svn commands:\n") + (svn-insert-indented-lines (svn-status-last-commands)) + (insert (format "\nContent of the <%s> buffer:\n" last-output-buffer-name)) + (svn-insert-indented-lines last-svn-cmd-output) + (goto-char (point-min)))) + +;; -------------------------------------------------------------------------------- +;; Make it easier to reload psvn, if a distribution has an older version +;; Just add the following to your .emacs: +;; (svn-prepare-for-reload) +;; (load "/path/to/psvn.el") + +;; Note the above will only work, if the loaded psvn.el has already the +;; function svn-prepare-for-reload +;; If this is not the case, do the following: +;; (load "/path/to/psvn.el");;make svn-prepare-for-reload available +;; (svn-prepare-for-reload) +;; (load "/path/to/psvn.el");; update the keybindings +;; -------------------------------------------------------------------------------- + +(defvar svn-prepare-for-reload-dont-touch-list '() "A list of variables that should not be touched by `svn-prepare-for-reload'") +(defvar svn-prepare-for-reload-variables-list '(svn-global-keymap svn-status-diff-mode-map svn-global-trac-map svn-status-mode-map + svn-status-mode-property-map svn-status-mode-extension-map + svn-status-mode-options-map svn-status-mode-trac-map svn-status-mode-branch-map + svn-log-edit-mode-map svn-log-view-mode-map + svn-log-view-popup-menu-map svn-info-mode-map svn-blame-mode-map svn-process-mode-map) + "A list of variables that should be set to nil via M-x `svn-prepare-for-reload'") +(defun svn-prepare-for-reload () + "This function resets some psvn.el variables to nil. +It makes reloading a newer version of psvn.el easier, if for example the used +GNU/Linux distribution uses an older version. + +The variables specified in `svn-prepare-for-reload-variables-list' will be reseted by this function. + +A variable will keep its value, if it is specified in `svn-prepare-for-reload-dont-touch-list'." + (interactive) + (dolist (var svn-prepare-for-reload-variables-list) + (unless (member var svn-prepare-for-reload-dont-touch-list) + (message (format "Resetting value of %s to nil" var))) + (set var nil))) + +(provide 'psvn) + +;; Local Variables: +;; indent-tabs-mode: nil +;; time-stamp-pattern: "300/(defconst svn-psvn-revision \"%:y-%02m-%02d, %02H:%02M:%02S\" \"The revision date of psvn.\")$" +;; End: +;;; psvn.el ends here diff --git a/pullrev.sh b/pullrev.sh new file mode 100755 index 0000000..7bf46f7 --- /dev/null +++ b/pullrev.sh @@ -0,0 +1,53 @@ +#!/bin/sh -e + +if [ $# -lt 1 ]; then + echo "What?" + exit 1 +fi + +repo="https://svn.apache.org/repos/asf/subversion/trunk" +#repo="https://svn.apache.org/repos/asf/subversion/branches/1.11.x" +prefix=`rpmspec -q --queryformat='%{name}-%{version}\n' ./subversion.spec | sed 1q` +suffix="r$1${2:++}" +fn="${prefix}-${suffix}.patch" +vcurl="http://svn.apache.org/viewvc?view=revision&revision=" + +if test -f ${fn}; then + mv -v -f ${fn} ${fn}\~ + echo "# $0 $*" > ${fn} + sed '1{/#.*pullrev/d;};/^--- /,$d' < ${fn}\~ >> ${fn} +else + echo "# $0 $*" > ${fn} +fi + +new=0 +for r in $*; do + if ! grep -q "${vcurl}${r}" ${fn}; then + echo "${vcurl}${r}" + new=1 + fi +done >> ${fn} + +[ $new -eq 0 ] || echo >> ${fn} + +prev=/dev/null +for r in $*; do + echo "+ fetching ${r}" + this=`mktemp /tmp/pullrevXXXXXX` + svn diff -c ${r} ${repo} | filterdiff --remove-timestamps --clean -x 'CHANGES' -x 'next-number' -x 'STATUS' \ + --addprefix="${prefix}/" > ${this} + next=`mktemp /tmp/pullrevXXXXXX` + combinediff --quiet ${prev} ${this} > ${next} + rm -f "${this}" + [ "${prev}" = "/dev/null" ] || rm -f "${prev}" + prev=${next} +done + +cat ${prev} >> ${fn} + +vi "${fn}" +echo "+ git add ${fn}" +git add "${fn}" +echo "+ spec template:" +echo "PatchN: ${fn}" +echo "%patchN -p1 -b .${suffix}" diff --git a/sources b/sources new file mode 100644 index 0000000..e8b655c --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA1 (subversion-1.14.1.tar.bz2) = ee4283c21b5925ee499f8cb9cb0ff546ac7b4b9a diff --git a/subversion-1.12.0-linking.patch b/subversion-1.12.0-linking.patch new file mode 100644 index 0000000..f3dcacc --- /dev/null +++ b/subversion-1.12.0-linking.patch @@ -0,0 +1,84 @@ + +Fix the way libtool is used to match standard practice: + +a) link ONLY libraries using -rpath $(libdir), not executables + .. this avoids adding an RPATH for $libdir to executables +b) link non-installable test binaries using -no-install + .. only for convenience but should speed up builds slightly(?) + +--- subversion-1.12.0/build.conf.linking ++++ subversion-1.12.0/build.conf +@@ -572,7 +572,7 @@ + path = subversion/bindings/swig/python/libsvn_swig_py + libs = libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_subr + apriconv apr python swig +-link-cmd = $(LINK) ++link-cmd = $(LINK_LIB) + install = swig-py-lib + # need special build rule to include -DSWIGPYTHON + compile-cmd = $(COMPILE_SWIG_PY) +@@ -598,7 +598,7 @@ + lang = ruby + path = subversion/bindings/swig/ruby/libsvn_swig_ruby + libs = libsvn_client libsvn_wc libsvn_delta libsvn_subr apriconv apr ruby swig +-link-cmd = $(LINK) $(SWIG_RB_LIBS) ++link-cmd = $(LINK_LIB) $(SWIG_RB_LIBS) + install = swig-rb-lib + # need special build rule to include + compile-cmd = $(COMPILE_SWIG_RB) +@@ -769,6 +769,7 @@ + libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr aprutil apriconv apr + msvc-static = yes + undefined-lib-symbols = yes ++link-cmd = $(LINK_TEST_LIB) + + # ---------------------------------------------------------------------------- + # Tests for libsvn_fs_base +--- subversion-1.12.0/build/generator/gen_base.py.linking ++++ subversion-1.12.0/build/generator/gen_base.py +@@ -599,7 +599,7 @@ + self.install = options.get('install') + self.compile_cmd = options.get('compile-cmd') + self.sources = options.get('sources', '*.c *.cpp') +- self.link_cmd = options.get('link-cmd', '$(LINK)') ++ self.link_cmd = options.get('link-cmd', '$(LINK_LIB)') + + self.external_lib = options.get('external-lib') + self.external_project = options.get('external-project') +@@ -659,6 +659,14 @@ + + self.msvc_force_static = options.get('msvc-force-static') == 'yes' + ++ if self.install in ['test', 'bdb-test', 'sub-test', ]: ++ self.link_cmd = '$(LINK_TEST)' ++ elif self.install in ['bin', 'tools']: ++ self.link_cmd = '$(LINK_EXE)' ++ elif self.link_cmd == '$(LINK_LIB)': ++ raise GenError('ERROR: Unknown executable link type for ' + self.name + \ ++ ': ' + self.link_cmd + ' (' + self.install + ')') ++ + def add_dependencies(self): + TargetLinked.add_dependencies(self) + +--- subversion-1.12.0/Makefile.in.linking ++++ subversion-1.12.0/Makefile.in +@@ -268,11 +268,14 @@ + COMPILE_SVNXX = $(LT_COMPILE_CXX) $(SVNXX_INCLUDES) -o $@ -c + COMPILE_SVNXX_TEST = $(LT_COMPILE_CXX) $(SVNXX_INCLUDES) $(BOOST_TEST_CPPFLAGS) -o $@ -c + +-LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(libdir) +-LINK_LIB = $(LINK) $(LT_SO_VERSION) +-LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS) $(LDFLAGS) -rpath $(libdir) +-LINK_CXX_LIB = $(LINK_CXX) $(LT_SO_VERSION) +-LINK_SVNXX_TEST = $(LINK_CXX) $(BOOST_TEST_LDFLAGS) ++LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) ++LINK_LIB = $(LINK) $(LT_SO_VERSION) -rpath $(libdir) ++LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS) $(LDFLAGS) ++LINK_CXX_LIB = $(LINK_CXX) $(LT_SO_VERSION) -rpath $(libdir) ++LINK_SVNXX_TEST = $(LINK_CXX) $(BOOST_TEST_LDFLAGS) -no-install ++LINK_TEST = $(LINK) -no-install ++LINK_TEST_LIB = $(LINK_TEST) -avoid-version ++LINK_EXE = $(LINK) + + # special link rule for mod_dav_svn + LINK_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(APACHE_LIBEXECDIR) -avoid-version -module $(APACHE_LDFLAGS) -shared diff --git a/subversion-1.14.0-findpy.patch b/subversion-1.14.0-findpy.patch new file mode 100644 index 0000000..d0908e9 --- /dev/null +++ b/subversion-1.14.0-findpy.patch @@ -0,0 +1,11 @@ +--- subversion-1.14.0/build/find_python.sh.findpy ++++ subversion-1.14.0/build/find_python.sh +@@ -26,7 +26,7 @@ + for pypath in "$PYTHON" "$PYTHON2" "$PYTHON3" python python2 python3; do + if [ "x$pypath" != "x" ]; then + DETECT_PYTHON="import sys;sys.exit((sys.hexversion < $VERSION) and 1 or 0)" +- if "$pypath" -c "$DETECT_PYTHON" >/dev/null 2>/dev/null; then ++ if "$pypath" -c "$DETECT_PYTHON"; then + echo $pypath + exit 0 + fi diff --git a/subversion-1.14.0-soversion.patch b/subversion-1.14.0-soversion.patch new file mode 100644 index 0000000..02fe0b4 --- /dev/null +++ b/subversion-1.14.0-soversion.patch @@ -0,0 +1,19 @@ + +Use the minor version as the revision in the libtool version, so the library +soversion is not always 0.0.0. (Does not influence the soname) + +--- subversion-1.14.0/configure.ac.soversion ++++ subversion-1.14.0/configure.ac +@@ -112,7 +112,11 @@ + SVN_APR_MAJOR_VERSION=1 + fi + AC_SUBST(SVN_APR_MAJOR_VERSION) +-SVN_LT_SOVERSION="-version-info $svn_lib_ver" ++ ++m4_define([svn_ver_minor], m4_bpatsubst(AC_PACKAGE_VERSION, [[0-9]*\.\([0-9]*\)\.[0-9]*], [\1])) ++ ++SVN_LT_SOVERSION="-version-info $svn_lib_ver:svn_ver_minor" ++AC_MSG_NOTICE([SVN_LT_SOVERSION $SVN_LT_SOVERSION]) + AC_SUBST(SVN_LT_SOVERSION) + AC_DEFINE_UNQUOTED(SVN_SOVERSION, $svn_lib_ver, + [Subversion library major verson]) diff --git a/subversion-1.14.0-testwarn.patch b/subversion-1.14.0-testwarn.patch new file mode 100644 index 0000000..29f08ed --- /dev/null +++ b/subversion-1.14.0-testwarn.patch @@ -0,0 +1,14 @@ + +Suppress gcc 10 warning. + +--- subversion-1.14.0/subversion/tests/svn_test.h.testwarn ++++ subversion-1.14.0/subversion/tests/svn_test.h +@@ -128,7 +128,7 @@ + return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, \ + "Strings not equal\n Expected: '%s'\n Found: '%s'" \ + "\n at %s:%d", \ +- tst_str2, tst_str1, __FILE__, __LINE__); \ ++ tst_str2 ? tst_str2 : "(NULL)", tst_str1 ? tst_str1 : "(NULL)", __FILE__, __LINE__); \ + } while(0) + + /** Handy macro for testing integer equality. diff --git a/subversion-1.14.1-CVE-2022-24070.patch b/subversion-1.14.1-CVE-2022-24070.patch new file mode 100644 index 0000000..e13af5e --- /dev/null +++ b/subversion-1.14.1-CVE-2022-24070.patch @@ -0,0 +1,41 @@ +--- subversion-1.14.1/subversion/libsvn_repos/authz.c ++++ subversion-1.14.1/subversion/libsvn_repos/authz.c +@@ -130,6 +130,30 @@ + static svn_object_pool__t *filtered_pool = NULL; + static svn_atomic_t authz_pool_initialized = FALSE; + ++/* ++ * Ensure that we will initialize authz again if the pool which ++ * our authz caches depend on is cleared. ++ * ++ * HTTPD may run pre/post config hooks multiple times and clear ++ * its global configuration pool which our authz pools depend on. ++ * This happens in a non-threaded context during HTTPD's intialization ++ * and HTTPD's main loop, so it is safe to reset static variables here. ++ * (And any applications which cleared this pool while SVN threads ++ * were running would crash no matter what.) ++ * ++ * See issue #4880, "Use-after-free of object-pools in ++ * subversion/libsvn_repos/authz.c when used as httpd module" ++ */ ++static apr_status_t ++deinit_authz(void *data) ++{ ++ /* The two object pools run their own cleanup handlers. */ ++ authz_pool = NULL; ++ filtered_pool = NULL; ++ authz_pool_initialized = FALSE; ++ return APR_SUCCESS; ++} ++ + /* Implements svn_atomic__err_init_func_t. */ + static svn_error_t * + synchronized_authz_initialize(void *baton, apr_pool_t *pool) +@@ -143,6 +167,7 @@ + SVN_ERR(svn_object_pool__create(&authz_pool, multi_threaded, pool)); + SVN_ERR(svn_object_pool__create(&filtered_pool, multi_threaded, pool)); + ++ apr_pool_cleanup_register(pool, NULL, deinit_authz, apr_pool_cleanup_null); + return SVN_NO_ERROR; + } + diff --git a/subversion-1.14.1-fixjavatests.patch b/subversion-1.14.1-fixjavatests.patch new file mode 100644 index 0000000..b7a79b0 --- /dev/null +++ b/subversion-1.14.1-fixjavatests.patch @@ -0,0 +1,30 @@ + +See upstream dev@subversion thread. Fixes intermittent failure of +javahl tests, particularly reproducible on aarch64. + +Message-ID: <11de5f5c-5059-b973-95a1-385e7913a63a@syntevo.com> +From: Alexandr Miloslavskiy + +--- subversion-1.14.1/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java.fixjavatests ++++ subversion-1.14.1/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java +@@ -4676,7 +4676,19 @@ + // RuntimeException("Test exception") is expected here + } + +- tunnelAgent.joinAndTest(); ++ // In this test, there is a race condition that sometimes results in ++ // IOException when 'WAIT_TUNNEL' tries to read from a pipe that ++ // already has its read end closed. This is not an error, but ++ // it's hard to distinguish this case from other IOException which ++ // indicate a problem. To reproduce, simply wrap this test's body in ++ // a loop. The workaround is to ignore any detected IOException. ++ // ++ // tunnelAgent.joinAndTest(); ++ try { ++ tunnelAgent.join(); ++ } catch (InterruptedException e) { ++ e.printStackTrace (); ++ } + } + + /** diff --git a/subversion-1.14.1-testnoautoprops.patch b/subversion-1.14.1-testnoautoprops.patch new file mode 100644 index 0000000..96dd59d --- /dev/null +++ b/subversion-1.14.1-testnoautoprops.patch @@ -0,0 +1,14 @@ + +Fix intermittent failures when "svn add" guesses a near-empty file is binary and hence +the output is different. + +--- subversion-1.14.1/subversion/tests/cmdline/svntest/main.py.testnoautoprops ++++ subversion-1.14.1/subversion/tests/cmdline/svntest/main.py +@@ -691,6 +691,7 @@ + + [miscellany] + interactive-conflicts = false ++enable-auto-props = no + """ + if exclusive_wc_locks: + config_contents += """ diff --git a/subversion-1.8.0-rubybind.patch b/subversion-1.8.0-rubybind.patch new file mode 100644 index 0000000..de9288a --- /dev/null +++ b/subversion-1.8.0-rubybind.patch @@ -0,0 +1,24 @@ + +Try a little harder to avoid svnserve() bind failures. + +--- subversion-1.8.0/subversion/bindings/swig/ruby/test/util.rb.rubybind ++++ subversion-1.8.0/subversion/bindings/swig/ruby/test/util.rb +@@ -39,7 +39,8 @@ module SvnTestUtil + @realm = "sample realm" + + @svnserve_host = "127.0.0.1" +- @svnserve_ports = (64152..64282).collect{|x| x.to_s} ++ sport = (50000 + rand(100) * 100) ++ @svnserve_ports = (sport..sport + 99).collect{|x| x.to_s} + + @tmp_path = Dir.mktmpdir + @wc_path = File.join(@tmp_path, "wc") +@@ -252,6 +253,8 @@ realm = #{@realm} + "--listen-port", port, + "-d", "--foreground") + } ++ # wait a while for svnserve to attempt a bind() and possibly fail ++ sleep(1) + pid, status = Process.waitpid2(@svnserve_pid, Process::WNOHANG) + if status and status.exited? + if $DEBUG diff --git a/subversion-1.8.5-swigplWall.patch b/subversion-1.8.5-swigplWall.patch new file mode 100644 index 0000000..af66806 --- /dev/null +++ b/subversion-1.8.5-swigplWall.patch @@ -0,0 +1,16 @@ + +Don't drop -Wall in the swig Perl bindings, otherwise building with +e.g. -Wformat-security might break. + +https://bugzilla.redhat.com/show_bug.cgi?id=1037341 + +--- subversion-1.8.5/subversion/bindings/swig/perl/native/Makefile.PL.in.swigplWall ++++ subversion-1.8.5/subversion/bindings/swig/perl/native/Makefile.PL.in +@@ -54,7 +54,6 @@ my $includes = ' -I/usr/include/apr-1 + # SWIG is using C++ style comments in an extern "C" code. + $cflags =~ s/-ansi\s+//g; + $cflags =~ s/-std=c89\s+//g; +-$cflags =~ s/-Wall//g; + $cflags =~ s/-Wunused//g; + $cflags =~ s/-Wshadow//g; + $cflags =~ s/-Wstrict-prototypes//g; diff --git a/subversion.conf b/subversion.conf new file mode 100644 index 0000000..1c0f8c7 --- /dev/null +++ b/subversion.conf @@ -0,0 +1,41 @@ + +LoadModule dav_svn_module modules/mod_dav_svn.so +LoadModule authz_svn_module modules/mod_authz_svn.so +LoadModule dontdothat_module modules/mod_dontdothat.so + +# +# Example configuration to enable HTTP access for a directory +# containing Subversion repositories, "/var/www/svn". Each repository +# must be both: +# +# a) readable and writable by the 'apache' user, and +# +# b) labelled with the 'httpd_sys_content_t' context if using +# SELinux +# + +# +# To create a new repository "http://localhost/repos/stuff" using +# this configuration, run as root: +# +# # cd /var/www/svn +# # svnadmin create stuff +# # chown -R apache:apache stuff +# # chcon -R -t httpd_sys_content_t stuff +# + +# +# DAV svn +# SVNParentPath /var/www/svn +# +# # Limit write permission to list of valid users. +# +# # Require SSL connection for password protection. +# # SSLRequireSSL +# +# AuthType Basic +# AuthName "Authorization Realm" +# AuthUserFile /path/to/passwdfile +# Require valid-user +# +# diff --git a/subversion.spec b/subversion.spec new file mode 100644 index 0000000..929aab6 --- /dev/null +++ b/subversion.spec @@ -0,0 +1,1028 @@ +# set to zero to avoid running test suite + +%bcond_without kwallet +%bcond_without tests + +%if 0%{?fedora} > 32 || 0%{?rhel} > 8 +%bcond_with bdb +%else +%bcond_without bdb +%endif + +# Python 2 for F<32, Python 3 for F>=32 and RHEL>=9 +%if 0%{?fedora} < 32 && 0%{?rhel} < 9 +%bcond_without python2 +%bcond_with python3 +%bcond_without pyswig +%bcond_without ruby +%else +%bcond_with python2 +%bcond_without python3 +%bcond_without pyswig +%bcond_without ruby +%endif + +%ifarch %{power64} s390x +%global with_java 0 +%else +%global with_java 1 +%endif + +%if %{with python2} == %{with python3} +%error Pick exactly one Python version +%endif + +# set JDK path to build javahl; default for JPackage +%define jdk_path /usr/lib/jvm/java + +%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn 2>/dev/null || echo 0-0)}} + +%define perl_vendorarch %(eval "`%{__perl} -V:installvendorarch`"; echo $installvendorarch) + +%if %{with python2} +%global svn_python_sitearch %{python2_sitearch} +%global svn_python %{__python2} +%global svn_python_br python2-devel +%else +%global svn_python_sitearch %{python3_sitearch} +%global svn_python %{__python3} +%global svn_python_br python3-devel +%endif + +Summary: A Modern Concurrent Version Control System +Name: subversion +Version: 1.14.1 +Release: 2%{?dist} +License: ASL 2.0 +URL: https://subversion.apache.org/ + +Source0: https://downloads.apache.org/subversion/subversion-%{version}.tar.bz2 +Source1: subversion.conf +Source3: filter-requires.sh +Source4: http://www.xsteve.at/prg/emacs/psvn.el +Source5: psvn-init.el +Source6: svnserve.service +Source7: svnserve.tmpfiles +Source8: svnserve.sysconf +Patch1: subversion-1.12.0-linking.patch +Patch2: subversion-1.14.0-testwarn.patch +Patch3: subversion-1.14.0-soversion.patch +Patch4: subversion-1.8.0-rubybind.patch +Patch5: subversion-1.8.5-swigplWall.patch +Patch6: subversion-1.14.0-findpy.patch +Patch7: subversion-1.14.1-CVE-2022-24070.patch +Patch8: subversion-1.14.1-testnoautoprops.patch +Patch9: subversion-1.14.1-fixjavatests.patch + +BuildRequires: autoconf, libtool, texinfo, which +BuildRequires: swig >= 1.3.24, gettext +%if %{with bdb} +BuildRequires: libdb-devel >= 4.1.25 +%endif +BuildRequires: %{svn_python_br} +BuildRequires: apr-devel >= 1.3.0, apr-util-devel >= 1.3.0 +BuildRequires: libserf-devel >= 1.3.0, cyrus-sasl-devel +BuildRequires: sqlite-devel >= 3.4.0, file-devel, systemd-units +BuildRequires: utf8proc-devel, lz4-devel +# Any apr-util crypto backend needed +BuildRequires: apr-util-openssl +# For systemctl scriptlets +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +Provides: svn = %{version}-%{release} +Requires: subversion-libs%{?_isa} = %{version}-%{release} + +%define __perl_requires %{SOURCE3} + +# Put Python bindings in site-packages +%define swigdirs swig_pydir=%{svn_python_sitearch}/libsvn swig_pydir_extra=%{svn_python_sitearch}/svn + +%description +Subversion is a concurrent version control system which enables one +or more users to collaborate in developing and maintaining a +hierarchy of files and directories while keeping a history of all +changes. Subversion only stores the differences between versions, +instead of every complete file. Subversion is intended to be a +compelling replacement for CVS. + +%package libs +Summary: Libraries for Subversion Version Control system +# APR 1.3.x interfaces are required +Conflicts: apr%{?_isa} < 1.3.0 +# Enforced at run-time by ra_serf +Conflicts: libserf%{?_isa} < 1.3.0 + +%description libs +The subversion-libs package includes the essential shared libraries +used by the Subversion version control tools. + +%if %{with python2} && %{with pyswig} +%package -n python2-subversion +%{?python_provide:%python_provide python2-subversion} +# Remove before F30 +Provides: %{name}-python = %{version}-%{release} +Provides: %{name}-python%{?_isa} = %{version}-%{release} +Obsoletes: %{name}-python < %{version}-%{release} +BuildRequires: python2-devel +Summary: Python bindings for Subversion Version Control system + +%description -n python2-subversion +The python2-subversion package includes the Python 2.x bindings to the +Subversion libraries. +%endif +%if %{with python3} && %{with pyswig} +%package -n python3-subversion +%{?python_provide:%python_provide python3-subversion} +Summary: Python bindings for Subversion Version Control system +BuildRequires: python3-devel py3c-devel +Requires: subversion-libs%{?_isa} = %{version}-%{release} + +%description -n python3-subversion +The python3-subversion package includes the Python 3.x bindings to the +Subversion libraries. +%endif + +%package devel +Summary: Development package for the Subversion libraries +Requires: subversion-libs%{?_isa} = %{version}-%{release} +Requires: apr-devel%{?_isa}, apr-util-devel%{?_isa} + +%description devel +The subversion-devel package includes the libraries and include files +for developers interacting with the subversion package. + +%package gnome +Summary: GNOME Keyring support for Subversion +Requires: subversion-libs%{?_isa} = %{version}-%{release} +BuildRequires: dbus-devel, libsecret-devel + +%description gnome +The subversion-gnome package adds support for storing Subversion +passwords in the GNOME Keyring. + +%if %{with kwallet} +%package kde +Summary: KDE Wallet support for Subversion +Requires: subversion-libs%{?_isa} = %{version}-%{release} +BuildRequires: qt5-qtbase-devel >= 5.0.0, kf5-kwallet-devel, kf5-ki18n-devel +BuildRequires: kf5-kcoreaddons-devel + +%description kde +The subversion-kde package adds support for storing Subversion +passwords in the KDE Wallet. +%endif + +%package -n mod_dav_svn +Summary: Apache httpd module for Subversion server +Requires: httpd-mmn = %{_httpd_mmn} +Requires: subversion-libs%{?_isa} = %{version}-%{release} +BuildRequires: httpd-devel >= 2.0.45 + +%description -n mod_dav_svn +The mod_dav_svn package allows access to a Subversion repository +using HTTP, via the Apache httpd server. + +%package perl +Summary: Perl bindings to the Subversion libraries +BuildRequires: perl-devel >= 2:5.8.0, perl-generators, perl(ExtUtils::MakeMaker) +BuildRequires: perl(Test::More), perl(ExtUtils::Embed) +Requires: %(eval `perl -V:version`; echo "perl(:MODULE_COMPAT_$version)") +Requires: subversion-libs%{?_isa} = %{version}-%{release} + +%description perl +This package includes the Perl bindings to the Subversion libraries. + +%if %{with_java} +%package javahl +Summary: JNI bindings to the Subversion libraries +Requires: subversion = %{version}-%{release} +BuildRequires: java-11-openjdk-devel +# JAR repacking requires both zip and unzip in the buildroot +BuildRequires: zip, unzip +# For the tests +BuildRequires: junit +BuildArch: noarch + +%description javahl +This package includes the JNI bindings to the Subversion libraries. +%endif + +%if %{with ruby} +%package ruby +Summary: Ruby bindings to the Subversion libraries +BuildRequires: ruby-devel >= 1.9.1, ruby >= 1.9.1 +BuildRequires: rubygem(test-unit) +Requires: subversion-libs%{?_isa} = %{version}-%{release} +Conflicts: ruby-libs%{?_isa} < 1.8.2 + +%description ruby +This package includes the Ruby bindings to the Subversion libraries. +%endif + +%package tools +Summary: Supplementary tools for Subversion +Requires: subversion-libs%{?_isa} = %{version}-%{release} + +%description tools +This package includes supplementary tools for use with Subversion. + +%prep +%setup -q +%patch1 -p1 -b .linking +%patch2 -p1 -b .testwarn +%patch3 -p1 -b .soversion +%patch4 -p1 -b .rubybind +%patch5 -p1 -b .swigplWall +%patch6 -p1 -b .findpy +%patch7 -p1 -b .cve24070 +%patch8 -p1 -b .testnoautoprops +%patch9 -p1 -b .fixjavatests + + +: +: === Building: +: === Python3=%{with python3} Python2=%{with python2} PySwig=%{with pyswig} +: === Java=%{with_java} Ruby=%{with ruby} +: === BDB=%{with bdb} Tests=%{with tests} KWallet=%{with kwallet} +: + +%build +# Regenerate the buildsystem, so that any patches applied to +# configure, swig bindings etc take effect. +mv build-outputs.mk build-outputs.mk.old +export PYTHON=%{svn_python} + +### Force regeneration of swig bindings with the buildroot's SWIG. +# Generated files depend on the build/generator/swig/*.py which +# generates them, so when autogen-standalone.mk's autogen-swig target +# is run by autogen.sh it will regenerate them: +touch build/generator/swig/*.py + +### Regenerate everything: +# This PATH order makes the fugly test for libtoolize work... +PATH=/usr/bin:$PATH ./autogen.sh --release + +# fix shebang lines, #111498 +perl -pi -e 's|/usr/bin/env perl -w|/usr/bin/perl -w|' tools/hook-scripts/*.pl.in +# fix python executable +perl -pi -e 's|/usr/bin/env python.*|%{svn_python}|' subversion/tests/cmdline/svneditor.py + +# override weird -shrext from ruby +export svn_cv_ruby_link="%{__cc} -shared" +export svn_cv_ruby_sitedir_libsuffix="" +export svn_cv_ruby_sitedir_archsuffix="" +%if 0%{?fedora} >= 32 || 0%{?rhel} >= 9 +# Fix include path for ruby2.7 +export svn_cv_ruby_includes="-I%{_includedir}" +%endif + +#export EXTRA_CFLAGS="$RPM_OPT_FLAGS -DSVN_SQLITE_MIN_VERSION_NUMBER=3007012 \ +# -DSVN_SQLITE_MIN_VERSION=\\\"3.7.12\\\"" +export APACHE_LDFLAGS="-Wl,-z,relro,-z,now" +export CC=gcc CXX=g++ JAVA_HOME=%{jdk_path} + +%configure --with-apr=%{_prefix} --with-apr-util=%{_prefix} \ + --disable-debug \ + --with-swig --with-serf=%{_prefix} \ + --with-ruby-sitedir=%{ruby_vendorarchdir} \ + --with-ruby-test-verbose=verbose \ + --with-apxs=%{_httpd_apxs} --disable-mod-activation \ + --with-apache-libexecdir=%{_httpd_moddir} \ + --disable-static --with-sasl=%{_prefix} \ + --with-libmagic=%{_prefix} \ + --with-gnome-keyring \ +%if %{with_java} + --enable-javahl \ + --with-junit=%{_prefix}/share/java/junit.jar \ +%endif +%if %{with kwallet} + --with-kwallet=%{_includedir}:%{_libdir} \ +%endif + --enable-plaintext-password-storage \ +%if %{with bdb} + --with-berkeley-db \ +%else + --without-berkeley-db \ +%endif + || (cat config.log; exit 1) +make %{?_smp_mflags} all tools +%if %{with pyswig} +make swig-py swig-py-lib %{swigdirs} +%endif +make swig-pl swig-pl-lib +%if %{with ruby} +make swig-rb swig-rb-lib +%endif +%if %{with_java} +# javahl-javah does not parallel-make with javahl +#make javahl-java javahl-javah +make javahl +%endif + +%install +make install DESTDIR=$RPM_BUILD_ROOT +%if %{with pyswig} +make install-swig-py %{swigdirs} DESTDIR=$RPM_BUILD_ROOT +%endif +make install-swig-pl-lib install-swig-rb DESTDIR=$RPM_BUILD_ROOT +make pure_vendor_install -C subversion/bindings/swig/perl/native \ + PERL_INSTALL_ROOT=$RPM_BUILD_ROOT +%if %{with_java} +make install-javahl-java install-javahl-lib javahl_javadir=%{_javadir} DESTDIR=$RPM_BUILD_ROOT +%endif + +install -m 755 -d ${RPM_BUILD_ROOT}%{_sysconfdir}/subversion + +mkdir -p ${RPM_BUILD_ROOT}{%{_httpd_modconfdir},%{_httpd_confdir}} + +%if "%{_httpd_modconfdir}" == "%{_httpd_confdir}" +# httpd <= 2.2.x +install -p -m 644 %{SOURCE1} ${RPM_BUILD_ROOT}%{_httpd_confdir} +%else +sed -n /^LoadModule/p %{SOURCE1} > 10-subversion.conf +sed /^LoadModule/d %{SOURCE1} > example.conf +touch -r %{SOURCE1} 10-subversion.conf example.conf +install -p -m 644 10-subversion.conf ${RPM_BUILD_ROOT}%{_httpd_modconfdir} +%endif + +# Remove unpackaged files +rm -rf ${RPM_BUILD_ROOT}%{_includedir}/subversion-*/*.txt \ + ${RPM_BUILD_ROOT}%{svn_python_sitearch}/*/*.{a,la} + +# The SVN build system is broken w.r.t. DSO support; it treats +# normal libraries as DSOs and puts them in $libdir, whereas they +# should go in some subdir somewhere, and be linked using -module, +# etc. So, forcibly nuke the .so's for libsvn_auth_{gnome,kde}, +# since nothing should ever link against them directly. +rm -f ${RPM_BUILD_ROOT}%{_libdir}/libsvn_auth_*.so + +# remove stuff produced with Perl modules +find $RPM_BUILD_ROOT -type f \ + -a \( -name .packlist -o \( -name '*.bs' -a -empty \) \) \ + -print0 | xargs -0 rm -f + +# make Perl modules writable so they get stripped +find $RPM_BUILD_ROOT%{_libdir}/perl5 -type f -perm 555 -print0 | + xargs -0 chmod 755 + +# unnecessary libraries for swig bindings +rm -f ${RPM_BUILD_ROOT}%{_libdir}/libsvn_swig_*.{so,la,a} + +# Remove unnecessary ruby libraries +rm -f ${RPM_BUILD_ROOT}%{ruby_vendorarchdir}/svn/ext/*.*a + +# Trim what goes in docdir +rm -rvf tools/*/*.in tools/hook-scripts/mailer/tests + +# Install psvn for emacs and xemacs +for f in emacs/site-lisp xemacs/site-packages/lisp; do + install -m 755 -d ${RPM_BUILD_ROOT}%{_datadir}/$f + install -m 644 $RPM_SOURCE_DIR/psvn.el ${RPM_BUILD_ROOT}%{_datadir}/$f +done + +install -m 644 $RPM_SOURCE_DIR/psvn-init.el \ + ${RPM_BUILD_ROOT}%{_datadir}/emacs/site-lisp + +# Rename authz_svn INSTALL doc for docdir +ln -f subversion/mod_authz_svn/INSTALL mod_authz_svn-INSTALL + +# Trim exported dependencies to APR libraries only: +sed -i "/^dependency_libs/{ + s, -l[^ ']*, ,g; + s, -L[^ ']*, ,g; + s,%{_libdir}/lib[^a][^p][^r][^ ']*.la, ,g; + }" $RPM_BUILD_ROOT%{_libdir}/*.la + +# Trim libdir in pkgconfig files to avoid multilib conflicts +sed -i '/^libdir=/d' $RPM_BUILD_ROOT%{_datadir}/pkgconfig/libsvn*.pc + +# Install bash completion +install -Dpm 644 tools/client-side/bash_completion \ + $RPM_BUILD_ROOT%{_datadir}/bash-completion/completions/svn +for comp in svnadmin svndumpfilter svnlook svnsync svnversion; do + ln -s svn \ + $RPM_BUILD_ROOT%{_datadir}/bash-completion/completions/${comp} +done + +# Install svnserve bits +mkdir -p %{buildroot}%{_unitdir} \ + %{buildroot}/run/svnserve \ + %{buildroot}%{_prefix}/lib/tmpfiles.d \ + %{buildroot}%{_sysconfdir}/sysconfig + +install -p -m 644 $RPM_SOURCE_DIR/svnserve.service \ + %{buildroot}%{_unitdir}/svnserve.service +install -p -m 644 $RPM_SOURCE_DIR/svnserve.tmpfiles \ + %{buildroot}%{_prefix}/lib/tmpfiles.d/svnserve.conf +install -p -m 644 $RPM_SOURCE_DIR/svnserve.sysconf \ + %{buildroot}%{_sysconfdir}/sysconfig/svnserve + +# Install tools ex diff*, x509-parser +make install-tools DESTDIR=$RPM_BUILD_ROOT toolsdir=%{_bindir} +rm -f $RPM_BUILD_ROOT%{_bindir}/diff* $RPM_BUILD_ROOT%{_bindir}/x509-parser + +# Don't add spurious dependency in libserf-devel +sed -i "/^Requires.private/s, serf-1, ," \ + $RPM_BUILD_ROOT%{_datadir}/pkgconfig/libsvn_ra_serf.pc + +# Make svnauthz-validate a symlink +rm $RPM_BUILD_ROOT%{_bindir}/svnauthz-validate +ln -s svnauthz $RPM_BUILD_ROOT%{_bindir}/svnauthz-validate + +for f in svn-populate-node-origins-index fsfs-access-map \ + svnauthz svnauthz-validate svnmucc svnraisetreeconflict svnbench \ + svn-mergeinfo-normalizer fsfs-stats svnmover svnconflict; do + echo %{_bindir}/$f + if test -f $RPM_BUILD_ROOT%{_mandir}/man?/${f}.*; then + echo %{_mandir}/man?/${f}.* + fi +done | tee tools.files | sed 's/^/%%exclude /' > exclude.tools.files + +%find_lang %{name} + +cat %{name}.lang exclude.tools.files >> %{name}.files + +%if %{with tests} +%check +export LANG=C LC_ALL=C +export LD_LIBRARY_PATH=$RPM_BUILD_ROOT%{_libdir} +export MALLOC_PERTURB_=171 MALLOC_CHECK_=3 +export LIBC_FATAL_STDERR_=1 +export PYTHON=%{svn_python} +if ! make check CLEANUP=yes; then + : Test suite failure. + cat fails.log + exit 1 +fi +if ! make check-swig-pl check-swig-rb; then + : Swig test failure. + exit 1 +fi +%if %{with pyswig} +if ! make check-swig-py; then + : Python swig test failure. + exit 1 +fi +%endif +# check-swig-rb omitted: it runs svnserve +%if %{with_java} +make check-javahl +%endif +%endif + +%post +%systemd_post svnserve.service + +%preun +%systemd_preun svnserve.service + +%postun +%systemd_postun_with_restart svnserve.service + +%ldconfig_scriptlets libs + +%ldconfig_scriptlets perl + +%ldconfig_scriptlets ruby + +%if %{with_java} +%ldconfig_scriptlets javahl +%endif + +%files -f %{name}.files +%{!?_licensedir:%global license %%doc} +%license LICENSE NOTICE +%doc BUGS COMMITTERS INSTALL README CHANGES +%doc mod_authz_svn-INSTALL +%{_bindir}/* +%{_mandir}/man*/* +%{_datadir}/emacs/site-lisp/*.el +%{_datadir}/xemacs/site-packages/lisp/*.el +%{_datadir}/bash-completion/ +%config(noreplace) %{_sysconfdir}/sysconfig/svnserve +%dir %{_sysconfdir}/subversion +%exclude %{_mandir}/man*/*::* +%{_unitdir}/*.service +%attr(0700,root,root) %dir /run/svnserve +%{_prefix}/lib/tmpfiles.d/svnserve.conf + +%files tools -f tools.files +%doc tools/hook-scripts tools/backup tools/examples tools/xslt +%if %{with bdb} +%doc tools/bdb +%endif + +%files libs +%{!?_licensedir:%global license %%doc} +%license LICENSE NOTICE +%{_libdir}/libsvn*.so.* +%exclude %{_libdir}/libsvn_swig_perl* +%exclude %{_libdir}/libsvn_swig_ruby* +%if %{with_java} +%{_libdir}/libsvnjavahl-*.so +%endif +%if %{with kwallet} +%exclude %{_libdir}/libsvn_auth_kwallet* +%endif +%exclude %{_libdir}/libsvn_auth_gnome* + +%if %{with python2} && %{with pyswig} +%files -n python2-subversion +%{python2_sitearch}/svn +%{python2_sitearch}/libsvn +%endif + +%if %{with python3} && %{with pyswig} +%files -n python3-subversion +%{python3_sitearch}/svn +%{python3_sitearch}/libsvn +%endif + +%files gnome +%{_libdir}/libsvn_auth_gnome_keyring-*.so.* + +%if %{with kwallet} +%files kde +%{_libdir}/libsvn_auth_kwallet-*.so.* +%endif + +%files devel +%{_includedir}/subversion-1 +%{_libdir}/libsvn*.*a +%{_libdir}/libsvn*.so +%{_datadir}/pkgconfig/*.pc +%exclude %{_libdir}/libsvn_swig_perl* +%exclude %{_libdir}/libsvnjavahl-*.so + +%files -n mod_dav_svn +%config(noreplace) %{_httpd_modconfdir}/*.conf +%{_libdir}/httpd/modules/mod_*.so +%if "%{_httpd_modconfdir}" != "%{_httpd_confdir}" +%doc example.conf +%endif + +%files perl +%{perl_vendorarch}/auto/SVN +%{perl_vendorarch}/SVN +%{_libdir}/libsvn_swig_perl* +%{_mandir}/man*/*::* + +%if %{with ruby} +%files ruby +%{_libdir}/libsvn_swig_ruby* +%{ruby_vendorarchdir}/svn +%endif + +%if %{with_java} +%files javahl +%{_javadir}/svn-javahl.jar +%endif + +%changelog +* Mon May 09 2022 Richard Lescak - 1.14.1-2 +- add fix for CVE-2022-24070 + +* Wed Feb 10 2021 Joe Orton - 1.14.1-1 +- update to 1.14.1 for CVE-2020-17525 (#1923928) + +* Fri Dec 11 2020 Joe Orton - 1.14.0-8 +- strip libdir from pkgconfig files (#1844947) +- add missing -libs dep from python3-subversion + +* Fri Dec 11 2020 Joe Orton - 1.14.0-7 +- enable plaintext password storage (#1844947) + +* Sat Aug 01 2020 Fedora Release Engineering - 1.14.0-6 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Wed Jul 29 2020 Fedora Release Engineering - 1.14.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jun 23 2020 Jitka Plesnikova - 1.14.0-4 +- Perl 5.32 rebuild + +* Wed Jun 3 2020 Merlin Mathesius - 1.14.0-3 +- Minor conditional fixes for ELN + +* Wed Jun 3 2020 Joe Orton - 1.14.0-2 +- use minor version as libtool library revision number + +* Mon Jun 1 2020 Joe Orton - 1.14.0-1 +- update to 1.14.0 (#1840565, #1812195) + +* Tue May 19 2020 Joe Orton - 1.14.0~rc2-2 +- switch subpackages to lock-step requires on -libs rather than subversion +- fixed the build-requires (Jitka Plesnikova) + +* Thu Apr 30 2020 Joe Orton - 1.14.0~rc2-1 +- drop Berkeley DB support for Fedora > 32 +- BR java-11-openjdk-devel + +* Thu Apr 23 2020 Joe Orton - 1.14.0~rc2-0 +- update to 1.14.0-rc2 + +* Wed Feb 12 2020 Joe Orton - 1.13.0-4 +- fix FTBFS on 32-bit arches (#1800120) +- conditionally package bdb tools in -tools + +* Fri Jan 31 2020 Fedora Release Engineering - 1.12.2-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Tue Jan 21 2020 Mamoru TASAKA - 1.12.2-4 +- F-32: fix include path for ruby 2.7 +- Rebuild for ruby 2.7 + +* Mon Jan 6 2020 Joe Orton - 1.12.2-3 +- update for KDE 5 (Phil O, #1768693) + +* Fri Aug 30 2019 Joe Orton - 1.12.2-2 +- switch to Python 3 for F32+ (#1737928) + +* Thu Jul 25 2019 Joe Orton - 1.12.2-1 +- update to 1.12.2 + +* Sat Jun 01 2019 Jitka Plesnikova - 1.12.0-2 +- Perl 5.30 rebuild + +* Wed May 1 2019 Joe Orton - 1.12.0-1 +- update to 1.12.0 (#1702471) + +* Wed Apr 17 2019 Joe Orton - 1.11.1-5 +- fix build with APR 1.7.0 (upstream r1857391) + +* Sun Feb 03 2019 Fedora Release Engineering - 1.11.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 21 2019 Mamoru TASAKA - 1.11.1-3 +- F-30: rebuild against ruby26 + +* Mon Jan 14 2019 Björn Esser - 1.11.1-2 +- Rebuilt for libcrypt.so.2 (#1666033) + +* Fri Jan 11 2019 Joe Orton - 1.11.1-1 +- update to 1.11.1 + +* Wed Oct 31 2018 Joe Orton - 1.11.0-1 +- update to 1.11.0 + +* Thu Oct 11 2018 Joe Orton - 1.10.3-1 +- update to 1.10.3 + +* Fri Jul 20 2018 Joe Orton - 1.10.2-1 +- update to 1.10.2 (#1603197) + +* Sat Jul 14 2018 Fedora Release Engineering - 1.10.0-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Jun 29 2018 Jitka Plesnikova - 1.10.0-9 +- Perl 5.28 rebuild + +* Thu Jun 28 2018 Joe Orton - 1.10.0-8 +- fix test suite invocation + +* Thu Jun 28 2018 Joe Orton - 1.10.0-7 +- switch build conditional to disable only python bindings + +* Thu May 3 2018 Joe Orton - 1.10.0-6 +- really disable Berkeley DB support if required by bcond +- add build conditional to disable swig binding subpackages + +* Tue May 1 2018 Joe Orton - 1.10.0-5 +- remove build and -devel deps on libgnome-keyring-devel + +* Tue May 1 2018 Joe Orton - 1.10.0-4 +- drop -devel dep on libserf-devel + +* Tue Apr 24 2018 Joe Orton - 1.10.0-3 +- add bdb, tests as build conditional + +* Tue Apr 17 2018 Joe Orton - 1.10.0-2 +- move new tools to -tools + +* Mon Apr 16 2018 Joe Orton - 1.10.0-1 +- update to 1.10.0 (#1566493) + +* Tue Mar 27 2018 Joe Orton - 1.9.7-7 +- add build conditionals for python2, python3 and kwallet + +* Thu Feb 8 2018 Joe Orton - 1.9.7-6 +- force use of Python2 in test suite + +* Thu Feb 01 2018 Iryna Shcherbina - 1.9.7-5 +- Update Python 2 dependency declarations to new packaging standards + (See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3) + +* Sat Jan 20 2018 Björn Esser - 1.9.7-4 +- Rebuilt for switch to libxcrypt + +* Fri Jan 05 2018 Mamoru TASAKA - 1.9.7-3 +- F-28: rebuild for ruby25 + +* Sun Dec 17 2017 Zbigniew Jędrzejewski-Szmek - 1.9.7-2 +- Python 2 binary package renamed to python2-subversion + See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3 + +* Fri Aug 11 2017 Joe Orton - 1.9.7-1 +- update to 1.9.7 (CVE-2017-9800, #1480402) +- add Documentation= to svnserve.service + +* Thu Aug 03 2017 Fedora Release Engineering - 1.9.6-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 1.9.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Jul 17 2017 Joe Orton - 1.9.6-2 +- move javahl .so to -libs (#1469158) + +* Thu Jul 6 2017 Joe Orton - 1.9.6-1 +- update to 1.9.6 (#1467890) +- update to latest upstream psvn.el +- move libsvnjavahl to -libs, build -javahl noarch +- fix javahl Requires + +* Sun Jun 04 2017 Jitka Plesnikova - 1.9.5-4 +- Perl 5.26 rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 1.9.5-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri Jan 13 2017 Mamoru TASAKA - 1.9.5-2 +- F-26: rebuild for ruby24 + +* Mon Jan 2 2017 Joe Orton - 1.9.5-1 +- update to 1.9.5 (#1400040, CVE-2016-8734) + +* Tue Jul 19 2016 Fedora Release Engineering - 1.9.4-4 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Wed May 25 2016 Jitka Plesnikova - 1.9.4-3 +- Enable tests +- Revert one of Ruby 2.2 fixes + +* Tue May 17 2016 Jitka Plesnikova - 1.9.4-2 +- Perl 5.24 rebuild + +* Sun May 8 2016 Peter Robinson 1.9.4-1 +- Update to 1.9.4 (#1331222) CVE-2016-2167 CVE-2016-2168 +- Move tools in docs to tools subpackage (rhbz 1171757 1199761) +- Disable make check to work around FTBFS + +* Fri Feb 05 2016 Fedora Release Engineering - 1.9.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jan 21 2016 Joe Orton - 1.9.3-2 +- rebuild for Ruby 2.3 + +* Tue Dec 15 2015 Joe Orton - 1.9.3-1 +- update to 1.9.3 (#1291683) +- use private /tmp in svnserve.service + +* Thu Sep 24 2015 Joe Orton - 1.9.2-1 +- update to 1.9.2 (#1265447) + +* Mon Sep 14 2015 Joe Orton - 1.9.1-1 +- update to 1.9.1 (#1259099) + +* Mon Aug 24 2015 Joe Orton - 1.9.0-1 +- update to 1.9.0 (#1207835) +- package pkgconfig files + +* Tue Jul 14 2015 Joe Orton - 1.8.13-7 +- move svnauthz to -tools; make svnauthz-validate a symlink +- move svnmucc man page to -tools +- restore dep on systemd (#1183873) + +* Fri Jul 10 2015 Joe Orton - 1.8.13-6 +- rebuild with tests enabled + +* Fri Jun 19 2015 Fedora Release Engineering - 1.8.13-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Jun 15 2015 Ville Skyttä - 1.8.13-4 +- Own bash-completion dirs not owned by anything in dep chain + +* Sat Jun 06 2015 Jitka Plesnikova - 1.8.13-3 +- Perl 5.22 rebuild + +* Tue Apr 21 2015 Peter Robinson 1.8.13-2 +- Disable tests to fix swig test issues + +* Wed Apr 08 2015 - 1.8.13-1 +- Fix Ruby's test suite. + +* Tue Apr 7 2015 Joe Orton - 1.8.13-1 +- update to 1.8.13 (#1207835) +- attempt to patch around SWIG issues + +* Tue Dec 16 2014 Joe Orton - 1.8.11-1 +- update to 1.8.11 (#1174521) +- require newer libserf (#1155670) + +* Tue Sep 23 2014 Joe Orton - 1.8.10-6 +- prevents assert()ions in library code (#1058693) + +* Tue Sep 23 2014 Joe Orton - 1.8.10-5 +- drop sysv conversion trigger (#1133786) + +* Tue Sep 23 2014 Joe Orton - 1.8.10-4 +- move svn-bench, fsfs-* to -tools + +* Tue Aug 26 2014 Jitka Plesnikova - 1.8.10-3 +- Perl 5.20 rebuild + +* Thu Aug 21 2014 Kevin Fenzi - 1.8.10-2 +- Rebuild for rpm bug 1131960 + +* Mon Aug 18 2014 Joe Orton - 1.8.10-1 +- update to 1.8.10 (#1129100, #1128884, #1125800) + +* Mon Aug 18 2014 Fedora Release Engineering - 1.8.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sun Jun 08 2014 Fedora Release Engineering - 1.8.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Wed May 28 2014 Joe Orton - 1.8.9-1 +- update to 1.8.9 (#1100779) + +* Tue Apr 29 2014 Vít Ondruch - 1.8.8-3 +- Rebuilt for https://fedoraproject.org/wiki/Changes/Ruby_2.1 + +* Tue Apr 22 2014 Joe Orton - 1.8.8-2 +- require minitest 4 to fix tests for Ruby bindings (#1089252) + +* Fri Feb 28 2014 Joe Orton - 1.8.8-1 +- update to 1.8.8 + +* Thu Jan 23 2014 Joe Orton - 1.8.5-4 +- fix _httpd_mmn expansion in absence of httpd-devel + +* Mon Jan 6 2014 Joe Orton - 1.8.5-3 +- fix permissions of /run/svnserve (#1048422) + +* Tue Dec 10 2013 Joe Orton - 1.8.5-2 +- don't drop -Wall when building swig Perl bindings (#1037341) + +* Tue Nov 26 2013 Joe Orton - 1.8.5-1 +- update to 1.8.5 (#1034130) +- add fix for wc-queries-test breakage (h/t Andreas Stieger, r1542774) + +* Mon Nov 18 2013 Joe Orton - 1.8.4-2 +- add fix for ppc breakage (Andreas Stieger, #985582) + +* Tue Oct 29 2013 Joe Orton - 1.8.4-1 +- update to 1.8.4 + +* Tue Sep 3 2013 Joe Orton - 1.8.3-1 +- update to 1.8.3 +- move bash completions out of /etc (#922993) + +* Tue Aug 06 2013 Adam Williamson - 1.8.1-2 +- rebuild for perl 5.18 (again; 1.8.1-1 beat out 1.8.0-2) + +* Thu Jul 25 2013 Joe Orton - 1.8.1-1 +- update to 1.8.1 + +* Fri Jul 19 2013 Joe Orton - 1.8.0-3 +- temporarily ignore test suite failures on ppc* (#985582) + +* Wed Jul 17 2013 Petr Pisar - 1.8.0-2 +- Perl 5.18 rebuild + +* Tue Jun 18 2013 Joe Orton - 1.8.0-1 +- update to 1.8.0; switch to serf +- use full relro in mod_dav_svn build (#973694) + +* Mon Jun 3 2013 Joe Orton - 1.7.10-1 +- update to 1.7.10 (#970014) +- fix aarch64 build issues (Dennis Gilmore, #926578) + +* Thu May 9 2013 Joe Orton - 1.7.9-3 +- fix spurious failures in ruby test suite (upstream r1327373) + +* Thu May 9 2013 Joe Orton - 1.7.9-2 +- try harder to avoid svnserve bind failures in ruby binding tests +- enable verbose output for ruby binding tests + +* Tue Apr 9 2013 Joe Orton - 1.7.9-1 +- update to 1.7.9 + +* Wed Mar 27 2013 Vít Ondruch - 1.7.8-6 +- Rebuild for https://fedoraproject.org/wiki/Features/Ruby_2.0.0 +- Drop Ruby version checks from configuration script. +- Fix and enable Ruby test suite. + +* Thu Mar 14 2013 Joe Orton - 1.7.8-5 +- drop specific dep on ruby(abi) + +* Fri Feb 15 2013 Fedora Release Engineering - 1.7.8-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Jan 8 2013 Joe Orton - 1.7.8-3 +- update to latest psvn.el + +* Tue Jan 8 2013 Lukáš Nykrýn - 1.7.8-2 +- Scriptlets replaced with new systemd macros (#850410) + +* Fri Jan 4 2013 Joe Orton - 1.7.8-1 +- update to 1.7.8 + +* Thu Oct 11 2012 Joe Orton - 1.7.7-1 +- update to 1.7.7 + +* Fri Aug 17 2012 Joe Orton - 1.7.6-1 +- update to 1.7.6 + +* Sat Jul 21 2012 Fedora Release Engineering - 1.7.5-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jul 16 2012 Joe Orton - 1.7.5-5 +- switch svnserve pidfile to use /run, use /usr/lib/tmpfiles.d (#840195) + +* Thu Jun 28 2012 Petr Pisar - 1.7.5-4 +- Perl 5.16 rebuild + +* Mon Jun 18 2012 Dan Horák - 1.7.5-2 +- Perl 5.16 rebuild + +* Tue May 22 2012 Joe Orton - 1.7.5-1 +- update to 1.7.5 + +* Tue Apr 24 2012 Joe Orton - 1.7.4-6 +- drop strict sqlite version requirement (#815396) + +* Mon Apr 23 2012 Joe Orton - 1.7.4-5 +- switch to libdb-devel (#814090) + +* Thu Apr 19 2012 Joe Orton - 1.7.4-4 +- adapt for conf.modules.d with httpd 2.4 +- add possible workaround for kwallet crasher (#810861) + +* Fri Mar 30 2012 Joe Orton - 1.7.4-3 +- re-enable test suite + +* Fri Mar 30 2012 Joe Orton - 1.7.4-2 +- fix build with httpd 2.4 + +* Mon Mar 12 2012 Joe Orton - 1.7.4-1 +- update to 1.7.4 +- fix build with httpd 2.4 + +* Thu Mar 1 2012 Joe Orton - 1.7.3-7 +- re-enable kwallet (#791031) + +* Wed Feb 29 2012 Joe Orton - 1.7.3-6 +- update psvn + +* Wed Feb 29 2012 Joe Orton - 1.7.3-5 +- add tools subpackage (#648015) + +* Tue Feb 28 2012 Joe Orton - 1.7.3-4 +- trim contents of doc dic (#746433) + +* Tue Feb 28 2012 Joe Orton - 1.7.3-3 +- re-enable test suite + +* Tue Feb 28 2012 Joe Orton - 1.7.3-2 +- add upstream test suite fixes for APR hash change (r1293602, r1293811) +- use ruby vendorlib directory (#798203) +- convert svnserve to systemd (#754074) + +* Mon Feb 13 2012 Joe Orton - 1.7.3-1 +- update to 1.7.3 +- ship, enable mod_dontdothat + +* Mon Feb 13 2012 Joe Orton - 1.7.2-2 +- require ruby 1.9.1 abi + +* Thu Feb 9 2012 Joe Orton - 1.7.2-1 +- update to 1.7.2 +- add Vincent Batts' Ruby 1.9 fixes from dev@ + +* Sun Feb 5 2012 Peter Robinson - 1.7.1-3 +- fix gnome-keyring build deps + +* Sat Jan 14 2012 Fedora Release Engineering - 1.7.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Nov 28 2011 Joe Orton - 1.7.1-1 +- update to 1.7.1 +- (temporarily) disable failing kwallet support + +* Sun Nov 27 2011 Ville Skyttä - 1.7.0-3 +- Build with libmagic support. + +* Sat Oct 15 2011 Ville Skyttä - 1.7.0-2 +- Fix apr Conflicts syntax in -libs. +- Fix obsolete chown syntax in subversion.conf. +- Fix use of spaces vs tabs in specfile. + +* Wed Oct 12 2011 Joe Orton - 1.7.0-1 +- update to 1.7.0 +- drop svn2cl (no longer shipped in upstream tarball) diff --git a/svnserve.service b/svnserve.service new file mode 100644 index 0000000..6fbbe1e --- /dev/null +++ b/svnserve.service @@ -0,0 +1,13 @@ +[Unit] +Description=Subversion protocol daemon +After=syslog.target network.target +Documentation=man:svnserve(8) + +[Service] +Type=forking +EnvironmentFile=/etc/sysconfig/svnserve +ExecStart=/usr/bin/svnserve --daemon --pid-file=/run/svnserve/svnserve.pid $OPTIONS +PrivateTmp=yes + +[Install] +WantedBy=multi-user.target diff --git a/svnserve.sysconf b/svnserve.sysconf new file mode 100644 index 0000000..647e09d --- /dev/null +++ b/svnserve.sysconf @@ -0,0 +1,4 @@ +# OPTIONS is used to pass command-line arguments to svnserve. +# +# Specify the repository location in -r parameter: +OPTIONS="-r /var/svn" diff --git a/svnserve.tmpfiles b/svnserve.tmpfiles new file mode 100644 index 0000000..e8487d3 --- /dev/null +++ b/svnserve.tmpfiles @@ -0,0 +1 @@ +D /run/svnserve 0700 root root - diff --git a/upstream b/upstream new file mode 100644 index 0000000..2b24a3b --- /dev/null +++ b/upstream @@ -0,0 +1 @@ +subversion-1.6.12.tar.bz2 diff --git a/upstream-key.gpg b/upstream-key.gpg new file mode 100644 index 0000000..7c8d5d5 --- /dev/null +++ b/upstream-key.gpg @@ -0,0 +1,2358 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.9 (GNU/Linux) + +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 +=/QO8 +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +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 +=B4XR +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +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 +7er0at7C8YwwLvB0aEONMR81 +=RMom +-----END PGP PUBLIC KEY BLOCK-----