--- subversion-1.7.9.orig/debian/README.source +++ subversion-1.7.9/debian/README.source @@ -0,0 +1,4 @@ +This Debian package uses quilt(1) for patch management. +Please see /usr/share/doc/quilt/README.source for more information. + + -- Peter Samuelson Wed, 18 Jun 2008 21:45:55 -0500 --- subversion-1.7.9.orig/debian/authz_svn.load +++ subversion-1.7.9/debian/authz_svn.load @@ -0,0 +1,2 @@ +# Depends: dav_svn +LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so --- subversion-1.7.9.orig/debian/bin/svn-bisect +++ subversion-1.7.9/debian/bin/svn-bisect @@ -0,0 +1,187 @@ +#!/bin/sh -e +# +# Copyright (C) 2008,2009 by Robert Millan +# Copyright (C) 2009 by Peter Samuelson +# +# This program 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 3 of the License, or +# (at your option) any later version. +# +# This program 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 this program. If not, see . + +dir=.svn-bisect +: ${SVN:=svn} + +svn_info () +{ + LC_ALL=C $SVN info | awk "/^$1:/{ print \$2 }" +} + +usage () +{ + cat << EOF +Usage: + $0 start [good_rev [bad_rev]] + $0 good [revision] + $0 bad [revision] + $0 run {command} + $0 status + $0 reset +EOF +} + +do_init () +{ + rm -rf $dir + mkdir -p $dir + svn_info URL > $dir/url + svn_info Revision > $dir/start + if [ -n "$1" ]; then do_good_bad good "$1"; fi + if [ -n "$2" ]; then do_good_bad bad "$2"; fi +} + +do_reset () +{ + if [ ! -d $dir ]; then return 0; fi + if [ ! -f $dir/url ]; then + echo >&2 "Error: no $dir/url file" + exit 1 + fi + url=$(cat $dir/url) + rev=$(cat $dir/start) + $SVN switch -r$rev "$url@$rev" + rm -fr $dir + echo "Now at r$rev in $url" +} + +do_status () +{ + if [ ! -d $dir ]; then + status='not initialized' + elif [ -f $dir/found ]; then + status="found bad revision r$(cat $dir/found)" + elif [ ! -f $dir/revs ]; then + if [ ! -f $dir/good ]; then + status='still need a "good" revision' + elif [ ! -f $dir/bad ]; then + status='still need a "bad" revision' + else + status='???' + fi + else + status="r$(head -n1 $dir/revs) is good, r$(tail -n1 $dir/revs) is bad" + status="$status, $(($(wc -l < $dir/revs) - 2)) unknown revs in between" + fi + echo "svn-bisect: status: $status" +} + +do_good_bad () +{ + what=$1 + shift + good=0; bad=99999999; + if [ -n "$1" ] ; then + current=$(echo "$1" | sed s/^r*// | tee $dir/$what) + else + current=$(svn_info Revision | tee $dir/$what) + fi + + if [ -f $dir/revs ]; then + cat $dir/revs | while read rev; do + if { [ $what = good ] && [ $rev -ge $current ]; } || + { [ $what = bad ] && [ $rev -le $current ]; }; then + echo $rev + fi + done > $dir/revs.new; + mv $dir/revs.new $dir/revs + elif [ -f $dir/good ] && [ -f $dir/bad ]; then + $SVN log -q -r$(cat $dir/good):$(cat $dir/bad) | + awk '/^r/{print $1}' | cut -c2- > $dir/revs + else + return 0 + fi + good=$(head -n1 $dir/revs) + bad=$(tail -n1 $dir/revs) + url=$(cat $dir/url) + start=$(cat $dir/start) + n=$(wc -l < $dir/revs) + case $n in + 0) + echo >&2 "Error: no good or bad revs" + exit 1 ;; + 1) + echo >&2 "Error: r$(cat $dir/revs) is marked as both good and bad" + exit 1 ;; + 2) + echo "Regression found!" + echo "Last good revision: r$good" + echo "First bad revision:" + $SVN log -r$bad + echo "Use '$0 reset' or 'rm -r $dir' to clean up" + echo $bad > $dir/found + return 0 ;; + esac + target=$(head -n $(((n+1)/2)) $dir/revs | tail -n1) + echo "Switching to r$target ..." + $SVN switch -r$target "$url@$start" + url2=$(svn_info URL) + if [ "$url" != "$url2" ]; then + echo "r$target is in $url2" + fi + return $? +} + +do_run () +{ + cmd=$1 + shift + while [ -d $dir ] && [ ! -f $dir/found ]; do + set +e + eval ${cmd} + status=$? + set -e + case $status in + 125) $0 skip ;; + 0) $0 good ;; + *) $0 bad ;; + esac + done +} + + +cmd=$1 +shift +case "$cmd" in + + start) do_init "$@" ;; + + bad) do_good_bad bad "$@" ;; + + good) do_good_bad good "$@" ;; + + run) do_run "$@" ;; + + status) do_status ;; + + reset) do_reset ;; + + -h|--help) + usage + exit 0 ;; + + "") + usage >&2 + exit 1 ;; + + *) + echo "Unknown parameter \`$cmd'" >&2 + usage >&2 + exit 1 ;; +esac --- subversion-1.7.9.orig/debian/bin/svnwrap +++ subversion-1.7.9/debian/bin/svnwrap @@ -0,0 +1,35 @@ +#!/bin/sh +# +# svnwrap.sh: wrapper subversion client programs, which sets umask=002. +# +# Copyright 2006 by Peter Samuelson +# Permission is granted to everyone to use and distribute this work, +# without limitation, modified or unmodified, in any way, for any purpose. +# +# This script is not always needed: for somewhat complicated reasons, +# subversion already Does The Right Thing for FSFS repositories but +# cannot feasibly do so for BDB. +# +# See the manpage for more details. + +umask 002 + +known_progs='svn svnlook svnserve svnadmin svnversion' +known_progs_path=/usr/bin + +usage () { + echo >&2 "Usage: svnwrap {program} [args...]" + echo >&2 "Valid programs: $known_progs" + exit 1 +} + +exe= +arg0=$(basename "$0") +case " $known_progs " in + *" $arg0 "*) exe=$arg0 ;; + *" $1 "*) exe=$1; shift ;; + *) usage ;; +esac +case "$exe" in *" "*) usage ;; esac + +exec $known_progs_path/$exe "$@" --- subversion-1.7.9.orig/debian/changelog +++ subversion-1.7.9/debian/changelog @@ -0,0 +1,2297 @@ +subversion (1.7.9-1+nmu4) unstable; urgency=low + + * Non-maintainer upload. + * patches/ruby-test-wc: New patch from upstream to fix a stray case of a + testsuite failure due to APR 1.4 hash randomization. Thanks to + Michael Gilbert for digging this up. (Closes: #705364) + * Use --disable-neon-version-check to build libsvn_ra_neon against libneon27 + 0.30.0. + * Add handling of directory to symlink conversions for + /usr/share/doc/libsvn-{dev,java,ruby,ruby1.8}. (Closes: #690155) + + -- James McCoy Mon, 02 Sep 2013 21:11:08 -0400 + +subversion (1.7.9-1+nmu3) unstable; urgency=high + + * Non-maintainer upload. + * Disable libapache2-svn build (closes: #712004, #666794) + + -- Julien Cristau Tue, 09 Jul 2013 19:56:11 +0200 + +subversion (1.7.9-1+nmu2) unstable; urgency=high + + * Non-maintainer upload. + * Add CVE-2013-1968.patch patch. + CVE-2013-1968: Subversion FSFS repositories can be corrupted by newline + characters in filenames. (Closes: #711033) + * Add CVE-2013-2112.patch patch. + CVE-2013-2112: Fix remotely triggerable DoS vulnerability. (Closes: #711033) + + -- Salvatore Bonaccorso Thu, 06 Jun 2013 13:14:52 +0200 + +subversion (1.7.9-1+nmu1) unstable; urgency=medium + + * Non-maintainer upload. + * Convert SVN_STREAM_CHUNK_SIZE to an integer in svn/core.py (closes: #683188). + + -- Michael Gilbert Fri, 12 Apr 2013 00:58:01 +0000 + +subversion (1.7.9-1) unstable; urgency=medium + + * New upstream version. Some DOS fixes in mod_dav_svn: + - CVE-2013-1845: mod_dav_svn excessive memory usage from property changes + - CVE-2013-1846: mod_dav_svn crashes on LOCK requests against activity URLs + - CVE-2013-1847: mod_dav_svn crashes on LOCK requests against non-existant + URLs + - CVE-2013-1849: mod_dav_svn crashes on PROPFIND requests against activity + URLs + - CVE-2013-1884: mod_dav_svn crashes on out of range limit in log REPORT + request + * patches/python-swig205, patches/g++47: Remove as obsolete. + * Don't make python-subversion 'Depends: subversion'. It is quite + usable on its own. + * Move libsvn1 to section 'libs'. (Ref: #700145) + * Update watch file. (Closes: #672157) + + -- Peter Samuelson Sat, 06 Apr 2013 16:16:37 -0500 + +subversion (1.7.5-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream version. (Closes: #621692, #656966) + - Refresh patches; remove obsolete no-dbus-spam, kwallet-wid, + perl-warning, perl-compiler-flags, po, swig2-compat, + disable-failing-tests, python-exception-syntax + - Split patches/apr-abi into apr-abi1 (to be submitted) and + apr-abi2 (Debian-specific). + - Disable patches/ruby-test-info ... for now. + - Requires serf 1.0 or higher. + * Upstream no longer ships contrib in tarball: + - Remove contrib-license-audit + - subversion-tools now Recommends: svn2cl + - Ship svn-clean, svn-fast-backup, svn_apply_autoprops, + svn_load_dirs, commit-email.pl in debian/contrib + - Don't ship svnmerge.py, it has outlived its usefulness + - Delete patches/{svn2cl-*,svn-clean-ignore,commit-email} + - Overhaul debian/copyright + * rules: Specify that we want our own libtool. Otherwise it finds the + one from /usr/share/apr-1.0/build, which doesn't support C++. + * patches/entropy: Remove as obsolete. It was a workaround for apr + using /dev/random, but apr switched to /dev/urandom in 1.3. + * Move emacs plugins from subversion to subversion-tools. + * patches/java-osgi-metadata: Add OSGi metadata to the libsvn-java + jarfile. Thanks Jakub Adam. (Closes: #644438) + * Switch from python-support to dh_python2. + * patches/python-swig205: New patch: Adjust for swig 2.0.5+ handling of + Python ints vs. longs. + + [ Michael Diers ] + * More contrib adjustments: + - Provide debian/contrib/emacs from upstream VCS contrib/client-side/emacs + - Add svn_1.6_releasenotes.html, svn_1.7_releasenotes.html + - subversion.docs, subversion.install + - subversion-tools.docs, subversion-tools.manpages + + -- Peter Samuelson Sat, 16 Jun 2012 23:56:38 -0500 + +subversion (1.6.18dfsg-1) experimental; urgency=low + + * New upstream version. + - patches/sasl-mem-handling: delete obsolete patch. + * Add Conflicts and Replaces: libsvn-jni. (Closes: #675987) + * Rename libsvn-ruby1.8 to ruby-svn, per Ruby policy. + Leave transition package behind for wheezy. + + -- Peter Samuelson Fri, 08 Jun 2012 00:04:19 -0500 + +subversion (1.6.17dfsg-4) unstable; urgency=medium + + * Ack NMU, thanks Ondrej. Urgency medium because the NMU fixes RC bugs. + - Revert libsvn-java split. Instead, disable multiarch for libsvn-java. + If anyone _needs_ multiarch for Java libraries, which I doubt, we + should come up with a way to produce deterministic jar files. + - Reintroduce specific db dependencies, so a random binNMU can't + change the DB version without warning. + * Disable serf support for now, as this release won't properly work with + serf 1.0. + * patches/g++47: New patch to build with g++ 4.7. + * Policy 3.9.3 (no changes). + * Move ruby files to /usr/lib/ruby/vendor_ruby per ruby policy. + + -- Peter Samuelson Sun, 03 Jun 2012 17:54:15 -0500 + +subversion (1.6.17dfsg-3.1) unstable; urgency=low + + * Non-maintainer upload + * Disable test-suite which was broken by apr 1.4.6 update (Closes: #669494) + * Also rescue on Errno::EINVAL (Closes: #624810, #629952) + * Split libsvn-java to libsvn-java and libsvn-jni (Closes: #670034) + * Depend on generic libdb-dev and db-util (Closes: #621460) + * Install java files prior to dh_install -i call + * Declare proper relationships between -jni and -java packages + + -- Ondřej Surý Tue, 29 May 2012 15:49:32 +0200 + +subversion (1.6.17dfsg-3) unstable; urgency=medium + + * libapache2.preinst: Fix upgrade case from before 1.6.17dfsg-2. + * libapache2.prerm: 'a2dismod' modules in reverse dependency order. + * patches/apache_module_dependency: New patch to allow mod_authz_svn to + load before mod_dav_svn and still use its functions. + All these together, Closes: #642250. + * Remove a bit more autofoo in 'clean' target. + + -- Peter Samuelson Sat, 19 Nov 2011 18:56:28 -0600 + +subversion (1.6.17dfsg-2) unstable; urgency=low + + * Standards-Version: 3.9.2. Also, multiarch. + * Move to debhelper level 7. + * patches/perl-warning: New patch to suppress a bogus Perl undef warning. + (Closes: #422699) + * patches/swig2-compat: New patch from upstream to build with swig 2.x. + (Closes: #634049) + * patches/perl-compiler-flags: New patch from upstream to address an + issue brought to light by Perl 5.14. (Closes: #628507) + * patches/sasl-mem-handling: New patch from upstream to fix a crash with + svn:// URLs and SASL authentication. (Closes: #631765) + * patches/svn2cl-upstream: Use --non-interactive in svn2cl to avoid + hanging on, e.g., password prompts. (Closes: #443860) + * patches/python-exception-syntax: New patch: Fix a couple instances of + literal string exceptions in Python, which don't work in 2.6+. + (Closes: #585358) + * Remove some preinst/postinst magic that hasn't been needed in years. + * Split authz_svn.load away from dav_svn.load, since most users do not + need both. New installs will enable only dav_svn by default. + * Restart apache in libapache2-svn postinst. (Closes: #610236, #628990) + * Improve symbols file with (regex)__ catchall for private symbols not + otherwise accounted for. (Closes: #607544) I'm also including a + workaround for rapidsvn, to be removed when 0.14 is released. + * Add ${misc:Depends} everywhere. Drop libsvn-java dependency on a jre. + Thanks, Lintian. + * Remove the extra copy of jquery supplied by doxygen, from libsvn-doc. + Doesn't seem to even be used. Thanks, Lintian. + * patches/po: New patch from Laurent Bigonville to fix minor issues in + fr.po and ja.po. (Closes: #607381) + * Move to dh_lintian, and fix up the overrides a bit. + + -- Peter Samuelson Thu, 15 Sep 2011 12:02:03 -0500 + +subversion (1.6.17dfsg-1) unstable; urgency=high + + * New upstream version. Includes security fixes: + - CVE-2011-1752: Remotely triggered crash in mod_dav_svn + - CVE-2011-1783: Remotely triggered memory exhaustion in mod_dav_svn + - CVE-2011-1921: Content leak of certain files marked unreadable + * svn-bisect: Support $SVN environment variable, requested by Daniel + Shahaf upstream. + * Update Lintian overrides to account for python through 2.9, + in case that ever comes to be. + + -- Peter Samuelson Wed, 01 Jun 2011 17:07:33 -0500 + +subversion (1.6.16dfsg-1) unstable; urgency=high + + * New upstream version. + - Fixes CVE-2011-0715: Remotely crash mod_dav_svn anonymously via a + lock token. + * patches/change-range: New patch to support -cA-B syntax on command line. + * Stop using svn-make-config.c; we can do the same just by running svn + itself in a controlled home directory. Delete debian/tools/. + + -- Peter Samuelson Thu, 03 Mar 2011 10:55:42 -0600 + +subversion (1.6.12dfsg-4) unstable; urgency=high + + * patches/loosen-sqlite-version-check: New patch: Relax the SQLite + version check, to match the Debian sqlite3 packaging. + (Closes: #608925) + * patches/cve-2010-4539: New patch for CVE-2010-4539, fixing a remotely + triggered crash in mod_dav_svn involving use of the SVNParentPath + feature. (Closes: #608989) + + -- Peter Samuelson Wed, 05 Jan 2011 10:43:01 -0600 + +subversion (1.6.12dfsg-3) unstable; urgency=medium + + * Apply two patches from upstream 1.6.15: + - patches/server-memleak: New patch: fix some server-side memory + leaks, including CVE-2010-4644. + - patches/no-wc1.7-check: New patch: Stop checking for being inside a + 1.7 working copy. The value is too low and the performance penalty + too high. + + -- Peter Samuelson Wed, 22 Dec 2010 20:38:17 -0600 + +subversion (1.6.12dfsg-2) unstable; urgency=medium + + * patches/cve-2010-3315: New patch for CVE-2010-3315, whereby, in rare + configurations, mod_dav_svn could give too much access to authorized + users. + * control: Update Vcs-* fields, Homepage, Policy to 3.9.1 (no changes), + tweak python version declaration (Closes: #587853). + + -- Peter Samuelson Fri, 01 Oct 2010 12:11:10 -0500 + +subversion (1.6.12dfsg-1) unstable; urgency=medium + + * Urgency medium, as it (probably) fixes some FTBFS. + * New upstream version. + - Fixes some or all cases of inappropriate need for read access to the + root of the repository. (Closes: #510883) + * Disable parallel mode for 'make check', which appears to have made + some build daemons sad. + * svn-bisect: use pegs to support bisecting in deleted branches. + Thanks Nikita Borodikhin. (Closes: #582344) + * patches/ruby-test-info: expand for more failures nobody can figure + out. Sigh. + * Upgrade from source format 1.0 to 1.0. + + -- Peter Samuelson Mon, 21 Jun 2010 11:53:14 -0500 + +subversion (1.6.11dfsg-1) unstable; urgency=low + + * New upstream version. Rediff a patch or two. + - Mergeinfo queries no longer require access to repository root. + (Ref: #510883) + - Ignores errors reading .svn/ in parent directories. (Closes: #570271) + * rules: Run 'check' target in parallel mode. + + -- Peter Samuelson Mon, 19 Apr 2010 23:22:07 -0500 + +subversion (1.6.9dfsg-1) unstable; urgency=low + + * New upstream release. + - patches/16x-po, patches/ruby-test-core: remove, applied upstream. + * patches/java-build: Update for gcj 4.4. Update the build dependency + too, as this version of the patch will not work on gcj 4.3. + Thanks to Nobuhiro Iwamatsu. (Closes: #561516) + * patches/build-fixes: Fix parallelism in 'doc-api' target. Again. + (Closes: #537297) + * patches/ruby-test-info: Disable the two failing ruby tests that + nobody can reproduce except on the buildds. (Closes: #545372) + + -- Peter Samuelson Wed, 27 Jan 2010 01:57:47 -0600 + +subversion (1.6.6dfsg-2) unstable; urgency=low + + * Update svn-bisect (Closes: #535234), fix bugs, add features, + and write a manpage. Also mention it in the subversion-tools + Description. (Closes: #535187) + * Move from db4.7 to db4.8, tracking apr-util. (Closes: #557457) + * Move the example XSL and CSS files for mod_dav_svn to + /usr/share/doc/libapache2-svn/examples/. (Closes: #553535) + * patches/ruby-test-info: New patch to maybe address a FTBFS. (#545372) + Thanks Michael Diers, Joe Swatosh and Stefan Sperling. I expect that + this is not the only fix needed, but we shall see. + * patches/16x-po: New patch: a couple translation updates from 1.6.7. + * libsvn-java: depend on ${shlibs:Depends}, thanks Lintian. + * python-subversion: Update an outdated Lintian override. + * libsvn1: Add a handful of Lintian overrides. + + -- Peter Samuelson Sun, 22 Nov 2009 17:53:45 -0600 + +subversion (1.6.6dfsg-1) unstable; urgency=low + + * New upstream release. + - Reintroduce svn_load_dirs.pl: Dolby has agreed to an explicit free + software license. Thanks Blair Zajac for following up on this. + - patches/ruby-test-core: New patch from upstream to fix a new failure + in the ruby testsuite. + * Standards-Version 3.8.3 (no changes). + * control: Some housecleaning: remove some Conflicts/Replaces/Provides + that haven't been needed since etch. + * patches/build-fixes: add a small fix for parallel builds. + (Closes: #531369, #543110) + * patches/svn2cl-upstream: New patch to fix the XSL to better comply + with XML standards. (Closes: #546990) + * Enable kwallet support. (Closes: #539564) + - patches/kwallet-wid: New patch based very loosely on upstream work, to + let the kwallet library know your terminal's Window ID, if available. + - patches/apr-abi, patches/rpath: Fix the LINK_CXX target, now that + we're finally using it. + * Set dependency_libs='' in all .la files (Closes: #544877), as per: + http://lists.debian.org/debian-devel/2009/08/msg00783.html + + -- Peter Samuelson Thu, 22 Oct 2009 11:32:13 -0500 + +subversion (1.6.5dfsg-1) unstable; urgency=low + + * New upstream release. + - Resolves symlinks in ~/.subversion. (Closes: #541202) + * patches/ssh-no-controlmaster: Replace with the much simpler approach + upstream demonstrates with 'ssh -q'. + * patches/no-dbus-spam: New patch to shut up the gnome-keyring library + when it can't initialize. (Closes: #542403) + * patches/ruby-test-tree-conflicts: New patch from upstream trunk, to + fix two ruby test failures. + + -- Peter Samuelson Thu, 20 Aug 2009 12:16:39 -0500 + +subversion (1.6.4dfsg-1) unstable; urgency=high + + * New upstream security release. + - Fix CVE-2009-2411, heap overflows in svndiff stream parsing. + + -- Peter Samuelson Wed, 05 Aug 2009 20:12:07 -0500 + +subversion (1.6.3dfsg-1) unstable; urgency=low + + * New upstream release. (Closes: #531366) + * Upload to unstable (Closes: #532648) + * Update package sections corresponding to recent ftpmaster work. + * Re-enable libsvn_ra_serf, now that serf 0.3.0-0.2 is available. + * Add symbols file for libsvn1, for finer-grained dependencies. + + -- Peter Samuelson Tue, 14 Jul 2009 23:51:24 -0500 + +subversion (1.6.1dfsg-1) experimental; urgency=low + + * New upstream release. + + -- Peter Samuelson Thu, 09 Apr 2009 17:30:40 -0500 + +subversion (1.6.0dfsg-1) experimental; urgency=low + + * New upstream release. + - patches/{commit-email2,out-of-tree-build-fixes,svn2cl-upstream, + ssh-no-sigkill}: deleted, applied or obsoleted upstream. + Other patches rediffed. + - patches/build-fixes: New patch, mostly for out-of-tree build stuff. + - Fixes typo in fr.po. (Closes: #503266) + - Fixes WC out-of-sync issue. (Closes: #500665) + * Build-depends: libsqlite3-dev, libgnome-keyring-dev, libdbus-1-dev. + We _should_ give equal opportunity to KDE 4 KWallet support, + but in terms of dependencies, that is a much heavier burden. + - Disable 'auth-test' test. It assumes the gnome-keyring service + is available at test time - not likely, on a build daemon. + * Remove serf backend support for now, as it requires 0.3.0. + * Move to db4.7, tracking apr-util. (Closes: #526222) + + -- Peter Samuelson Fri, 27 Mar 2009 15:54:25 -0500 + +subversion (1.5.6dfsg-1) unstable; urgency=low + + * New upstream release. + * patches/commit-email2: New patch to fix mail header formatting in + commit-email.pl hook. (Closes: #508301) + * Tweak 'site-packages' location for python 2.6, taken from the Ubuntu + patch uploaded by Matthias Klose. + * Build-Depends is back again to libdb4.6-dev. + + -- Peter Samuelson Wed, 25 Feb 2009 20:23:51 -0600 + +subversion (1.5.5dfsg1-1) experimental; urgency=low + + * New upstream release. + * New script svn-bisect, thanks Robert Millan. (Closes: #505100) + * DAV proxy fixed for certain commit subcommands. (Closes: #511212) + + -- Peter Samuelson Wed, 07 Jan 2009 23:24:53 -0600 + +subversion (1.5.4dfsg1-1) experimental; urgency=low + + * New upstream release + + -- Peter Samuelson Thu, 23 Oct 2008 19:35:57 -0500 + +subversion (1.5.3dfsg1-1) experimental; urgency=low + + * New upstream release. + - patches/perl-test-syntax-error: removed, applied upstream + - Fixes infinite loop in a 'svn mv' corner case (Closes: #497953) + - bash completion updates (Closes: #499888) + + -- Peter Samuelson Fri, 10 Oct 2008 13:27:24 -0500 + +subversion (1.5.1dfsg1-1) unstable; urgency=low + + * New upstream release. + - Fixes some major corner cases in merge tracking. + - Fixes several crash bugs and regressions from 1.4 -> 1.5. + - patches/ruby-test-wc-normalize-compared-value: Remove, applied upstream. + * Symlink libsvn_ra_dav-1.so.1 -> libsvn_ra_neon-1.so.1 to avoid + breaking old packages that mistakenly linked to ra_dav. This was not + and is not supported, but at least one package did it. (Closes: #490423) + * Add a NEWS entry for 1.5.x in general. + * debian/watch: Add dversionmangle setting, thanks to lintian. + + -- Peter Samuelson Thu, 24 Jul 2008 15:48:17 -0500 + +subversion (1.5.0dfsg1-4) unstable; urgency=medium + + * Work around bug where 'make javahl' is not -j-safe. + + -- Peter Samuelson Mon, 07 Jul 2008 01:37:38 -0500 + +subversion (1.5.0dfsg1-3) unstable; urgency=medium + + * Bump shlibs file to libsvn1 (>= 1.5.0). (Closes: #488949) + * Fix typo in Build-Conflicts (libsvn-dev, not libsvn1-dev). + * Fix svnwrap(1) manpage inetd.conf example. (Closes: #462313) + + -- Peter Samuelson Wed, 02 Jul 2008 08:23:31 -0500 + +subversion (1.5.0dfsg1-2) unstable; urgency=low + + * Reenable Java support. + * patches/java-build: New patch to hack around incompatibilities between + Sun javah and gcj javah. + * Remove the last remnants of libsvn-javahl from the source package. + * Include upstream release notes file svn_1.5_releasenotes.html. + * Add svn-populate-node-origins-index (used in upgrading a repository + to 1.5) and svnmucc (useful client tool) to the subversion package. + (Closes: #408487) + + -- Peter Samuelson Mon, 30 Jun 2008 00:22:28 -0500 + +subversion (1.5.0dfsg1-1) experimental; urgency=low + + * New upstream release + - Fixes many bugs including: + - Translation errors (Closes: #404982, #451514) + - Now exports externals from a working copy. (Closes: #448864) + - Newer psvn.el provided. (Closes: #393651, #441994) + - 'svn export' handles externals now. (Closes: #448864) + - Perl module destructor doesn't crash. (Closes: #401340) + - 'svn merge' gets less confused on tree conflicts. (Closes: #366530) + - Update debian/contrib-license-audit, README.Debian-tarball + - Remove obsolete patches: jelmer-python-bindings, kaffe, + kaffe-javah, limit-zlib-link, neon27, python-memleak, + ruby-newswig, ruby-test-ra-race, svn-clean-manpage, + svn_load_dirs, swig-warning-124, testsuite-dont-use-os-popen3 + * rules: Run autogen-swig for each python version. + (Not strictly needed, but it is the simplest approach.) + * Switch from dpatch to quilt. + * Policy 3.8.0: + - copyright: Delete copy of common-licenses/Apache-2.0 + - control: Add Homepage field; + Wrap Uploaders field, which was > 80 columns + - rules: Support DEB_BUILD_OPTIONS=parallel=n; + Require DEB_BUILD_OPTIONS to be space-separated + - README.source: New file explaining quilt + * control: Add XS-Python-Version header, to suppress a warning + * control: Build-Conflicts: libsvn1-dev (<< 1.5); libtool can cause + trouble with installed .so files that don't contain needed symbols. + * control: New Build-Depends: libserf-0-0-dev, libsasl2-dev. + * control: Simplify Depends/Recommends to assume etch or newer. (Keep + some old Conflicts/Replaces/Provides.) Delete the libsvn-javahl etch + transition package. + * control: libsvn-java: I believe it needs java5 now, not just java2. + Hence gij | java5-runtime-headless. + * patches/perl-test-syntax-error: New patch borrowed from upstream, to + fix a perl5.10 issue in one of the tests. + * patches/ruby-test-wc-normalize-compared-value: New patch borrowed from + upstream, to fix a ruby test failure. + * patches/svn2cl: Split into svn2cl-upstream and svn2cl-debian. + Update svn2cl-upstream to 0.10 from upstream trunk. + * patches/apr-abi: Small adjustment to reduce libtool warnings. + * patches/out-of-tree-build-fixes: New patch: fix a few issues with + building outside the source tree. + * rules: Disable Java for the first upload to experimental, as I'm still + working on fixing that. + + -- Peter Samuelson Fri, 20 Jun 2008 21:53:29 -0500 + +subversion (1.4.6dfsg1-5) UNRELEASED; urgency=low + + * Downgrade libsvn-dev "Depends: libneon27-gnutls-dev" to Suggests and + add zlib1g-dev. These are for static linking. (Closes: #482512) + + -- Peter Samuelson Thu, 29 May 2008 20:29:41 -0500 + +subversion (1.4.6dfsg1-4) unstable; urgency=low + + * Disable java on alpha and hppa, as requested by Matthias Klose. + (Closes: #477908) + * Switch from neon27 to neon27-gnutls. (Closes: #478142) + * patches/testsuite-dont-use-os-popen3: New patch (from upstream): + use popen2.Popen3 instead of os.popen3. (Closes: #479079) + * patches/svn-clean-ignore: New feature patch, a mechanism to specify + files which, though unversioned, 'svn-clean' should not remove. + Suggested by Jonathan Hall. + * Add another -j1 to debian/rules, to fix a parallel build problem. + * patches/ssh-no-controlmaster: New patch to avoid a bad interaction + with OpenSSH connection sharing. (Closes: #413102) + + -- Peter Samuelson Sat, 03 May 2008 00:35:18 -0500 + +subversion (1.4.6dfsg1-3) unstable; urgency=low + + * patches/neon27: update for neon 0.28. (Closes: #476117) + * Build for all supported python versions. Loosely based on an Ubuntu + patch by Matthias Klose. (Closes: #446636) + + -- Peter Samuelson Mon, 14 Apr 2008 11:08:22 -0500 + +subversion (1.4.6dfsg1-2) unstable; urgency=low + + * subversion.NEWS: Add a note about the db4.6 upgrade. (Closes: #465432) + * rules: use dh_link rather than hand-rolled symlink management. + Closes: #465609 in the process. + * rules: Define DEB_HOST_ARCH and friends before using them, to fix + FTBFSes on the non-java architectures. + + -- Peter Samuelson Sat, 08 Mar 2008 14:27:22 -0600 + +subversion (1.4.6dfsg1-1) unstable; urgency=low + + * New upstream version. + - Don't use Chinese colons in zh_CN l10n file. (Closes: #397729) + * Build with db 4.6, to match apr-util. + * patches/svn-clean-manpage: New patch, fix a small typo. (Closes: #441827) + * patches/neon27: New patch from upstream trunk to support neon 0.27. + - control: build-depend on libneon27-dev. + - rules: no longer --disable-neon-version-check. + * patches/ruby-newswig: Support swig 1.3.33. (Closes: #453166) + * patches/python-memleak: New patch to fix a serious memory leak in the + Python bindings. Thanks to Jelmer Vernooij. (Closes: #428755) + * control: Policy 3.7.3. + * control: spell 'Source-Version' as 'binary:Version' for political + correctness. (Or for clarity.) + * control: add appropriate Vcs-Svn and Vcs-Browser fields. + * control: subversion-tools Recommends: rsync. (Closes: #459023) + * patches/svn2cl: update svn2cl to 0.9 (from upstream trunk). + * patches/commit-email: use original 'sendmail' commit-email.pl mode, + rather than the direct SMTP feature. (Closes: #447824) + * rules: do not run 'dh_testroot' or 'make extraclean' in clean rule. + * rules: rewrite DEB_BUILD_OPTIONS support; remove 'notest' synonym, as + the world seems to be standardizing on 'nocheck'. + * rules: remove 'DEB_BUILD_OPTIONS=-j[N]' support, add support for the + new 'dpkg-buildpackage -j[N]' feature. + * rules: add an option to disable ruby bindings. Though it turns out + we don't need it ... yet. + + -- Peter Samuelson Mon, 11 Feb 2008 23:49:02 -0600 + +subversion (1.4.4dfsg1-1) unstable; urgency=low + + * New upstream version. + - Fixes rare case of data loss / repository corruption. (Closes: #419348) + - Fixes minor security inconsistency regarding restricted paths being + copied to unrestricted paths, CVE-2007-2448. (Closes: #428194) + * Fix note in README.Debian about how to download vc-svn.el. + Thanks to Michael Richters. (Closes: #416582) + * rules: configure --disable-neon-version-check, to allow use of neon 0.26.3. + * rules: replace $(PWD) with $(CURDIR) to appease lintian. + Our use of PWD was safe, this is just a cleanup. + * rules: ship a shlibs file only for libsvn1; nobody should ever link to + the libraries in other packages. (Thanks again to lintian.) + - lintian-overrides: inform lintian that it's ok not to have shlibs + files in the swig-based packages + + -- Peter Samuelson Thu, 07 Jun 2007 00:57:11 -0500 + +subversion (1.4.3dfsg1-1) experimental; urgency=low + + [ Peter Samuelson ] + * New upstream version. + - patches/neon26 removed; applied upstream + * rules: Small cleanups, thanks to Patrick Desnoyers. + * patches/jelmer-python-bindings: Remove some python2.4isms (should help + with porting to sarge and elsewhere). Thanks to Romain Francoise, and + upstream. + + -- Peter Samuelson Thu, 25 Jan 2007 18:30:04 -0600 + +subversion (1.4.2dfsg1-2) unstable; urgency=medium + + [ Peter Samuelson ] + * rules: fix 'dontberoot' target not to run when it shouldn't. + (Closes: #396435) + * Add subversion-tools Conflicts: kdesdk-scripts (<= 4:3.5.5-1). + I'm told that their next release will remove the 'svn-clean' script, + which is quite similar to the one in subversion-tools. (See: #397874) + * Add manpages for svn-clean, svn-hot-backup, svn-fast-backup, and + svn-backup-dumps. Troy Heber helped write the last three. + * Ship svnmerge.README in subversion-tools. + + -- Peter Samuelson Fri, 10 Nov 2006 08:45:01 -0600 + +subversion (1.4.2dfsg1-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream release. + - No longer ships IETF draft spec. (Closes: #393414) + - patches/svnsync-manpage, parts of patches/neon26, patches/svnshell: + Obsolete, removed. + - Re-roll upstream tarball to remove some unlicensed files from the + "contrib" directory. Update debian/copyright regarding other files + in "contrib". (Closes: #394395) + * patches/neon26: update for 1.4.2, add neon 0.26.2 to the whitelist. + * Improve libapache2-svn installation experience: + - Use a2enmod/a2dismod instead of hand-hacking. + - dav_svn.conf: Comment everything out. (Many will want to use + sites-available/* rather than dav_svn.conf anyway.) Fix some of + the text and add more. (Closes: #392805) + * libsvn-java: Remove alternative Depends: java1-runtime. + It does in fact require JRE 1.2 (java2-runtime). + * Build with neon26 instead of neon25. + * Ship some example code from upstream in the various devel packages. + - patches/examples-compile-instructions: New patch, some small doc fixes. + * Ship a lot more scripts in subversion-tools, including svnmerge + (Closes: #293528), svn2cl (Closes: #350133). + - List these scripts in the Description. (Closes: #357506) + - Downgrade most Depends to Recommends, augment Recommends and Suggests + to match the scripts. + * rules: Add explicit check and informative error message for trying to + build as root. (Closes: #396435) + * libapache2-svn Description: it's Apache 2.2, not 2.0. (Closes: #397113) + * patches/ruby-test-ra-race: replace my fix by upstream's better one, + should _really_ fix m68k build this time. (Closes: #397173) + * patches/jelmer-python-bindings: New patch: backport python binding + improvements by Jelmer Vernooij from trunk. This is needed for + certain advanced python-based tools. + + -- Peter Samuelson Thu, 9 Nov 2006 00:07:42 -0600 + +subversion (1.4.0-5) unstable; urgency=medium + + [ Peter Samuelson ] + * rules: Set HOME to a dummy value to prevent a build failure if the + real HOME is mode -x. Plus a few minor cleanups. + * rules: Link -ldb explicitly (rather than implicitly via -laprutil-1). + This is required for libdb symbol versioning to propagate. + Thanks to Pitr Jansen for help tracking this down. + * patches/svnshell: Fix insufficient argument checking in 'setrev' + command. (Closes: #392004) + + -- Peter Samuelson Wed, 11 Oct 2006 03:30:03 -0500 + +subversion (1.4.0-4) unstable; urgency=medium + + [ Peter Samuelson ] + * patches/apr-abi: switch to a simpler test that actually DTRT on 64-bit + platforms. (Closes: #391744) + + -- Peter Samuelson Sun, 8 Oct 2006 09:26:04 -0500 + +subversion (1.4.0-3) unstable; urgency=low + + [ Peter Samuelson ] + * patches/ruby-test-ra-race: New patch for another testsuite race + discovered on m68k. + * patches/ruby-typemap-digest: New patch to fix a m68k failure, quite + possibly the same failure we've seen sporadically on other arches + in the past. Thanks to Roman Zippel. (Closes: #387996) + * rules: sed *.la to change internal *.la references to -l form. + (Closes: #388733) + * control,rules: Reinstate libsvn-javahl as a dummy package, for + sarge upgrades. (Closes: #387901) + * control,rules: Disable Java on hurd-i386, requested by Cyril Brulebois. + * Build with apache 2.2 / apr1 / aprutil1 again, now that apache 2.2 is + going into unstable. + - aprutil1 always links to libdb4.4 nowadays. (Closes: #387396) + * libapache2-svn.postinst: Do not enable the dav_fs module: not needed + for a Subversion server. + + [ Troy Heber ] + * debian/control clean up of Maintainer and Uploaders fields to reflect the + current team. + + -- Troy Heber Tue, 3 Oct 2006 07:45:31 -0600 + +subversion (1.4.0-2) unstable; urgency=low + + [ Peter Samuelson ] + * Run tests in 'build' target, not 'binary' target. This prevents a + build failure if 'binary' is run as root (not fakeroot). + * patches/svnsync-manpage: trivial typo fix from upstream. + * Delete README.db4.4: the upgrade procedure it describes is now fully + automatic. + + -- Peter Samuelson Sun, 10 Sep 2006 05:05:47 -0500 + +subversion (1.4.0-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream version - well, not really new, it's rc5 rebranded. + * Revert libsvn1/apache2.2 change, since apache 2.2 is not yet in + unstable. libsvn1 is libsvn0 again, for now. + * patches/no-extra-libs: detect apr0/apr1 correctly, and use + pkg-config for neon. + * patches/neon26: new patch to build cleanly with neon 0.26.1. + Though we won't actually use it until #386652 is fixed. + * Document BDB 4.4 upgrade better; also, move the NEWS entry from + 'libsvn0' to 'subversion' where it is more likely to actually be + read. + * patches/no-extra-libs-2: Tweak to remove more unnecessary linking. + + -- Peter Samuelson Thu, 7 Sep 2006 21:03:06 -0500 + +subversion (1.4.0~rc5-1) experimental; urgency=low + + * New upstream version. + - patches/ruby-txtdelta-apply-instructions: remove (obsolete). + + -- Peter Samuelson Thu, 24 Aug 2006 05:31:24 -0500 + +subversion (1.4.0~rc4-2) experimental; urgency=low + + [ Peter Samuelson ] + * Reenable apache support; build-depend on apache2-threaded-dev 2.2, + now that it's in experimental. + * Build-Depends: remove bison, relax python version again (as python + handling is now done by python-support). + * patches/ruby-txtdelta-apply-instructions: new patch from upstream, + fixes the test failure on amd64. + * Compile against libdb4.4, which should fix the famous "wedged + repository" issue. + - Build-Depends: libaprutil1-dev (>= 1.2.7+dfsg-1) + - Update rules, control, README.db4.4 + - Add note to libsvn1.NEWS - please read it! + + -- Peter Samuelson Fri, 18 Aug 2006 13:06:49 -0500 + +subversion (1.4.0~rc4-1) experimental; urgency=low + + * There is a known issue with amd64 and the SvnDeltaTest in the ruby + testsuite. + + [ Peter Samuelson ] + * New upstream release. + - commit-email.pl has option not to send diffs. (Closes: #217133) + - Help text clarified for options like --file. (Closes: #233099) + - Rediff patches. Delete patches already included upstream: + apache-crash-fix, bash_completion, lc_ctype, perl-test-clean, + svn_load_dirs-symlinks, swig-1.3.28. + - Add Build-Depends: zlib1g-dev. + * Bump subversion-tools dependencies on the other packages to >= 1.4. + * Support ENABLE_APACHE macro, to disable 'libapache2-svn'. + Disable apache until apache 2.2 makes its way into experimental. + * Switch to libapr1, which entails an ABI change to libsvn. + - libsvn0 -> libsvn1 + - libsvn0-dev -> libsvn-dev + - patches/apr-abi: New patch: change the libsvn_* SONAMEs. + (This type of change should be upstream-driven, but upstream has + declined to do it.) + - patches/fix-bdb-version-detection: New patch: tweak BDB version + detection not to rely on an apr-util misfeature (#387105). + * Rename libsvn-javahl to libsvn-java, to comply (in spirit) with the + Java Policy. (Closes: #377119) + * Rename libsvn-core-perl to libsvn-perl, because it provides several + modules in the SVN:: namespace, not just SVN::Core. + * patches/limit-zlib-link: New patch from upstream to prevent + unnecessary -lz linkage in client binaries. + * Update copyright file again. + * Switch to python-support. + * subversion-tools: downgrade rcs and exim4 to Recommends. + * Add NEWS entry to libsvn1, explaining compatibility issues - please + read it, folks! + + [ Troy Heber ] + * tweaked rpath patch HUNK 2, so it would apply cleanly. + + -- Peter Samuelson Thu, 10 Aug 2006 20:43:19 -0500 + +subversion (1.3.2-6) unstable; urgency=low + + [ Peter Samuelson ] + * Add libsvn0 Conflicts: subversion (<< 1.3) to prevent chaos from + linking to both neon24 and neon25. + * Add libsvn0 Conflicts: python2.3-subversion (<< 1.2.3dfsg1-1) + because of the libsvn_swig_py move. (Closes: #385146) + * Link with Berkeley DB 4.4. (Closes: #385589, #383880 again) + - patches/bdb-44: new patch cobbled together from upstream trunk + * patches/ruby-test-svnserve-race: update from our 'sleep 3' hack to + what I hope is a proper fix. Thanks to Kobayashi Noritada, Wouter + Verhelst and Roman Zippel. (Closes: #378837) + * Switch to python-support. + + -- Peter Samuelson Sat, 2 Sep 2006 05:04:09 -0500 + +subversion (1.3.2-5) unstable; urgency=medium + + [ Peter Samuelson ] + * python-subversion.{prerm,postinst}: use pyversions, fix stupid bug + (Closes: #379278) in prerm. Tighten python build-dep to ensure + availability of pyversions. + * patches/ruby-test-svnserve-race: increase 'sleep 1' hack to 'sleep 3' + for now. Not a proper fix, but should build on m68k. + * control: downgrade subversion Depends: patch to Suggests. You can do + a lot with subversion without a 'patch' program. + + -- Troy Heber Mon, 24 Jul 2006 14:01:49 -0600 + +subversion (1.3.2-4) unstable; urgency=low + + [ Peter Samuelson ] + * control, rules, patches/*: switch from cdbs-simple-patchsys to dpatch. + Remove .patch suffixes, change build-depends. + * rules: separate the *-arch and *-indep targets properly. + * copyright: updates, mention licenses for the bits in the tarball which we + don't use. + * Support new python policy, building for version 'current'. + Thanks to Max Bowsher. (Closes: #373387) + * Improve package descriptions. (Closes: #375469) + * Add java2-runtime alternative to libsvn-javahl JVM dependency. + (Closes: #377529) + * Add libsvn0 Conflicts: libsvn-core-perl (<< 1.2.3dfsg1-1) to force a + necessary upgrade. (Closes: #376565) + + [ Guilherme de S. Pastore ] + * control: updated e-mail address. + + -- Troy Heber Mon, 17 Jul 2006 08:39:20 -0600 + +subversion (1.3.2-3) unstable; urgency=low + + [ Troy Heber] + * Adding arm to list of javahl disabled architectures + + -- Troy Heber Wed, 14 Jun 2006 14:26:44 -0600 + +subversion (1.3.2-2) unstable; urgency=low + + [ Peter Samuelson ] + * control, rules: switch from kaffe to java-gcj-compat-dev. Thanks to + Bastian Blank. Also reenable libsvn-javahl, for now, on all + architectures except m68k, mips, mipsel. (Closes: #370228) + * ruby-test-svnserve-race.patch: new kludge to avoid a race condition in + the ruby testsuite on really slow machines. + + -- Peter Samuelson Mon, 12 Jun 2006 18:50:08 -0500 + +subversion (1.3.2-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream release. + - Remove patches applied upstream: apache-crash-fix.patch, + svn_load_dirs-symlinks.patch, swig-1.3.28.patch + * debian/watch: new file for use by 'uscan' from devscripts. + * Standards version 3.7.2. (No changes.) + * control: upgrade Build-Conflicts to libsvn0 (<< 1.3). + This is that old workaround for #291641. + * rules: rework testsuite invocation: + - Add 'check' series of targets, and 'check-help' to remind one + of what they are + - Conditionalise javahl tests on ENABLE_JAVAHL + - Reorder the checks to put the core tests at the end; they are by far + the most time-consuming, and rarely fail anyway + - Only 'cat tests.log' if the core tests fail: the other testsuites + don't use that file anyway + + -- Peter Samuelson Thu, 1 Jun 2006 04:10:19 -0500 + +subversion (1.3.1-3) unstable; urgency=medium + + [ Peter Samuelson ] + * Tighten dependency between subversion and libsvn0, to reduce user + confusion. It is almost always the library version that matters, as + far as bugs and features are concerned. (Closes: #359315) + * Disable java bindings on hppa and ia64, since kaffe is broken on + those architectures. It's been broken on ia64 for a long time, and it + looks as though hppa may remain broken for awhile too (see #364819). + * ssh-no-sigkill.patch: new patch to SIGTERM (instead of SIGKILL) the + tunnel agent, which is usually ssh. We can do this now that #313371 + is fixed. (Closes: #335528) + * rules: add -V'libsvn0 (>= 1.3.0)' to dh_makeshlibs to loosen the + shlibs file a bit. Upstream guarantees that the library ABI won't be + augmented during any single x.y.* cycle. + * svnwrap.sh, man/svnwrap.1: new script for subversion-tools package to + optionally wrap subversion client commands with 'umask 002'. + (Closes: #242368, #259226, #282468, #292358) + * lc_ctype.patch: new patch to make locale errors non-fatal, suggested + by upstream developer Peter Lundblad. (Closes: #363983) + * last-changed-date-charset.patch: new patch: convert $LastChangedDate$ + keyword from UTF-8 to local character set. (Closes: #290774) + * apache-crash-fix.patch: new patch to fix a crash in mod_dav_svn. + * swig-warning-124.patch: new patch to disable swig typemap warning, + drastically shrinking the build log. + + [ Troy Heber ] + * changing from UNRELEASED to unstable and uploading + + -- Troy Heber Fri, 05 May 2006 18:14:57 -0600 + +subversion (1.3.1-2) unstable; urgency=low + + [ Peter Samuelson ] + * Fix libsvn-ruby1.8: actually ship the swig glue, which we had overlooked. + Thanks to Thiago Avancini for the report and some Ruby help. + * Exclude Java bindings on kfreebsd-amd64. (Closes: #361488) + + -- Peter Samuelson Sun, 9 Apr 2006 05:10:42 -0500 + +subversion (1.3.1-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream version. + - Delete obsolete neon-0.25.5.patch. + * swig-1.3.28.patch: add a few more upstream patches. + + -- Troy Heber Tue, 04 Apr 2006 15:05:12 -0600 + +subversion (1.3.0-5) unstable; urgency=high + + * rpath.patch: Delete rpaths for apache2 modules. + (Closes: #359234, also see CVE-2006-1564) + - rules: Do not override INSTALL_MOD_SHARED, this is no longer needed + - libapache2-svn.install: Use modules from the install, not from + the build tree + + -- Peter Samuelson Tue, 28 Mar 2006 00:56:59 -0600 + +subversion (1.3.0-4) unstable; urgency=low + + [ Peter Samuelson ] + * rules: Support DEB_BUILD_OPTIONS=-jN, passed to child make processes. + Invoke 'make autogen-swig' separately as it has problems with -j. + Be more paranoid about cleaning out old swig headers. + Document all the DEB_BUILD_OPTIONS we now support. + * control: Don't say we provide python2.4-subversion, since we don't. + * swig-1.3.28.patch: add another upstream patchlet. Should fix the + intermittent FTBFS due to the ruby test suite. + * rules: fix doc/subversion/README.db4.3.gz symlink (Closes: #357856) + + -- Troy Heber Mon, 20 Mar 2006 08:13:33 -0700 + +subversion (1.3.0-3) unstable; urgency=low + + [ Peter Samuelson ] + * rules: Symlink /usr/share/doc/libsvn-ruby -> libsvn-ruby1.8 + * swig-1.3.27.patch: Rename to swig-1.3.28.patch, and update it with + more patches stolen from upstream, to support SWIG 1.3.28. + - control: Remove Build-Conflicts: swig (>= 1.3.28). Assume for now + that 1.3.29 and newer won't cause other problems. + + [ Adam Conrad ] + * Do the Provides/Replaces/Conflicts dance for python2.4-subversion as + well, since Ubuntu has shipped that for ages, and this allows for + smoother upgrades/sidegrades between the two. + + -- Troy Heber Sun, 12 Mar 2006 15:32:57 -0700 + +subversion (1.3.0-2) unstable; urgency=low + + [ Peter Samuelson ] + * Disable java bindings on m68k for now. It seems to have problems + similar to the ones on arm and mips. (See #344986.) + * Some suggestions from Ubuntu backporter Blair Zajac (Closes: #347775): + - Delete pregenerated swig headers which may or may not be compatible + with Debian's version of swig. + - Tighten Build-Depends on kaffe to >= 2:1.1.6: he reports that 1.1.5 + fails to build the Java bindings. + - Build-Depends: junit, pass --with-junit to configure, and run 'make + check-javahl'. It fails on current free JVMs, so ignore failure. + - Tighten subversion-dev dependency on libapr0-dev to >= 2.0.55-3, + to match the Build-Depends. + - Pass CLEANUP=true to 'make check' to reduce disk usage. + * subversion.README.Debian: Rewrite for clarity, and to document the two + Emacs helpers. Thanks to Gavin Baker for both the research and the + writing. + * rules: 'make swig-rb' so that 'make install-swig-rb' does not have + to do it for us. Thanks to Max Bowsher for noticing. + * Adjust swig patches: + - swig-1.3.27-hack.patch: remove, obsoleted by upstream changes. + - ruby-swig-1.3.27.patch: rename to swig-1.3.27.patch and update to + include trunk r18172, which is likely to go in a future 1.3.x. + * New package libsvn-doc with doxygen-generated API docs in HTML + format. Thanks to Max Bowsher. (Closes: #269635) + - Add Suggests: libsvn-doc for libsvn0-dev + * Rename python2.3-subversion to python-subversion, recommended by + Python policy. This will allow for a slightly smoother global python + transition in the future. + - Replaces/Conflicts/Provides: python2.3-subversion + - Use #!/usr/bin/python everywhere, not #!/usr/bin/python2.3 + * Add Provides: libsvn-dev to libsvn0-dev. The package will be renamed + in the future, when libsvn0 becomes libsvn1. + * Loosen dependencies between subversion-tools and the other packages, + as the one is "Architecture: all" and the others are not. + * Build-Conflict with swig 1.3.28 and newer, to document reality. This + has been addressed by upstream trunk but not yet backported. + * patches/neon-0.25.5.patch: new patch from upstream, to allow compiling + with neon 0.25.5. + + [ Troy Heber ] + * Changing my email address + + -- Troy Heber Wed, 22 Feb 2006 08:18:12 -0700 + +subversion (1.3.0-1) experimental; urgency=low + + [ Peter, Guilherme ] + * New upstream version. (Closes: #344819) + - Undeprecates svnserve -R (Closes: #341438) + - Fixes typo in locks/db-logs.lock (Closes: #339298) + - README does not mention bdb specifics when using fsfs (Closes: #295860) + - Seems to not crash on deep directory checkouts with certain kernels. + (Closes: #348327) + - Back to a pristine upstream tar, as upstream has removed the + (non-free) Subversion Book. + - All patches rediffed / ported. + - no_extra_libs, svn_load_dirs_symlinks: renamed to no-extra-libs, + svn_load_dirs-symlinks, for consistency. + - commit-email-warning, l10n-segfault: Removed (fixed upstream). + + [ Peter Samuelson ] + * New packages libsvn-ruby1.8 and dummy libsvn-ruby. (Closes: #335987) + - patches/ruby-no-strict-aliasing.patch: new patch. + - patches/ruby-swig-1.3.27.patch: new patch from upstream, to + build with SWIG 1.3.27. Upstream says this is still unofficial. + * Disable java on kfreebsd-i386. (Closes: #345196) + * patches/bash_completion.patch: new patch to fix minor wildcard + breakage with bash completion. (Closes: #342052) + * rules: remove x bit from /etc/bash_completion.d/subversion. + Thanks, lintian. + * control: downgrade db4.3-util to Suggests. + * Move README.db4.3 and the corresponding NEWS entry to the libsvn0 + package. Leave a symlink in /usr/share/doc/subversion/. + (Closes: #342235) + * README.db4.3: add notes about preserving file permissions. + Thanks to Ross Boylan. (Closes: #345819) + * patches/svn_load_dirs_symlinks.patch: new patch to handle symlinks in + the svn_load_dirs contrib script. Thanks to Tilman Koschnick. + (Closes: #311440, #319165) + * rules: cleanups: + - Use debhelper -s instead of -a, and -i -s instead of -A. + This would have prevented the need for 1.2.3dfsg1-2. + - Move some build rules out of the 'install' target. + - Enable additional tests (make check-swig-py). + - Drop use of 'time' (and corresponding build-dep in control). + * control: move from libneon24 to libneon25, as upstream now prefers. + * patches/no-extra-libs-2.patch: new patch: more spurious-link pruning. + + -- Peter Samuelson Fri, 6 Jan 2006 03:28:16 -0600 + +subversion (1.2.3dfsg1-3) unstable; urgency=low + + [ Peter Samuelson ] + * rules: Remove the unwritten requirement that /usr/bin/python be + specifically version 2.3: + - derive python version from debian/control, not from dpkg -l + - pass PYTHON=python2.3 explicitly into configure + * rules: clean rule: Seek and destroy _all_ *.pyc files. There were + a few we didn't catch before, buried in the testsuite. + * Remove various unneeded files from language bindings (Closes: #310777) + - libsvn-core-perl.install: don't install /usr/lib/*.{a,la,so} + - python2.3-subversion.install: likewise + - libsvn-javahl.install: don't install /usr/lib/jni/*.{a,la} + - rules: delete *.{a,la} from python2.3/site-packages/libsvn + * control: build-depends on libapr0-dev (>= 2.0.55-3). + Earlier versions of libapr0 will try to make us link to libdb4.2. + * subversion.NEWS, README.db4.3: document db4.2 -> db4.3 upgrade. + * patches/no_extra_libs.patch: new patch to prevent linking to several + unneeded libraries. (Closes: #336373, which was caused by linking to + libssl0.9.8.) + - debian/control: Remove several depends and build-depends we are no + longer using because of this + * patches/commit-email-warning.patch: new patch to eliminate a harmless + warning in a hook script. (Closes: #336781) + * patches/perl-test-clean.patch: new patch to avoid leaving several + /tmp/svn-perl-test-xxxxxx dirs. + * patches/swig-1.3.27-hack.patch: new patch to avoid FTBFS from bad + interaction of swig 1.3.27 and . A *really* ugly hack. + + [ Adam Conrad ] + * Switch to using DB4.3 instead of DB4.2, as libapr0 has + (Closes: #335455, #335438) + - Bump build-dep and libsvn0-dev dep from libdb4.2-dev to libdb4.3-dev + - Bump subversion and libapache2-svn deps from db4.2-util to db4.3-util + + [ Troy Heber ] + * Added note about the requirement for nfs-common when your repository lives + on a NFS volume. (closes: #316097) + * Changing the default behavior to not use apr_generate_random_bytes(), + Debian use the system APR which is configured to use /dev/random. In cases + where the entropy pool is drained svn commands can block waiting. Removing + the call to apr_generate_random_bytes and using the fallback apr_time_now + instead. (closes: #285708, #298822) + + -- Peter Samuelson Fri, 2 Dec 2005 16:22:44 -0600 + +subversion (1.2.3dfsg1-2) unstable; urgency=low + + * Use DH_OPTIONS=-Nlibsvn-javahl in debian/rules, rather than the + Architecture fields in debian/control, to disable the java package. + Due to misuse of debhelper, the last attempt didn't work. And I think + this way is nicer anyway. Suggested by Steve Langasek. + + -- Peter Samuelson Wed, 19 Oct 2005 04:27:51 -0500 + +subversion (1.2.3dfsg1-1) unstable; urgency=low + + [ Guilherme de S. Pastore ] + * debian/control: + - changed section of libsvn-core-perl to perl + - changed section of libsvn-javahl to devel + - bump to Standards-Version 3.6.2.1 with no changes + * debian/rules: + - minor cleanups + - removed remnants of control auto-generation + + [ Peter Samuelson ] + * Re-repack orig tarball to eliminate the tar-in-tar arrangement + * debian/rules: adjust to build without the tar-in-tar + - configure and build in ./BUILD + - 'clean' removes ./BUILD and files from autogen.sh + - adjust a lot of installation source paths + - pass both DEB_SRCDIR and DEB_BUILDDIR into debian/tools/Makefile + * debian/tools/Makefile: support separate src and build dirs + * debian/rules: modernise use of debhelper + - use dh_install instead of dh_movefiles + - move pathnames out of rules, into *.install, *.dirs, *.docs, *.examples + - side effect (but correct): move libsvn_swig_* from libsvn0{,-dev} + to python2.3-subversion and libsvn-core-perl + - install Java libraries to /usr/lib/jni, not /usr/lib (Closes: #327789) + * debian/rules, debian/control: disable libsvn-javahl on arm, armeb, + mips, mipsel, on advice from Jeroen van Wolffelaar. It seems kaffe + may remain broken on these architectures for a while. (Closes: #329184) + * debian/rules: rip out "architectures to run full testsuite on" logic, + on advice from Steve Langasek. It is not safe to assume that + debian-specific changes to an upstream release will never cause test + failures. Local admins can still use DEB_BUILD_OPTIONS=notest to + speed up a local compile. + * debian/control: relax all versioned build-deps; all the versions are + satisfied in sarge (and most of them in woody). + * debian/rules, debian/subversion-tools.{postinst,postrm,install}: + - move /usr/lib/subversion to /usr/share/subversion (Closes: #330824) + - move hot-backup.py to /usr/share/doc/subversion/examples + - create compat symlink /usr/lib/subversion + * debian/control: remove pkg-subversion-maintainers from Uploaders - it's + not the right place to document the existence of a list + * debian/control, debian/rules: build with kaffe-pthreads specifically + (works around a FTBFS with kaffe 1.1.6) + + -- Peter Samuelson Tue, 18 Oct 2005 03:03:27 -0500 + +subversion (1.2.3a-1) unstable; urgency=low + + * Welcome the Debian Subversion Team (Closes: #322257) + + [ Guilherme de S. Pastore ] + * New upstream release (Closes: #320417) + - tarball repackaged without svnbook, as it's licensed under + a non-DFSG-free license (Closes: #215083, #218185, #314154) + - fixes export segmentation fault with versioned items in + "deleted" state (Closes: #314381, #316133, #316227, #320572, #324037) + * debian/compat: + - bump to debhelper compatibility version 4 + - no longer export DH_COMPAT from inside debian/rules + * debian/control: + - dropped auto-generation with m4 + - dropped build-dependency on quilt + - bump to Standards-Version 3.6.2 with no changes + - removed Conflicts/Replaces on all packages not present in + stable anymore (Closes: #310519) + * debian/patches/ltmain.sh.patch: + - removed; applied upstream + * debian/patches/kaffe-cast.patch: + - removed; broken and unnecessary + * debian/subversion.doc-base.book: + - removed; the book is no longer present + * debian/README.Debian: + - Removed; was doing the work of a package description, and + mentioned the (removed) svnbook + * debian/python2.3-subversion.README.Debian: + - Renamed from pythonX.Y-subversion.README.Debian, we longer + use that auto-generation stuff + * debian/rules: + - tiny fixes to unbreak the build process + - include simple-patchsys.mk from CDBS instead of using quilt; + it was too complex for our needs + - fixed detection of tarballs, as to not get confused by CDBS + auto-generated lists, which would cause the build to fail + - no longer do any magic to auto-generate debian/control and + python related documentation; too complex for too little gain + - set LANG to C, otherwise the build may fail because of tests + failing for not being able to recognize strings returned by + some tools + - no longer do any magic to support builds on pre-sarge + environments; the package is already complex enough without + supporting old cruft unnecessarily + * Removed packaging documentation, as it was pretty much outdated + * Removed maintenance scripts from the package; left them + on the 'tools' section of the repository on svn.debian.org + + [ David Kimdon ] + * Do not install vc-svn.el (closes: #314213, #315100, #324633) + * Autoload psvn.el by default. (closes: #223303, #235905, #305953) + * Remove hard-coded DEB_BUILDDIR from debian/rules. + * Enable javahl bindings by default (closes: #271125, #323839) + + [ Peter Samuelson ] + * debian/patches/l10n-segfault.patch: + - fixes a "svn add" crash in the es, fr, it, pl, pt_BR and zh_TW + locales (Closes: #316143, #323376, #326079) + * debian/patches/rpath.patch: + - port to subversion 1.2.x and reenable (work in progress, suppresses + most rpaths) + * debian/lintian-overrides: new file for binary package overrides + * debian/rules: + - support DEB_BUILD_OPTIONS=noopt + - invent a DEB_BUILD_OPTIONS=notest to disable the test suite more + easily + - the INSTALL file is redundant, do not install it in /usr/share/doc + - change #!/usr/bin/env python to #!/usr/bin/python2.3 in assorted + scripts + - split and install lintian-overrides to appropriate packages + - minor cruft removal + + -- Guilherme de S. Pastore Fri, 9 Sep 2005 14:57:03 -0300 + +subversion (1.2.0-1) unstable; urgency=low + + * New upstream release. (Closes: #310474) + * Fixes many bugs (some of these may have actually been fixed + before 1.2.0, in any case they are now fixed) : + svndumpfilter: no crash on 64-bit platforms (Closes: #309161) + symlink now works in "svn merge" (Closes: #296046) + svnserve does ipv6 (Closes: #235755) + svn no longer can export non-existent files (Closes: #279080) + svn status "R" is documented in the svn book: (Closes: #269021) + Fix auth problem (Closes: #269165) + svn diff handles ctrl-c (Closes: #266973) + * Build-conflict with libsvn0 (<<1.2). This is a work-around to + Debian bug 291641. + * The subversion book source has moved out of this package, install a + pre-built book. + + -- David Kimdon Wed, 8 Jun 2005 22:19:21 -0700 + +subversion (1.1.4-2) unstable; urgency=high + + * Put call to dh_installdeb after call to dh_python. Fixes purge + of python2.3-subversion (closes: #308777) + * Disable full testsuite. All archs have already past it. No need to + burden the autobuilders with all the tests. + * Set DEB_BUILDDIR correctly since something is apparently setting it + incorrectly. + + -- David Kimdon Thu, 12 May 2005 21:04:56 -0700 + +subversion (1.1.4-1) unstable; urgency=low + + * New upstream release. (Closes: #303179) + * Set LC_ALL for testsuite so build runs in a known environent. + (closes: #301495) + * Omit unnecessary svn.vim (now included in the standard vim distribution) + (closes: #298901) + * Try again to get -O2 in CFLAGS. (closes: #303744) + + -- David Kimdon Sun, 27 Mar 2005 20:43:17 -0800 + +subversion (1.1.3-3) unstable; urgency=low + + * Add -O2 to CFLAGS. + * Fix trac's revision log (closes: #299817) + patche thanks to Torsten Landschoff + + -- David Kimdon Fri, 25 Feb 2005 20:25:02 -0800 + +subversion (1.1.3-2) unstable; urgency=low + + * Patches thanks to Torsten Landschoff + - Let cdbs handle updating config.{sub|guess}. + - Support swig 1.3.24. (closes: #295452) + * Remove old upgrade notes from README.Debian. + * Fix doc url (closes: #293310) + + -- David Kimdon Sun, 20 Feb 2005 11:31:34 -0800 + +subversion (1.1.3-1) unstable; urgency=low + + * New upstream release. (closes: #290610, #288344, #290381) + - remove r12102.patch as it is integrated in this upstream release. + * Make libsvn0 conflict with libsvn-core-perl (= 1.0.9) (closes: #290807) + * Allow the build to use a 1.3.22 swig version since the Debian + version is patched to include the necessary runtime libraries. + * Don't start description synopses with a capital letter, make homepage + consistent explicit in package description (as suggested by the + Developer's Reference). + * Be more explicit about what the default apache module configuration + allows. Default to a read-only repository for non-anonymous + users. (closes: #277303) + * The book isn't being built properly, stop building it and use the + version that is shipped with the tarball (closes: #282393). + + -- David Kimdon Sat, 15 Jan 2005 14:12:54 -0800 + +subversion (1.1.1-2) unstable; urgency=low + + * Fix minor incompatability between 1.0 and 1.1 libraries. + (closes: #275545) + * Remove conditionals and variables that allow debian/rules to + support building subversion 1.0. + * Re-enable debian/patches/rpath.patch. This get rpath out of + some of the binaries. + * Minor build system fixes. + * python2.3-subversion now Conflict/Replace's python2.1-subversion + (closes: #281047) + * Mention DAV in description of libapache2-svn package. + (closes: #277301) + * Uncomment section markers in default configuration files. It is easy + to uncomment the option, but not the section marker and then wonder + why the change has not taken effect. (closes: #278162) + * Fix path to subversion book. (closes: #285240) + + -- David Kimdon Sun, 5 Dec 2004 10:26:12 -0800 + +subversion (1.1.1-1) experimental; urgency=low + + * New upstream release. (closes: #272000) + * Fix hard-coded swig version in debian/rules (closes: #276838) + * Mention 'dav' in the description of libapache2-svn so the package + is easier to find. (closes: #277302) + * Create libsvn-core-perl dependency on libsvn0 via the shlibs file + so the version is taken into account. (closes: #279439) + + -- David Kimdon Sat, 30 Oct 2004 07:59:52 -0700 + +subversion (1.1.0-1) experimental; urgency=low + + * New upstream release. + * Make debian/control.in a double-colon rule. This allows us to + build with old and new versions of cdbs. We are not using + cdbs's debian/control rule. + * Increase debhelper build dependency to 4.1.25 since we use + dh_python. + * Increase version number to prevent this package from being + removed from experimental. (1.0.8-1 has been uploaded to + unstable.) + * Disable testsuite on powerpc since I just ran it. + * Build depend on swig >= 1.3.22-2 so we get a runtime library + and the build doesn't fail. + + -- David Kimdon Sat, 25 Sep 2004 10:11:12 -0700 + +subversion (1.0.6+1.1.0rc4-1) experimental; urgency=high + + * New upstream release. + * CAN-2004-0749: mod_authz_svn fails to protect metadata + + -- David Kimdon Fri, 24 Sep 2004 20:38:15 -0700 + +subversion (1.0.6+1.1.0rc2-1) experimental; urgency=low + + * New upstream release. + * Build system changes so we can easily support subversion 1.1.x. + * Minor build changes to support 1.1.x. + + -- David Kimdon Wed, 8 Sep 2004 22:36:04 -0700 + +subversion (1.0.6-2) unstable; urgency=high + + * This package is source equivalent to 1.0.6-1. + * Remove debian/patches/apr_dir_make.patch as this is now fixed + in the apache2 version we depend on. + * Build depend on apache2 >= 2.0.50-11 so we get all fixes. + * Put version number to something that katie will not interpret as + a binary NMU. + + -- David Kimdon Wed, 1 Sep 2004 22:03:43 -0700 + +subversion (1.0.6-1.2.1) unstable; urgency=high + + * Binary non-maintainer upload by temporary maintainer. + + -- Matt Kraai Thu, 26 Aug 2004 15:06:09 -0700 + +subversion (1.0.6-1.2) unstable; urgency=high + + * Non-maintainer upload with maintainer approval. + * Reverting the apache2/apr LFS transition by bumping our build-dep + to (>= 2.0.50-10), as the apache2 maintenance team has decided that + the ABI transition, while desireable, just wasn't manageable this + close to a release. + * Re-enable the testsuite on all arches to make sure all this ABI + buggery hasn't, well, buggered anything. + + -- Adam Conrad Fri, 20 Aug 2004 10:34:24 -0600 + +subversion (1.0.6-1.1) unstable; urgency=medium + + * Non-maintainer upload by temporary maintainer. + * Work around the apr_dir_make bug in Apache 2.0.50 (closes: #256909). + * Update apache build-dep to >= 2.0.50-9 (closes: #266170, #266193). + + -- Matt Kraai Tue, 17 Aug 2004 04:31:49 -0700 + +subversion (1.0.6-1) unstable; urgency=high + + * New upstream release. + - fix mod_authz_svn COPY security hole (closes: #261938) + * Depend on exim4 rather than exim. (closes: #255363) + * Link libsvn_swig_perl-1.so with all the libraries it depends on. + (closes: #262025) + * Update neon build-dep to >= 0.24.7. + * Update apache build-dep to >= 2.0.50. + * Refresh debian/patches/repos-templates.patch. + * Add build-dep on libkrb5-dev. + * Fix permissions on libsvn-core-perl shared libraries. + * Only remove modules from apache's configuration when we are + removing libapache2-svn, not on upgrades. (closes: #251245) + Additionally, move the module config manipulation from the postrm + to the prerm. This way there is no time when apache is configured + to load a module that is not present on the system. + + -- David Kimdon Sun, 20 Jun 2004 15:34:57 +0200 + +subversion (1.0.5-1) unstable; urgency=low + + * New upstream release. + - Fix CAN-2004-0413: Subversion svn:// protocol string parsing error. + (closes: #253694) + * Update build-depends to neon 0.24.6. + * Fix broken /etc/emacs/site-start.d/vc-svn.el (closes: #250058) + + -- David Kimdon Mon, 24 May 2004 14:45:09 +0200 + +subversion (1.0.3-1) unstable; urgency=high + + * New upstream release. + - fix CAN-2004-0397 : Subversion remote vulnerability + (closes: #249791) + + -- David Kimdon Wed, 19 May 2004 20:31:15 +0200 + +subversion (1.0.2-5) unstable; urgency=low + + * Fix apache modules link in a cleaner way. Previously I had some + hard-coded link lines in debian rules. The present change modfies the + subversion build system itself to hopefully do the right thing in all + cases. This change is less invasive and should allow all archs to + build. (closes: #246903) + + -- David Kimdon Sun, 2 May 2004 11:09:20 +0200 + +subversion (1.0.2-4) unstable; urgency=low + + * Remove 'sudo' line that I didn't mean to commit and got included + in 1.0.2-3. Thanks to Norbert Tretkowski for noticing. + + -- David Kimdon Sat, 1 May 2004 14:07:28 +0200 + +subversion (1.0.2-3) unstable; urgency=low + + * Fix apache modules link. (closes: #246258) + + -- David Kimdon Sat, 1 May 2004 09:26:23 +0200 + +subversion (1.0.2-2) unstable; urgency=low + + * Fix python interpreter in svnshell. (closes: #245473) + * Include manpage for svn_load_dirs. Thanks to Per Olofsson. + (closes: #245630) + * Remove rpath from shared libraries. + * Archs not marked to run the testsuite will now still run basic_tests.py + * Disable full testsuite on archs that have passed it for 1.0.2-1. + + -- David Kimdon Fri, 23 Apr 2004 20:53:43 +0200 + +subversion (1.0.2-1) unstable; urgency=low + + * New upstream release. + * fix assertion failure in vwrite_tuple() (closes: #241076) + * Remove shlibs.local (closes: #244466) + * Put back in svnshell, patch the error messages so they are not + confusing (closes: #234462). + * Point to /usr/bin/svnshell as an example to help get started using + the pythong bindings. (closes: #239924) + * subversion now suggests subversion-tools. This may make it easier + to find the tools contained in subversion-tools. (closes: #243917) + + -- David Kimdon Sun, 18 Apr 2004 16:09:55 +0200 + +subversion (1.0.1-3) unstable; urgency=low + + * Fix python2.3-subversion and subversion-tools priority so they are + the same as the priorities in the override file. + * Fix libtool problem by no longer doing the LIBTOOL_IS_A_FOOL + hack. (closes: #242460) + * Fix hard-coded link in debian/rules to link with ptoper swig. + + -- David Kimdon Sat, 3 Apr 2004 11:13:29 +0200 + +subversion (1.0.1-2) unstable; urgency=low + + * Apply changes up to the current head of the 1.0.x branch. + This line is making its way to become 1.0.2. The diff was + obtained like this: + svn diff http://svn.collab.net/repos/svn/tags/1.0.1 \ + http://svn.collab.net/repos/svn/branches/1.0.x@9275 + - Fix recursive propset (closes: #238558) + * Increase swig build dependancy to 1.3.21-2 so we get a working + dependancy. (closes: #237230) + + -- David Kimdon Fri, 2 Apr 2004 20:19:46 +0200 + +subversion (1.0.1-1) unstable; urgency=low + + * New upstream release. + * Change libsvn0-dev and subversion-tools priority to extra so that + there is no longer a disparity between the override file and the + control file. + * cvs2svn is no longer part of this package, request for package filed, + see http://bugs.debian.org/237934 . + * libswig1.3 provides an incorrect shlibs file, add proper dependancies + to debian/shlibs.local (closes: #220107) + + -- David Kimdon Thu, 11 Mar 2004 12:21:33 +0100 + +subversion (1.0.0-2) unstable; urgency=low + + * Apply changes up to the current head of the 1.0.x branch. + This line is making its way to become 1.0.1 which is expected + to be released soon. The diff was obtained like this: + svn diff http://svn.collab.net/repos/svn/tags/1.0.0 \ + http://svn.collab.net/repos/svn/branches/1.0.x@8939 + - Fix directory walk ordering on filesystems that don't return + '.' first. (closes: #231364) + - Many other fixes. + * Fix description of the subversion book (it is a version control, + not a revision control system) + * Remove local copy of patchsys-quilt.mk and add version to quilt build-dep. + * Don't strip binaries if 'nostrip' is in DEB_BUILD_OPTIONS. + * Patch from Erno Kuusela to 50vc-svn.el so subversion vc backend doesn't + supersede an existing default. + * Don't ship .pyc files in pythonX.Y-subversion. These files should instead + be generated in the postinst. (closes: #236170) + * Detect if debian/control is invalid. If invalid then recreate it and + exit failure telling the user to try again. (closes: #204253) + * Add debian/shlibs.local which needs to stay around until #231659 + is fixed (closes: #234932). + * Fix broken stamp files that were among other things making the build + execute the configure and autogen rules unnecessarily. + * Update to policy 3.6.1 (no changes). + + -- David Kimdon Mon, 23 Feb 2004 22:32:22 +0100 + +subversion (1.0.0-1) unstable; urgency=low + + * New upstream release. + - INSTALL no longer says Subversion is alpha. (closes: #232945) + - Remove cvs2svn manpage. + * Fix formatting of NEWS.Debian. (closes: #232940) + * Put version in shlibs file. In the last upload I removed all version + info from the shlibs file rather than converting = to >=. + * Enable testsuite on many archs. + * Build with srcdir == builddir. This fixes some problems in the + perl bindings and generally makes the build system cleaner. + * Remove svnadmin-static. With the build system changes it wasn't + easy to keep it and we won't need it for a while if ever. + + -- David Kimdon Sat, 21 Feb 2004 08:49:04 +0100 + +subversion (0.37.0-3) unstable; urgency=low + + * When saying you need to dump/reload your repository it is helpful + to provide the path to the manual which describes how to do so. + (closes: #231176) + * Include README and HACKING. (closes: #218052) + * Mention to abbreviation 'svn' in short package descriptions. + (closes: #231698) + * shlibs file now creates a >= dependancy rather than a strict =. + (closes: #231681) + * Don't include svnshell. It is just an example of how to use the + bindings and isn't for general consumption. (closes: #230534) + * New package libsvn-core-perl. (closes: #208935) + * Fix doc build by giving the new path to the docbook stylesheets. + (closes: #231981) + * Start using 'quilt' and part of 'cdbs' to maintain separate pataches + within the source package. + * Fix default repos templates. (closes: #210901) + * Update swig build-dep to >= 1.3.21. This isn't actually required + by Subversion but I have some current Subversion bug reports that + indicate mixing 1.3.19 builds with 1.3.21 systems may cause problems. + * Pass fulll path the swig to configure so as to ensure we use the swig + from the Debian package. + * Don't pass broken CFLAGS to swig wrapper build (closes: #232591) + + -- David Kimdon Sat, 7 Feb 2004 00:00:41 +0100 + +subversion (0.37.0-2) unstable; urgency=low + + * Remove more references to Subversion being alpha (closes: #230744) + * Fix up debian/build.sh so the source package has all necessary files. + (closes: #230948) + * It looks like all archs have built the new swig now, so try this build + again (closes: #230955) + * NEWS.Debian and README.Debian made references to subversion + 0.35.1-1 which was never uploaded. Fix those references so they point + to 0.37.0-1. + + -- David Kimdon Mon, 2 Feb 2004 19:56:12 +0100 + +subversion (0.37.0-1) unstable; urgency=low + + ** NOTE: Repository dump/reload required. See NEWS.Debian ** + + * New upstream release. + - Subversion is getting close to the 1.0 release (closes: #193062) + - svnserve ssh now accepts user@host (closes: #202885) + * Rebuild against new libapr. (closes: #230311) + * doc build has changed since the last release, update so it still builds. + * Add build-conflicts against broken libtool 1.5-6. + * Don't build book since the source distribution already provides + us with a built book. + * Build with Berkeley DB 4.2. + * Increase required apache2 version to 2.0.48-7 so we build with the + same version of Berkeley DB. + * No longer install binaries that include debug symbols. + * Autogenerated cruft is no longer part of the source package's diff. + * Update debian/copyright notice for 2004. + * The default /etc/subversion/config and /etc/subversion/servers are now + generated as part of the build. + * Link libsvn_swig_py properly. (closes: #220107) + * Remove note from debian/control saying that this is an alpha release. + + -- David Kimdon Tue, 18 Nov 2003 21:39:50 +0100 + +subversion (0.33.0-1) unstable; urgency=low + + * New upstream release. (closes: #220672) + - fix internal diff library (closes: #218406, #220474) + - cvs2svn fixed (closes: #216868) + * Change build dependancy from apache2-devb to apache2-threaded-dev. + * Remove hack to get around broken apr-config now that bug #197685 is + fixed. + * Build depend on docbook-xsl rather than docbook-xsl-stylesheets. + (closes: #220788) + * Now that neon 0.24.4 is available increase build dependancy to require + it. Subversion itself doesn't require the new version but there are + enough bug fixes in that version of neon that it is better to use it. + * Enable mod_dav_fs in libapache2-svn.postinst (closes: #219620) + * Fix propchange-email.pl and commit-access-control.pl interpreter + (closes: #220692) + * Corrent python invocation in svnperms.py. + * Update /etc/subversion/{config,servers} + * Update debian/copyright. Re-sync with current upstream license (remove + reference to expat-lite, add reference to apr-util). Fix download + URL to point only to http://subversion.tigris.org rather than trying + to show the exact URL since that can change. + + -- David Kimdon Sat, 15 Nov 2003 22:29:33 +0100 + +subversion (0.32.1-1) unstable; urgency=low + + * New upstream release. + New manpages. (closes: #206646) + * The source package shouldn't be in Debian native format. (closes: #216514) + * Update default /etc/apache2/mods-available/dav_svn.conf with some better + comments and bring it up to date with current required syntax. + * Move last dump/reload notes from NEWS.Debian into README.Debian since it + isn't news anymore. + + -- David Kimdon Sun, 19 Oct 2003 19:22:52 +0200 + +subversion (0.31.0-1) unstable; urgency=low + + * New upstream release. + * Remove Matt Kraai from Uploaders field. Thanks for all the help + Matt! + * Wrote debian/tools/svn-make-config.c which is a tool that helps to + create default config files. Maybe this can be included upstream + somehow. Update /etc/subversion/{config,servers} + * Include svnadmin-static manpage. + + -- David Kimdon Tue, 7 Oct 2003 07:03:12 +0200 + +subversion (0.30.0-2) unstable; urgency=low + + * Adjust dynamic linker search path and location of svnversion + binary so the book build doesn't generate a spurious error message. + As a bonus the version number in the built doc should be correct + now instead of saying 'Draft'. + * Set XSL_DIR when building the docs so we can find things like + docbook.xsl. It appears as though this succeeded when I built + 0.30.0-1 because make didn't need to recreate the documentation + completely. On the autobuilders this was not the case. + (closes: #213116) + + -- David Kimdon Sun, 28 Sep 2003 21:24:55 +0200 + +subversion (0.30.0-1) unstable; urgency=low + + * New upstream release. + * Update /etc/subversion/{config,servers} + + -- David Kimdon Wed, 24 Sep 2003 22:15:17 +0200 + +subversion (0.29.0-2) unstable; urgency=low + + * Force neon build dependancy and libsvn0-dev dependancy to libneon24. + In reality neon 0.23.9 or greater will work, but since we need to + hard-code the version in the libsvn0-dev dependnacy it is simpler to just + force libneon24. (closes: #206031) + * Disable testsuite on archs where it has passed. + * Remove unneeded, crufty shlibs.local. + * Make debian/control read-only to discourage edits to it rather than + debian/control.in. (closes: #211091) + * Drop debhelper build dependancy back to >=3 so it is easier to + build the package on old systems. + * Actually install NEWS.Debian rather than having it sit in the + source package where no one can see it. (closes: #210684, #210822) + * Update /etc/subversion/config and /etc/subversion/servers + * Make package descriptions more clear and detailed. (closes: #210065) + * Fix commit-email.pl (closes: #211577) + * Remove extra hyphen in subversion.preinst rm's and make a note + about why we are doing the rm. + + -- David Kimdon Sun, 14 Sep 2003 09:04:35 +0000 + +subversion (0.29.0-1) unstable; urgency=low + + * New upstream release: + - Work with neon 0.24 (closes: #206031). + - Handle tool rearrangment, thanks to Kevin M. Rosenberg (closes: + #208813). + * Require debhelper 4.1.51 or later to install NEWS.Debian. + + -- Matt Kraai Fri, 05 Sep 2003 16:14:51 -0700 + +subversion (0.27.0-1) unstable; urgency=low + + * Merge multi-line depends and build-depends fields (closes: #203413). + * Fix verb conjugations in libapache2-svn's description (closes: + #203417). + * Change Apache location from /svn/repos to /svn (closes: #203301). + * Change the default repository location to /var/lib/svn. + * Force dependencies on libsvn0 to require the same version that was + used to build (closes: #203454). + * Move svnindex.css and svnindex.xsl to /var/www/apache2-default in + libapache2-svn (closes: #203749). + * Include "svn" in the description of subversion (closes: #204179). + * Regenerate control (closes: #205311). + + -- Matt Kraai Thu, 14 Aug 2003 16:22:04 -0700 + +subversion (0.26.0-1) unstable; urgency=low + + * Add self to Uploaders. + * New upstream release: + - Handle absolute paths in svn_load_dirs.pl (closes: #187331). + - Call Cmd.__init__ in svnshell.py (closes: #198140). + - Handle paths containing quotes in cvs2svn (closes: #201290). + * Build-depend on apache2-dev (>= 2.0.47), libapr0-dev (>= 2.0.47), and + libneon23-dev (>= 0.23.9). + * Include fixes from 0.25-0.1 (closes: #198304, #199015, #199710, + #200657, #201009). + * Add perl (>= 5.8.0-7) to subversion-tools's dependencies (closes: + #191138). + * Add liburi-perl (>= 1.17-1) to subversion-tools's dependencies + (closes: #198143). + * Rename libapache2-dav-svn to libapache2-svn and include mod_authz_svn + (closes: #198182). + + -- Matt Kraai Thu, 24 Jul 2003 05:55:37 -0700 + +subversion (0.25-0.1) unstable; urgency=low + + * Non-maintainer upload. + * New upstream release. + * Add missing files to python2.2-subversion (closes: #199015). + * Make subversion-tools replace subversion (<< 0.22.1-1) + (closes: #198304). + + -- Matt Kraai Sat, 12 Jul 2003 15:29:45 +0200 + +subversion (0.24.2-1) unstable; urgency=low + + * New upstream release + * Fix quoting error in debian/rules that was breaking the swig build. + * Add shlibs.local to work around problems like bug 197989. + + -- David Kimdon Wed, 18 Jun 2003 18:06:55 -0700 + +subversion (0.24.1-1) unstable; urgency=low + + * New upstream release : + - no long includes svn-deisgn info document (closes: #196412) + * strip svnadmin-static. It is very large and not needed for + debugging since the shared version of svnadmin can be used as long + as the package is installed. + * Follow apache2 change to module build helper (apxs -> apxs2). + (closes: #196577) + * Update apache2 and apr build dependancy. + * Build fixes thanks to Michael Cardenas + * Update build dependancy libsasl-dev -> libsasl2-dev. + * svn-design.info is no longer built, remove texinfo build-dep. + * Update apache2 example configuration based on input from + solo turn (closes: #197089) + * Don't attempt to load vc-svn when package has been removed and + only conffiles remain, patch thanks to Kalle Olavi Niemitalo + (closes: #193427) + * work around problem with apr-config (see bug #197685). + + -- David Kimdon Sun, 1 Jun 2003 20:45:05 -0700 + +subversion (0.23.0-2) unstable; urgency=low + + * Abort build on testsuite failure. + * Create a proper source package. (closes: #194517) + * Fix export over ra_svn. Thanks to Branden Robinson for the fix and + offering to NMU. (closes: #193060) + * Update comment-out vc-svn autoload commands to avoid problems with + xemacs. Thanks to Kalle Olavi Niemitalo for the + problem analysis and patch. (closes: #191632) + * Disable testsuite on archs that passed 0.23.0-1. + + -- David Kimdon Thu, 22 May 2003 09:52:35 -0700 + +subversion (0.23.0-1) unstable; urgency=low + + * New upstream release. + * Add build-dep on xsltproc, docbook-xsl-stylesheets, create + html version of book during build. + * Update to standards version 3.5.10 (no changes). + + -- David Kimdon Mon, 19 May 2003 18:34:24 -0700 + +subversion (0.22.2-1) unstable; urgency=low + + * New upstream release. + * Don't strip objects. This is a deliberate policy violation. The + goal is to lower the barrier to anyone wishing to debug this + software. See the notes in Bug#193062 for more info. + * Let debhelper create conffiles. + * Include perl dependancy information in subversion-tools package + (closes: #191138, #187324). + * Disable testsuite on archs that passed 0.22.1-1. + + -- David Kimdon Tue, 13 May 2003 18:20:44 -0700 + +subversion (0.22.1-1) unstable; urgency=low + + * New upstream release. + * Tone down the warning in the package description about data loss, simply + indicate that this software is still in development. + * Apply 0.21.0 changes to debian/control.in that were erronously applied + only to debian/control. (closes: #190353) + * Include HACKING in /usr/share/doc/subversion/. (closes: #191450) + * Don't automatically load emacs lisp files. The bindings can still be + enabled by the system administrator uncommenting the lines in + /etc/emacs/site-start.d. (closes: #190804) + * Update build dependancy to require more recent apache2-dev and + libapr0-dev (closes: #192595) + * Speed up ./debian/rules by limiting the number of times we exec dpkg. + * Add versioned build-dep on debhelper. + * Move the python script /usr/bin/svnshell from the 'subversion' + package into the 'subversion-tools' package. ('subversion-tools' + already had a python dependancy) + + -- David Kimdon Thu, 8 May 2003 08:16:13 -0700 + +subversion (0.21.0-1) unstable; urgency=low + + * New upstream release. + * Include svnshell. (closes: #187446) + * Include svnindex.css and svnindex.xsl. (closes: #185465) + * Make subversion priority optional. (closes: #188141) + * Update to policy 3.5.9 (no changes). + * Fix svn-dev.vim (closes: #187937). + * Fix emacs svn-status-mode (closes: #188706). + * Remove subversion-server package (closes: #182653). As indicated + in the bug report the subversion-server package was only necessary if + one wanted to use subversion with apache. I don't see a compelling + need for the subversion-server package, all it did is depend on + subversion, subversion-tools and libapache2-dav-svn. + + -- David Kimdon Wed, 16 Apr 2003 00:37:05 -0700 + +subversion (0.20.1-2) unstable; urgency=low + + * Fix svnversion breakage, again, sigh. This time with a fix that + is easier to maintain (no longer need to patch upstream source). + (closes: #186966) + * Fix improperly generated source package (was in Debian native format). + * Update package sections for libsvn0-dev and python2.2-subversion + based on new archive sections. + * Update debian/copyright (fix spelling of 'acknowledgment' and + extend copyright to 2003). + * Remove NEWS.Debian (was news from 0.17) + * Update /etc/subversion/[config,servers] + + -- David Kimdon Mon, 31 Mar 2003 07:34:01 -0800 + +subversion (0.20.1-1) unstable; urgency=low + + * New upstream release. + + -- David Kimdon Sun, 30 Mar 2003 18:14:01 -0800 + +subversion (0.20-1) unstable; urgency=low + + * New upstream release. + + -- David Kimdon Thu, 20 Mar 2003 21:43:10 -0800 + +subversion (0.19.1-2) unstable; urgency=low + + * Fix psvn.el autoload. (closes: #185130) + * Fix autobuild failure. (closes: #185088) + * Minor update to /etc/subversion/servers. + + -- David Kimdon Mon, 17 Mar 2003 07:00:17 -0800 + +subversion (0.19.1-1) unstable; urgency=low + + * New upstream release. + * Install psvn.el and vc-svn.el so they are autoloaded by emacs, + thanks to Martin Pool for a patch. (closes: #184032) + * Retiring svn-[buildpackage|inject] until I update them. + + -- David Kimdon Sun, 9 Mar 2003 18:45:57 -0800 + +subversion (0.18.1-1) unstable; urgency=low + + * New upstream minor release. + * add python fixups from woody backport + * disable testsuite for archs that have passed it + * fixup db tool path in hotbackup.py, again (closes: #182777) + + -- David Kimdon Sun, 23 Feb 2003 13:22:45 -0800 + +subversion (0.18.0-1) unstable; urgency=low + + * New upstream release. (closes: #180910) + - Use new --with-editor configure switch to set default editor to + /usr/bin/editor (closes: #162632, #164371) + - New cvs2svn manpage thanks to Robert Bihlmeyer + (closes: #176576) + * Fixups for woody backport + - libtool patch is back. It is only applied for the versions of libtool + that need it (such as the libtool in woody). + - make the testsuite run on woody. + * Add build-dep on libsasl-dev. + * Make subversion-tools depend on an explicit version of subversion and + python2.2-subversion (closes: #180621) + + -- David Kimdon Sun, 9 Feb 2003 22:16:27 -0800 + +subversion (0.17.1-2) unstable; urgency=low + + * The Berkeley DB update as of 0.17.1-1 requires you to run + 'svnadmin recover /path/to/repos', see README.Debian for + more information. + + * Include prominent note in changelog, README.Debian and + NEWS.Debian indicating steps required for Berkeley DB upgrade. + (closes: #178819) + * Don't include CHANGES twice. (closes: #178694) + * libapache2-dav-svn depends on a specific version of apache2 + (closes: #178833) + * Build-Dep on apache2 packages tightened to >> 2.0.44-6 since -5 + didn't have a non-interative install, this made subversion fail on + some autobuliders. + * Disable testsuite on the archetectures that passed 0.17.1-1. + * Remove version information for libapache2-dav-svn dependancy on + apache2 since apache2 is a virtual package. + + -- David Kimdon Mon, 27 Jan 2003 17:02:31 -0800 + +subversion (0.17.1-1) unstable; urgency=low + + * New upstream release. + * Build against berkeley db 4.1.24. + * Apply some changes from revs 4521:4523 so cvs2svn works. + * Include CHANGES in /usr/share/doc/subversion/. This is the upstream + summary of changes for each release. + * Compile against current libapr (closes: #177836). + * Fix path in svn_load_dirs (closes: #176610). + * Increase verbosity on testsuite so autobuilders don't kill the testsuite + due to inactivity. + * Don't create arch independant packages in the binary-arch target + (closes: #174381) + * Make testsuite run on sparc and alpha. It wasn't previously being run + due to a bug in the shell snippet that determines whether or not we want + it to run. + * Change libapache2-dav-svn dependancy from apache2-common to apache2, + we need one of the mpm's to have a working server (closes: #175902) + * Work-around for duplicate conffile entries created by debhelper. + + -- David Kimdon Sun, 15 Dec 2002 11:08:02 -0800 + +subversion (0.16.0-1) unstable; urgency=low + + * New upstream release. + * update /etc/subversion/config to include webdav compression option + * add back subversion.conffiles, it is needed for older versions of + debhelper. + * /etc/subversion/proxies renamed to /etc/subversion/servers (actually this + happenned with 0.15.0 or so but I forgot to note it here) + * upgrade to policy 3.5.8 + * include the contents of tools/hook-scripts/ in subversion-tools package + (closes: #171997) + * patches from Brandon Ehle to fix swig + build + * cat tests.log on testsuite failure. + * fix the pathnames on some scripts from tools/ on install. + * compile with -Wall + * subversion-tools now depends on exim | mail-transport-agent + * sed cvs2svn at install so we find rcsparse.py (closes: #172284) + + -- David Kimdon Thu, 5 Dec 2002 07:52:24 -0800 + +subversion (0.15.0-2) unstable; urgency=low + + * Fix broken conffile (closes: #171323) + * Don't run testsuite on archs that succeeded with 0.15.0-1. + * remove subversion.conffiles until Bug#126520 is closed. + + -- David Kimdon Sun, 1 Dec 2002 08:28:35 -0800 + +subversion (0.15.0-1) unstable; urgency=low + + * New upstream release. + * Add dependancy on libdb4.0-util for subversion and libapache2-dav-svn + packages. In case a repository gets wedged we want db4.0_recover + available. Fix paths in hot-backup.py (closes: #169797, #169796) + * Doc install cleanup thanks to Jon Middleton + * aprutl version checking hack, thanks to Jon Middleton + * Include a statically linked svnadmin that we can copy to svnadmin-$(VERSION) + on upgrade if the repository format changes. This facilitates a + repository dump/reload. + + -- David Kimdon Fri, 29 Nov 2002 10:19:14 -0800 + +subversion (0.14.5-1) unstable; urgency=low + + * add hot-backup.py (closes: #164870) + * Make swig1.3 build-dep a versioned build-dep (closes: #166301) + * The suggested location of the passwd file for libapache2-dav-svn has + moved from /etc/svn to /etc/subversion since the command line tools + store configuration info in that directory. + * add subversion-tools package. + * Add subversion-server package. This package depends on other packages + that you probably want to have if you are setting up a Subversion server. + * Don't ship svn-design.info anymore. All the info we need can be + found in the Subversion book. + * Subversion handbook is now a xml book, "Subversion : The Definitive Guide" + include the html version of this book. + * Build fixes and updates thanks to Jon Middleton + * Warn users upgrading from versions prior to 0.14.3 that they need to + do a dump/reload (closes: #163092). At some point I'd like to find a + good way of better automating the conversion. + * a few lintian fixes. + + -- David Kimdon Wed, 23 Oct 2002 08:01:54 -0700 + +subversion (0.14.3-3) unstable; urgency=low + + * Put autogen back as a prerequisite for the clean target. I + erroneously removed the autogen.sh run in the last upload, this left + us with a broken libtool. (closes: #164781) + + -- David Kimdon Sat, 19 Oct 2002 09:10:03 -0700 + +subversion (0.14.3-2) unstable; urgency=low + + * Disable testsuite on archs that have already built 0.14.3-1 + * new package python2.2-subversion (based on package created by + the subversion-snapshot source). These python bindings are used + by various scripts that we want to include eventually. + * libtool bug 98342 is fixed. We don't need to patch ltmain.sh anymore + (closes: #163858) + * build against new libapr0 which has a versioned shlibs file + (closes: #162814) + + -- David Kimdon Wed, 25 Sep 2002 22:57:41 -0700 + +subversion (0.14.3-1) unstable; urgency=low + + * New upstream release (closes: #158677) + - build against new libneon (closes: #160270) + - updated manpage (closes: #158834) + * make symlinks in /etc/apache2/ relative rather than absolute + (closes: #161268) + * Change priotiry (optional->extra). + * Update to standards version 3.5.7. + - honor 'nostrip' in DEB_BUILD_OPTIONS + - build with debug info by default + * include default dav_svn.conf in the proper location so + we can disable mod_dav_svn when libapache2-dav-svn is removed + (closes: #158549). + * Use /etc/subversion/config to give us proper editor behavior rather + than patching the C source as I had when I closed Bug#157129. + * Patch libsvn_subr so it respects /etc/subversion/config. + + -- David Kimdon Sat, 24 Aug 2002 11:36:11 -0700 + +subversion (0.14.1-3) unstable; urgency=low + + * rename apache module libapache-dav-svn -> libapache2-dav-svn + to indicate it is an apache2 module (closes: #158133) + * remove libapache-dav-svn dependancy on apache2, we only need to depend + on apache2-common (closes: #158132) + * cleanup handling of config.{sub|guess} + + -- David Kimdon Mon, 26 Aug 2002 21:15:35 -0700 + +subversion (0.14.1-2) unstable; urgency=low + + * Autotools fixes prompted by a failed autobuild and based on recomendations + in /usr/share/doc/autotools-dev/README.Debian.gz + - call configure with --host and --build flags based on the output of + dpkg-architecture + - symlink config.{sub|guess} during build so they are always up to date. + Add build-dep on autotools-dev. + - Call autogen.sh when cleaning the tree. Add versioned build-dep + on autoconf. + * Remove commented python package rule and python2.2-dev build-dep. + (I do plan on making the python package like in subversion-snapshot + in the future but still need to figure some things out.) + + -- David Kimdon Sat, 24 Aug 2002 07:42:49 -0700 + +subversion (0.14.1-1) unstable; urgency=low + + * New upstream version. + * some build fixes thanks to Jon Middleton + * libsvn0-dev priority changed from optional to extra since + libsvn0-dev depends on extra libdb4.0-dev and policy forbids + binary dependancies on packages with lower priorities. + * libneon build dep changed (libneon-dev -> libneon21-dev) + * Conform to policy section 12.4 (Editors and Pagers) which states + that if the EDITOR variable is not set the program should use + /usr/bin/editor when necessary. (closes: #157129) + + -- David Kimdon Fri, 9 Aug 2002 19:29:12 -0700 + +subversion (0.14.0-2) unstable; urgency=low + + * Fix up descriptions to indicate this is no longer pre-alpha, + this is an alpha realease. + * remove version dependancy's from build-deps and libapache-dav-svn deps, + the versions cause more trouble than they are worth and the proper + dependancy will be realized (for the most part) by way of libapr. + * rebuild with new apache2. + + -- David Kimdon Tue, 6 Aug 2002 20:51:36 -0700 + +subversion (0.14.0-1) unstable; urgency=low + + * New upstream. Alpha release. + - fix svn merge segfault (closes: #152461) + - requires new libneon (closes: #152622) + * Updates to svn-[inject|buildpackage]. + * Install /etc/bash_completion.d/subversion. (This allows for + programmable completion for the svn command under bash.) + * Include svn-handbook and svn-design, register properly with info + directory (closes: #153262) + * libsvn -> libsvn0 and other fixes base on recommendations in + Junichi Uekawa's Debian Library Packaging guide. + * Simplify libapache-dav-svn.postrm. + * Add url to package descriptions. + * add build-dep on python-dev (closes: #153199) + * remove build-dep on texi2html and texinfo since build documents are + available in the distribution. + * enable mod_dav in libapache_dav_svn, thanks to minus + for catching the bug. + + -- David Kimdon Sun, 30 Jun 2002 19:44:50 -0700 + +subversion (0.13.0-1) unstable; urgency=low + + * New upstream. + * Actually uploading for real (closes: #97234) + * Build debug version if DEB_BUILD_OPTIONS says to. + * Include hack to fix broken apxs2, we include our own version of apxs2 + and use that during the build. This will go away when apache2-dev + is fixed, that will likely be the release after 2.0.37-2. + * include selection from INSTALL in README.Debian + * Make warnings in debian/control about this being in-development, + pre-alpha software more conspicuous. + * Create /etc/apache2/mods-enabled/dav_svn.{load|conf} symlinks in + libapache-dav-svn.postinst if appropriate files exist in + /etc/apache2/mods-available. Delete these links in + libapache-dav-svn.postrm. + * include identical README.Debian in subversion and libapache-dav-svn + the info is pertinant to both packages. + * write svnadmin manpage + + -- David Kimdon Sat, 8 Jun 2002 08:19:04 -0700 + +subversion (0.12.0-1) unstable; urgency=low + + * New upstream. + * decided to delete apr/, apr-util/ and neon/ subdirs from original tarball. + We aren't using them, they just take up space. + * include experimental svn-inject and svn-buildpackage + * run testsuite during build + * add build-dep on python so we can run the testsuite + * update package descriptions + * bring back libsvn package + + -- David Kimdon Sat, 4 May 2002 09:41:54 -0700 + +subversion (0.11.1-1) unstable; urgency=low + + * New upstream. + * Now we aren't deleting the apr/ and neon/ subdirs, even though + we don't use them. + * add zlib1g-dev, bison, and patch to build depends. + * files previously in libsvn package are now in subversion package, + there aren't any other projects that use those libraries. + * build in build-svn to keep source tree cleaner. + * subversion-server package renamed to libapache-dav-svn + + -- David Kimdon Fri, 12 Apr 2002 20:16:22 -0700 + +subversion (0.10.2-1) unstable; urgency=low + + * New upstream. + * build against new apache2, neon, Berkeley DB + * stop using DBS, it was getting in my way. + * work around libtool bug #98342 with patch from the BTS. + * use Debian's libexpat rather than the included one. + * no longer using autoconf as part of the build. + + -- David Kimdon Wed, 20 Feb 2002 22:52:29 -0800 + +subversion (0.8.0-1) unstable; urgency=low + + * New upstream. + * track releases now rather than snapshots. + * build-depend on libtool, autoconf + * use dbs build scripts from package rather than on filesystem + * /etc/apache2/modules->/etc/apache2/mods-available + * rename packages svn-[server|client]-svn + -> subversion-[server|client]-svn + * change LIBTOOL_IS_A_FOOL hack since libsvn_ra wasn't building + properly + * create /etc/svn/ in subversion-server + + -- David Kimdon Fri, 23 Nov 2001 20:37:16 -0800 + +subversion-svn (473-1) unstable; urgency=low + + * New upstream. + * build against pre-release apache-2.0.28 package + * install manpages and info pages. + * don't strip libmod_dav_svn, otherwise apache can't load it + * get the module name right in dav_svn.load + * create repository in /var/svn in postinst if directory + doesn't exist and set up symlinks for apache2 + * remove dav_svn.conf on purge + * remove rpath + * subversion Debian package is now self-hosting + + -- David Kimdon Fri, 16 Nov 2001 22:01:32 -0800 + +subversion-svn (282-2) unstable; urgency=low + + * libexpat -> libsvn_expat to avoid conflict. + * don't use maintainer-mode b/c apache2 doesn't + * override mod_dav_svn install rule so we can put it in the right + place. + + -- David Kimdon Tue, 23 Oct 2001 08:32:55 -0700 + +subversion-svn (282-1) unstable; urgency=low + + * New upstream version. + + -- David Kimdon Mon, 22 Oct 2001 15:35:25 -0700 + +subversion-svn (256-1) unstable; urgency=low + + * New upstream, various packaging fixes. + + -- David Kimdon Wed, 17 Oct 2001 14:02:58 -0700 + +subversion-svn (252-1) unstable; urgency=low + + * Initial release. + + -- David Kimdon Fri, 28 Sep 2001 20:31:48 -0700 --- subversion-1.7.9.orig/debian/compat +++ subversion-1.7.9/debian/compat @@ -0,0 +1 @@ +7 --- subversion-1.7.9.orig/debian/contrib/commit-email.pl +++ subversion-1.7.9/debian/contrib/commit-email.pl @@ -0,0 +1,838 @@ +#!/usr/bin/env perl + +# ==================================================================== +# This script is deprecated. The Subversion developers recommend +# using mailer.py for post-commit and post-revprop change +# notifications. If you wish to improve or add features to a +# post-commit notification script, please do that work on mailer.py. +# See http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/mailer . +# ==================================================================== + +# ==================================================================== +# commit-email.pl: send a notification email describing either a +# commit or a revprop-change action on a Subversion repository. +# +# For usage, see the usage subroutine or run the script with no +# command line arguments. +# +# This script requires Subversion 1.2.0 or later. +# +# $HeadURL: http://svn.apache.org/repos/asf/subversion/branches/1.6.x/contrib/hook-scripts/commit-email.pl.in $ +# $LastChangedDate: 2010-03-16 15:22:28 +0000 (Tue, 16 Mar 2010) $ +# $LastChangedBy: cmpilato $ +# $LastChangedRevision: 923804 $ +# +# ==================================================================== +# Copyright (c) 2000-2006 CollabNet. All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://subversion.tigris.org/license-1.html. +# If newer versions of this license are posted there, you may use a +# newer version instead, at your option. +# +# This software consists of voluntary contributions made by many +# individuals. For exact contribution history, see the revision +# history and logs, available at http://subversion.tigris.org/. +# ==================================================================== + +# Turn on warnings the best way depending on the Perl version. +BEGIN { + if ( $] >= 5.006_000) + { require warnings; import warnings; } + else + { $^W = 1; } +} + +use strict; +use Carp; +use POSIX qw(strftime); +my ($sendmail, $smtp_server); + +###################################################################### +# Configuration section. + +# Sendmail path, or SMTP server address. +# You should define exactly one of these two configuration variables, +# leaving the other commented out, to select which method of sending +# email should be used. +# Using --stdout on the command line overrides both. +$sendmail = "/usr/sbin/sendmail"; +#$smtp_server = "127.0.0.1"; + +# Svnlook path. +my $svnlook = "/usr/bin/svnlook"; + +# By default, when a file is deleted from the repository, svnlook diff +# prints the entire contents of the file. If you want to save space +# in the log and email messages by not printing the file, then set +# $no_diff_deleted to 1. +my $no_diff_deleted = 0; +# By default, when a file is added to the repository, svnlook diff +# prints the entire contents of the file. If you want to save space +# in the log and email messages by not printing the file, then set +# $no_diff_added to 1. +my $no_diff_added = 0; + +# End of Configuration section. +###################################################################### + +# Check that the required programs exist, and the email sending method +# configuration is sane, to ensure that the administrator has set up +# the script properly. +{ + my $ok = 1; + foreach my $program ($sendmail, $svnlook) + { + next if not defined $program; + if (-e $program) + { + unless (-x $program) + { + warn "$0: required program `$program' is not executable, ", + "edit $0.\n"; + $ok = 0; + } + } + else + { + warn "$0: required program `$program' does not exist, edit $0.\n"; + $ok = 0; + } + } + if (not (defined $sendmail xor defined $smtp_server)) + { + warn "$0: exactly one of \$sendmail or \$smtp_server must be ", + "set, edit $0.\n"; + $ok = 0; + } + exit 1 unless $ok; +} + +require Net::SMTP if defined $smtp_server; + +###################################################################### +# Initial setup/command-line handling. + +# Each value in this array holds a hash reference which contains the +# associated email information for one project. Start with an +# implicit rule that matches all paths. +my @project_settings_list = (&new_project); + +# Process the command line arguments till there are none left. +# In commit mode: The first two arguments that are not used by a command line +# option are the repository path and the revision number. +# In revprop-change mode: The first four arguments that are not used by a +# command line option are the repository path, the revision number, the +# author, and the property name. This script has no support for the fifth +# argument (action) added to the post-revprop-change hook in Subversion +# 1.2.0 yet - patches welcome! +my $repos; +my $rev; +my $author; +my $propname; + +my $mode = 'commit'; +my $date; +my $diff_file; + +# Use the reference to the first project to populate. +my $current_project = $project_settings_list[0]; + +# This hash matches the command line option to the hash key in the +# project. If a key exists but has a false value (''), then the +# command line option is allowed but requires special handling. +my %opt_to_hash_key = ('--from' => 'from_address', + '--revprop-change' => '', + '-d' => '', + '-h' => 'hostname', + '-l' => 'log_file', + '-m' => '', + '-r' => 'reply_to', + '-s' => 'subject_prefix', + '--summary' => '', + '--diff' => '', + '--stdout' => ''); + +while (@ARGV) + { + my $arg = shift @ARGV; + if ($arg =~ /^-/) + { + my $hash_key = $opt_to_hash_key{$arg}; + unless (defined $hash_key) + { + die "$0: command line option `$arg' is not recognized.\n"; + } + + my $value; + if ($arg ne '--revprop-change' and $arg ne '--stdout' and $arg ne '--summary') + { + unless (@ARGV) + { + die "$0: command line option `$arg' is missing a value.\n"; + } + $value = shift @ARGV; + } + + if ($hash_key) + { + $current_project->{$hash_key} = $value; + } + else + { + if ($arg eq '-m') + { + $current_project = &new_project; + $current_project->{match_regex} = $value; + push(@project_settings_list, $current_project); + } + elsif ($arg eq '-d') + { + if ($mode ne 'revprop-change') + { + die "$0: `-d' is valid only when used after" + . " `--revprop-change'.\n"; + } + if ($diff_file) + { + die "$0: command line option `$arg'" + . " can only be used once.\n"; + } + $diff_file = $value; + } + elsif ($arg eq '--revprop-change') + { + if (defined $repos) + { + die "$0: `--revprop-change' must be specified before" + . " the first non-option argument.\n"; + } + $mode = 'revprop-change'; + } + elsif ($arg eq '--diff') + { + $current_project->{show_diff} = parse_boolean($value); + } + elsif ($arg eq '--stdout') + { + $current_project->{stdout} = 1; + } + elsif ($arg eq '--summary') + { + $current_project->{summary} = 1; + } + else + { + die "$0: internal error:" + . " should not be handling `$arg' here.\n"; + } + } + } + else + { + if (! defined $repos) + { + $repos = $arg; + } + elsif (! defined $rev) + { + $rev = $arg; + } + elsif (! defined $author && $mode eq 'revprop-change') + { + $author = $arg; + } + elsif (! defined $propname && $mode eq 'revprop-change') + { + $propname = $arg; + } + else + { + push(@{$current_project->{email_addresses}}, $arg); + } + } + } + +if ($mode eq 'commit') + { + &usage("$0: too few arguments.") unless defined $rev; + } +elsif ($mode eq 'revprop-change') + { + &usage("$0: too few arguments.") unless defined $propname; + } + +# Check the validity of the command line arguments. Check that the +# revision is an integer greater than 0 and that the repository +# directory exists. +unless ($rev =~ /^\d+/ and $rev > 0) + { + &usage("$0: revision number `$rev' must be an integer > 0."); + } +unless (-e $repos) + { + &usage("$0: repos directory `$repos' does not exist."); + } +unless (-d _) + { + &usage("$0: repos directory `$repos' is not a directory."); + } + +# Check that all of the regular expressions can be compiled and +# compile them. +{ + my $ok = 1; + for (my $i=0; $i<@project_settings_list; ++$i) + { + my $match_regex = $project_settings_list[$i]->{match_regex}; + + # To help users that automatically write regular expressions + # that match the root directory using ^/, remove the / character + # because subversion paths, while they start at the root level, + # do not begin with a /. + $match_regex =~ s#^\^/#^#; + + my $match_re; + eval { $match_re = qr/$match_regex/ }; + if ($@) + { + warn "$0: -m regex #$i `$match_regex' does not compile:\n$@\n"; + $ok = 0; + next; + } + $project_settings_list[$i]->{match_re} = $match_re; + } + exit 1 unless $ok; +} + +# Harvest common data needed for both commit or revprop-change. + +# Figure out what directories have changed using svnlook. +my @dirschanged = &read_from_process($svnlook, 'dirs-changed', $repos, + '-r', $rev); + +# Lose the trailing slash in the directory names if one exists, except +# in the case of '/'. +my $rootchanged = 0; +for (my $i=0; $i<@dirschanged; ++$i) + { + if ($dirschanged[$i] eq '/') + { + $rootchanged = 1; + } + else + { + $dirschanged[$i] =~ s#^(.+)[/\\]$#$1#; + } + } + +# Figure out what files have changed using svnlook. +my @svnlooklines = &read_from_process($svnlook, 'changed', $repos, '-r', $rev); + +# Parse the changed nodes. +my @adds; +my @dels; +my @mods; +foreach my $line (@svnlooklines) + { + my $path = ''; + my $code = ''; + + # Split the line up into the modification code and path, ignoring + # property modifications. + if ($line =~ /^(.). (.*)$/) + { + $code = $1; + $path = $2; + } + + if ($code eq 'A') + { + push(@adds, $path); + } + elsif ($code eq 'D') + { + push(@dels, $path); + } + else + { + push(@mods, $path); + } + } + +# Declare variables which carry information out of the inner scope of +# the conditional blocks below. +my $subject_base; +my $subject_logbase; +my @body; +# $author - declared above for use as a command line parameter in +# revprop-change mode. In commit mode, gets filled in below. + +if ($mode eq 'commit') + { + ###################################################################### + # Harvest data using svnlook. + + # Get the author, date, and log from svnlook. + my @infolines = &read_from_process($svnlook, 'info', $repos, '-r', $rev); + $author = shift @infolines; + $date = shift @infolines; + shift @infolines; + my @log = map { "$_\n" } @infolines; + + ###################################################################### + # Modified directory name collapsing. + + # Collapse the list of changed directories only if the root directory + # was not modified, because otherwise everything is under root and + # there's no point in collapsing the directories, and only if more + # than one directory was modified. + my $commondir = ''; + my @edited_dirschanged = @dirschanged; + if (!$rootchanged and @edited_dirschanged > 1) + { + my $firstline = shift @edited_dirschanged; + my @commonpieces = split('/', $firstline); + foreach my $line (@edited_dirschanged) + { + my @pieces = split('/', $line); + my $i = 0; + while ($i < @pieces and $i < @commonpieces) + { + if ($pieces[$i] ne $commonpieces[$i]) + { + splice(@commonpieces, $i, @commonpieces - $i); + last; + } + $i++; + } + } + unshift(@edited_dirschanged, $firstline); + + if (@commonpieces) + { + $commondir = join('/', @commonpieces); + my @new_dirschanged; + foreach my $dir (@edited_dirschanged) + { + if ($dir eq $commondir) + { + $dir = '.'; + } + else + { + $dir =~ s#^\Q$commondir/\E##; + } + push(@new_dirschanged, $dir); + } + @edited_dirschanged = @new_dirschanged; + } + } + my $dirlist = join(' ', @edited_dirschanged); + + ###################################################################### + # Assembly of log message. + + if ($commondir ne '') + { + $subject_base = "r$rev - in $commondir: $dirlist"; + } + else + { + $subject_base = "r$rev - $dirlist"; + } + my $summary = @log ? $log[0] : ''; + chomp($summary); + $subject_logbase = "r$rev - $summary"; + + # Put together the body of the log message. + push(@body, "Author: $author\n"); + push(@body, "Date: $date\n"); + push(@body, "New Revision: $rev\n"); + push(@body, "\n"); + if (@adds) + { + @adds = sort @adds; + push(@body, "Added:\n"); + push(@body, map { " $_\n" } @adds); + } + if (@dels) + { + @dels = sort @dels; + push(@body, "Removed:\n"); + push(@body, map { " $_\n" } @dels); + } + if (@mods) + { + @mods = sort @mods; + push(@body, "Modified:\n"); + push(@body, map { " $_\n" } @mods); + } + push(@body, "Log:\n"); + push(@body, @log); + push(@body, "\n"); + } +elsif ($mode eq 'revprop-change') + { + ###################################################################### + # Harvest data. + + my @svnlines; + # Get the diff file if it was provided, otherwise the property value. + if ($diff_file) + { + open(DIFF_FILE, $diff_file) or die "$0: cannot read `$diff_file': $!\n"; + @svnlines = ; + close DIFF_FILE; + } + else + { + @svnlines = &read_from_process($svnlook, 'propget', '--revprop', '-r', + $rev, $repos, $propname); + } + + ###################################################################### + # Assembly of log message. + + $subject_base = "propchange - r$rev $propname"; + + # Put together the body of the log message. + push(@body, "Author: $author\n"); + push(@body, "Revision: $rev\n"); + push(@body, "Property Name: $propname\n"); + push(@body, "\n"); + unless ($diff_file) + { + push(@body, "New Property Value:\n"); + } + push(@body, map { /[\r\n]+$/ ? $_ : "$_\n" } @svnlines); + push(@body, "\n"); + } + +# Cached information - calculated when first needed. +my @difflines; + +# Go through each project and see if there are any matches for this +# project. If so, send the log out. +foreach my $project (@project_settings_list) + { + my $match_re = $project->{match_re}; + my $match = 0; + foreach my $path (@dirschanged, @adds, @dels, @mods) + { + if ($path =~ $match_re) + { + $match = 1; + last; + } + } + + next unless $match; + + my @email_addresses = @{$project->{email_addresses}}; + my $userlist = join(' ', @email_addresses); + my $to = join(', ', @email_addresses); + my $from_address = $project->{from_address}; + my $hostname = $project->{hostname}; + my $log_file = $project->{log_file}; + my $reply_to = $project->{reply_to}; + my $subject_prefix = $project->{subject_prefix}; + my $summary = $project->{summary}; + my $diff_wanted = ($project->{show_diff} and $mode eq 'commit'); + my $stdout = $project->{stdout}; + + my $subject = $summary ? $subject_logbase : $subject_base; + if ($subject_prefix =~ /\w/) + { + $subject = "$subject_prefix $subject"; + } + my $mail_from = $author; + + if ($from_address =~ /\w/) + { + $mail_from = $from_address; + } + elsif ($hostname =~ /\w/) + { + $mail_from = "$mail_from\@$hostname"; + } + elsif (defined $smtp_server and ! $stdout) + { + die "$0: use of either `-h' or `--from' is mandatory when ", + "sending email using direct SMTP.\n"; + } + + my @head; + my $formatted_date; + if ($stdout) + { + $formatted_date = strftime('%a %b %e %X %Y', localtime()); + push(@head, "From $mail_from $formatted_date\n"); + } + $formatted_date = strftime('%a, %e %b %Y %X %z', localtime()); + push(@head, "Date: $formatted_date\n"); + push(@head, "To: $to\n"); + push(@head, "From: $mail_from\n"); + push(@head, "Subject: $subject\n"); + push(@head, "Reply-to: $reply_to\n") if $reply_to; + + ### Below, we set the content-type etc, but see these comments + ### from Greg Stein on why this is not a full solution. + # + # From: Greg Stein + # Subject: Re: svn commit: rev 2599 - trunk/tools/cgi + # To: dev@subversion.tigris.org + # Date: Fri, 19 Jul 2002 23:42:32 -0700 + # + # Well... that isn't strictly true. The contents of the files + # might not be UTF-8, so the "diff" portion will be hosed. + # + # If you want a truly "proper" commit message, then you'd use + # multipart MIME messages, with each file going into its own part, + # and labeled with an appropriate MIME type and charset. Of + # course, we haven't defined a charset property yet, but no biggy. + # + # Going with multipart will surely throw out the notion of "cut + # out the patch from the email and apply." But then again: the + # commit emailer could see that all portions are in the same + # charset and skip the multipart thang. + # + # etc etc + # + # Basically: adding/tweaking the content-type is nice, but don't + # think that is the proper solution. + push(@head, "Content-Type: text/plain; charset=UTF-8\n"); + push(@head, "Content-Transfer-Encoding: 8bit\n"); + + push(@head, "\n"); + + if ($diff_wanted and not @difflines) + { + # Get the diff from svnlook. + my @no_diff_deleted = $no_diff_deleted ? ('--no-diff-deleted') : (); + my @no_diff_added = $no_diff_added ? ('--no-diff-added') : (); + @difflines = &read_from_process($svnlook, 'diff', $repos, + '-r', $rev, @no_diff_deleted, + @no_diff_added); + @difflines = map { /[\r\n]+$/ ? $_ : "$_\n" } @difflines; + } + + if ($stdout) + { + print @head, @body; + print @difflines if $diff_wanted; + } + elsif (defined $sendmail and @email_addresses) + { + # Open a pipe to sendmail. + my $command = "$sendmail -f'$mail_from' $userlist"; + if (open(SENDMAIL, "| $command")) + { + print SENDMAIL @head, @body; + print SENDMAIL @difflines if $diff_wanted; + close SENDMAIL + or warn "$0: error in closing `$command' for writing: $!\n"; + } + else + { + warn "$0: cannot open `| $command' for writing: $!\n"; + } + } + elsif (defined $smtp_server and @email_addresses) + { + my $smtp = Net::SMTP->new($smtp_server) + or die "$0: error opening SMTP session to `$smtp_server': $!\n"; + handle_smtp_error($smtp, $smtp->mail($mail_from)); + handle_smtp_error($smtp, $smtp->recipient(@email_addresses)); + handle_smtp_error($smtp, $smtp->data()); + handle_smtp_error($smtp, $smtp->datasend(@head, @body)); + if ($diff_wanted) + { + handle_smtp_error($smtp, $smtp->datasend(@difflines)); + } + handle_smtp_error($smtp, $smtp->dataend()); + handle_smtp_error($smtp, $smtp->quit()); + } + + # Dump the output to logfile (if its name is not empty). + if ($log_file =~ /\w/) + { + if (open(LOGFILE, ">> $log_file")) + { + print LOGFILE @head, @body; + print LOGFILE @difflines if $diff_wanted; + close LOGFILE + or warn "$0: error in closing `$log_file' for appending: $!\n"; + } + else + { + warn "$0: cannot open `$log_file' for appending: $!\n"; + } + } + } + +exit 0; + +sub handle_smtp_error +{ + my ($smtp, $retval) = @_; + if (not $retval) + { + die "$0: SMTP Error: " . $smtp->message() . "\n"; + } +} + +sub usage +{ + warn "@_\n" if @_; + die "usage (commit mode):\n", + " $0 REPOS REVNUM [[-m regex] [options] [email_addr ...]] ...\n", + "usage: (revprop-change mode):\n", + " $0 --revprop-change REPOS REVNUM USER PROPNAME [-d diff_file] \\\n", + " [[-m regex] [options] [email_addr ...]] ...\n", + "options are:\n", + " -m regex Regular expression to match committed path\n", + " --from email_address Email address for 'From:' (overrides -h)\n", + " -h hostname Hostname to append to author for 'From:'\n", + " -l logfile Append mail contents to this log file\n", + " -r email_address Email address for 'Reply-To:'\n", + " -s subject_prefix Subject line prefix\n", + " --summary Use first line of commit log in subject\n", + " --diff y|n Include diff in message (default: y)\n", + " (applies to commit mode only)\n", + " --stdout Spit the message in mbox format to stdout.\n", + "\n", + "This script supports a single repository with multiple projects,\n", + "where each project receives email only for actions that affect that\n", + "project. A project is identified by using the -m command line\n". + "option with a regular expression argument. If the given revision\n", + "contains modifications to a path that matches the regular\n", + "expression, then the action applies to the project.\n", + "\n", + "Any of the following email addresses and command line options\n", + "(other than -d) are associated with this project, until the next -m,\n", + "which resets the options and the list of email addresses.\n", + "\n", + "To support a single project conveniently, the script initializes\n", + "itself with an implicit -m . rule that matches any modifications\n", + "to the repository. Therefore, to use the script for a single-\n", + "project repository, just use the other command line options and\n", + "a list of email addresses on the command line. If you do not want\n", + "a rule that matches the entire repository, then use -m with a\n", + "regular expression before any other command line options or email\n", + "addresses.\n", + "\n", + "'revprop-change' mode:\n", + "The message will contain a copy of the diff_file if it is provided,\n", + "otherwise a copy of the (assumed to be new) property value.\n", + "\n"; +} + +# Return a new hash data structure for a new empty project that +# matches any modifications to the repository. +sub new_project +{ + return {email_addresses => [], + from_address => '', + hostname => '', + log_file => '', + match_regex => '.', + reply_to => '', + subject_prefix => '', + show_diff => 1, + stdout => 0}; +} + +sub parse_boolean +{ + if ($_[0] eq 'y') { return 1; }; + if ($_[0] eq 'n') { return 0; }; + + die "$0: valid boolean options are 'y' or 'n', not '$_[0]'\n"; +} + +# Start a child process safely without using /bin/sh. +sub safe_read_from_pipe +{ + unless (@_) + { + croak "$0: safe_read_from_pipe passed no arguments.\n"; + } + + my $openfork_available = $^O ne "MSWin32"; + if ($openfork_available) # We can fork on this system. + { + my $pid = open(SAFE_READ, '-|'); + unless (defined $pid) + { + die "$0: cannot fork: $!\n"; + } + unless ($pid) + { + open(STDERR, ">&STDOUT") + or die "$0: cannot dup STDOUT: $!\n"; + exec(@_) + or die "$0: cannot exec `@_': $!\n"; + } + } + else # Running on Windows. No fork. + { + my @commandline = (); + my $arg; + + while ($arg = shift) + { + $arg =~ s/\"/\\\"/g; + if ($arg eq "" or $arg =~ /\s/) { $arg = "\"$arg\""; } + push(@commandline, $arg); + } + + # Now do the pipe. + open(SAFE_READ, "@commandline |") + or die "$0: cannot pipe to command: $!\n"; + } + my @output; + while () + { + s/[\r\n]+$//; + push(@output, $_); + } + close(SAFE_READ); + my $result = $?; + my $exit = $result >> 8; + my $signal = $result & 127; + my $cd = $result & 128 ? "with core dump" : ""; + if ($signal or $cd) + { + warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n"; + } + if (wantarray) + { + return ($result, @output); + } + else + { + return $result; + } +} + +# Use safe_read_from_pipe to start a child process safely and return +# the output if it succeeded or an error message followed by the output +# if it failed. +sub read_from_process +{ + unless (@_) + { + croak "$0: read_from_process passed no arguments.\n"; + } + my ($status, @output) = &safe_read_from_pipe(@_); + if ($status) + { + return ("$0: `@_' failed with this output:", @output); + } + else + { + return @output; + } +} --- subversion-1.7.9.orig/debian/contrib/emacs/50psvn.el +++ subversion-1.7.9/debian/contrib/emacs/50psvn.el @@ -0,0 +1,3 @@ +; Set up autoloads for psvn (svn directory edit mode for emacs) + +(autoload 'svn-status "psvn" nil t) --- subversion-1.7.9.orig/debian/contrib/emacs/dsvn.el +++ subversion-1.7.9/debian/contrib/emacs/dsvn.el @@ -0,0 +1,2150 @@ +;;; dsvn.el --- Subversion interface + +;; Copyright 2006-2010 Virtutech AB +;; Copyright 2010 Intel + +;; Author: David Kågedal +;; Mattias Engdegård +;; Maintainer: Mattias Engdegård +;; Created: 27 Jan 2006 +;; Keywords: docs + +;; This program 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 of the +;; License, or (at your option) any later version. + +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +;; USA + +;;; Commentary: +;; +;; This is an interface for managing Subversion working copies. It +;; can show you an up-to-date view of the current status, and commit +;; changes. If also helps you do other tasks such as updating, +;; switching, diffing and more. +;; +;; To get you started, add this line to your startup file: +;; +;; (autoload 'svn-status "dsvn" "Run `svn status'." t) +;; (autoload 'svn-update "dsvn" "Run `svn update'." t) +;; +;; This file integrates well with vc-svn, so you might want to do this +;; as well: +;; +;; (require 'vc-svn) +;; +;; To get the status view, type +;; +;; M-x svn-status +;; +;; and select a directory where you have a checked-out Subversion +;; working copy. A buffer will be created that shows what files you +;; have modified, and any unknown files. The file list corresponds +;; closely to that produced by "svn status", only slightly +;; reformatted. +;; +;; Navigate through the file list using "n" and "p", for next and +;; previous file, respectively. +;; +;; You can get a summary of available commands by typing "?". +;; +;; Some commands operate on files, and can either operate on the file +;; under point, or on a group of files that have been marked. The +;; commands used for marking a file are the following: +;; +;; m mark and go down +;; DEL unmark and go up +;; u unmark and go down +;; SPC toggle mark +;; M-DEL unmark all +;; +;; The commands that operate on files are: +;; +;; f Visit the file under point (does not use marks) +;; o Visit the file under point in another window (does not use marks) +;; = Show diff of uncommitted changes. This does not use marks +;; unless you give a prefix argument (C-u) +;; c Commit files +;; a Add files +;; r Remove files +;; R Resolve conflicts +;; M Rename/move files +;; U Revert files +;; P View or edit properties of the file or directory under point +;; (does not use marks) +;; l Show log of file or directory under point (does not use marks) +;; +;; These commands update what is shown in the status buffer: +;; +;; g Rerun "svn status" to update the list. Use a prefix +;; argument (C-u) to clear the list first to make sure that +;; it is correct. +;; s Update status of selected files +;; S Show status of specific file or directory +;; x Expunge unchanged files from the list +;; +;; To update the working copy: +;; +;; M-u Run "svn update". If a prefix argument is given (C-u), +;; you will be prompted for a revision to update to. +;; M-s Switch working copy to another branch. +;; M-m Merge in changes using "svn merge". +;; +;; To view the Subversion log, type "M-x svn-log". +;; +;; Bugs and missing features: +;; +;; - Annotate (blame). +;; - Log, with a useful log mode where the user can easily view any revision +;; as a diff or visit a revision of a file in a buffer. +;; - Integration with ediff or similar to resolve conflicts. + +(require 'vc) +(require 'log-edit) +(require 'uniquify) + +(defconst svn-status-msg-col 1) +(defconst svn-status-flags-col 11) +(defconst svn-status-mark-col 18) +(defconst svn-status-file-col 20) + +(defgroup dsvn nil + "Settings for dsvn." + :group 'tools) + +(defcustom svn-program "svn" + "*The svn program to run" + :type 'string + :group 'dsvn) + +(defcustom svn-restore-windows nil + "*Non-nil means that the window configuration is restored after commit" + :type 'boolean + :group 'dsvn) + +(defun svn-call-process (program buffer &rest args) + "Run svn and wait for it to finish. +Argument PROGRAM is the svn binary to run. +Argument BUFFER is the buffer in which to insert output. +Optional argument ARGS are the arguments to svn." + (let ((proc (apply 'start-process "svn" buffer program args))) + (set-process-coding-system proc 'utf-8) + (set-process-filter proc 'svn-output-filter) + (while (eq (process-status proc) 'run) + (accept-process-output proc 5) + (sit-for 0)))) + +(defun svn-run-with-output (subcommand &optional args mode) + "Run 'svn' with output to another window. +Argument SUBCOMMAND is the command to execute. +Optional argument ARGS is a list of the arguments to the command. +Optional argument MODE is the major mode to use for the output buffer. + +Return non-NIL if there was any output." + (let ((buf (get-buffer-create "*svn output*")) + (dir default-directory) + (inhibit-read-only t)) + (with-current-buffer buf + (erase-buffer) + (if mode + (funcall mode) + (fundamental-mode)) + (setq default-directory dir) + (setq buffer-read-only t) + (let ((cmd `(,svn-program ,subcommand ,@args)) + proc) + (setq proc (apply 'start-process "svn" buf cmd)) + (set-process-coding-system proc 'utf-8) + (set-process-filter proc 'svn-output-filter) + (while (eq (process-status proc) 'run) + (accept-process-output proc 5) + (sit-for 0))) + (if (= (point-min) (point-max)) + nil + (save-selected-window + (select-window (display-buffer buf)) + (goto-char (point-min))) + t)))) + +(defun svn-run-hidden (command args) + "Run 'svn' without showing output. +Argument COMMAND is the command to run. +Optional argument ARGS is a list of arguments. +Returns the buffer that holds the output from 'svn'." + (let ((buf (get-buffer-create " *svn*")) + (dir default-directory)) + (with-current-buffer buf + (erase-buffer) + (setq default-directory dir)) + (apply 'call-process svn-program nil buf nil (symbol-name command) args) + buf)) + +(defun svn-run-for-stdout (command args) + "Run `svn', and return standard output as a string, discarding stderr. +Argument COMMAND is the svn subcommand to run. +Optional argument ARGS is a list of arguments." + (let ((output-buffer (generate-new-buffer "*svn-stdout*"))) + (apply 'call-process svn-program nil (list output-buffer nil) nil + (symbol-name command) args) + (let ((stdout (with-current-buffer output-buffer (buffer-string)))) + (kill-buffer output-buffer) + stdout))) + +(defun svn-output-filter (proc str) + "Output filter for svn output. +Argument PROC is the process object. +Argument STR is the output string." + (save-excursion + (set-buffer (process-buffer proc)) + (goto-char (process-mark proc)) + ;; put point back where it was to avoid scrolling for long output + ;; (e.g., large diffs) + (let ((p (point)) + (inhibit-read-only t)) + (insert-before-markers str) + (goto-char p)))) + +(defvar svn-todo-queue '() + "A queue of commands to run when the current command finishes.") +(make-variable-buffer-local 'svn-todo-queue) + +(defun svn-current-url () + "Get the repository URL." + (with-current-buffer (svn-run-hidden 'info ()) + (if (re-search-backward "^URL: \\(.*\\)$" nil t) + (match-string 1) + (error "Couldn't find the current URL")))) + +(defun svn-repository-root () + "Get the repository root." + (with-current-buffer (svn-run-hidden 'info ()) + (if (re-search-backward "^Repository Root: \\(.*\\)$" nil t) + (match-string 1) + (error "Couldn't find the repository root")))) + +(defconst svn-noninteractive-blacklist + '(add revert resolved) + "Subversion commands that don't accept the --non-interactive option. +This is only important for svn 1.4, as 1.5 accepts this option for all +commands.") + +(defun svn-run (command args &optional description) + "Run subversion command COMMAND with ARGS. + +Optional third argument DESCRIPTION is a string used in the status +buffer to describe what is going on." + ;; Clean up old output + (let ((inhibit-read-only t)) + (delete-region svn-output-marker (point-max))) + + (let* ((command-s (symbol-name command)) + (filter-func (intern (concat "svn-" command-s "-filter"))) + (sentinel-func (intern (concat "svn-" command-s "-sentinel"))) + proc) + ;; The command status-v is interpreted as status -v + (when (eq command 'status-v) + (setq command-s "status" + args (cons "-v" args))) + (unless (memq command svn-noninteractive-blacklist) + (setq args (cons "--non-interactive" args))) + (setq proc (apply 'start-process "svn" (current-buffer) + svn-program command-s args)) + (if (fboundp filter-func) + (set-process-filter proc filter-func) + (set-process-filter proc 'svn-default-filter)) + (if (fboundp sentinel-func) + (set-process-sentinel proc sentinel-func) + (set-process-sentinel proc 'svn-default-sentinel)) + (setq svn-running (list description proc)) + (set-svn-process-status 'running) + proc)) + +(defun svn-check-running () + (when svn-running + (error "Can't run two svn processes from the same buffer"))) + +(defun svn-run-async (command args &optional file-filter) + "Run subversion command COMMAND with ARGS, possibly at a later time. + +Optional third argument FILE-FILTER is the file filter to be in effect +during the run." + + (if svn-running + (setq svn-todo-queue + (nconc svn-todo-queue + (list (list command args file-filter)))) + (progn + (set (make-local-variable 'svn-file-filter) file-filter) + (svn-run command args)))) + +;; This could be used to debug filter functions +(defvar svn-output-queue nil) +(defvar svn-in-output-filter nil) +(defun svn-filter-queue (proc str) + (setq svn-output-queue (nconc svn-output-queue (list str))) + (unless svn-in-output-filter + (let ((svn-in-output-filter t)) + (while svn-output-queue + (svn-status-filter proc (car svn-output-queue)) + (setq svn-output-queue (cdr svn-output-queue)))))) + +(defun svn-default-filter (proc str) + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert str)))) + +(defun svn-default-sentinel (proc reason) + (with-current-buffer (process-buffer proc) + (when (and svn-running + (eq proc (cadr svn-running))) + (setq svn-running nil) + (if (/= (process-exit-status proc) 0) + (set-svn-process-status 'failed) + (set-svn-process-status 'finished)) + (move-to-column goal-column)) + (when svn-todo-queue + (let ((cmd-info (car svn-todo-queue))) + (setq svn-todo-queue (cdr svn-todo-queue)) + (let ((command (car cmd-info)) + (args (cadr cmd-info)) + (file-filter (car (cddr cmd-info)))) + (set (make-local-variable 'svn-file-filter) file-filter) + (svn-run command args)))))) + +(defun svn-diff (arg) + "Run `svn diff'. +Argument ARG are the command line arguments." + (interactive "ssvn diff arguments: ") + (svn-run-with-output "diff" (split-string arg) 'diff-mode)) + +(defun svn-commit () + "Commit changes to one or more files." + (interactive) + (save-some-buffers) + (let ((status-buf (current-buffer)) + (commit-buf (get-buffer-create "*svn commit*")) + (window-conf (and svn-restore-windows (current-window-configuration))) + (listfun (lambda () (with-current-buffer log-edit-parent-buffer + (svn-action-files))))) + (log-edit 'svn-confirm-commit t + (if (< emacs-major-version 23) + listfun + (list (cons 'log-edit-listfun listfun))) + commit-buf) + (set (make-local-variable 'saved-window-configuration) window-conf))) + +(defun svn-confirm-commit () + "Commit changes with the current buffer as commit message." + (interactive) + (let ((files (with-current-buffer log-edit-parent-buffer + (svn-action-files))) + (commit-buf (current-buffer)) + (status-buf log-edit-parent-buffer) + (window-conf saved-window-configuration) + ;; XEmacs lacks make-temp-file but has make-temp-name + temp-directory + (msg-file (if (fboundp 'make-temp-file) + (make-temp-file "svn-commit") + (make-temp-name (expand-file-name "svn-commit" + (temp-directory)))))) + ;; Ensure final newline + (goto-char (point-max)) + (unless (bolp) + (newline)) + (write-region (point-min) (point-max) msg-file) + (when (boundp 'vc-comment-ring) + ;; insert message into comment ring, unless identical to the previous + (let ((comment (buffer-string))) + (when (or (ring-empty-p vc-comment-ring) + (not (equal comment (ring-ref vc-comment-ring 0)))) + (ring-insert vc-comment-ring comment)))) + (kill-buffer commit-buf) + (with-current-buffer status-buf + (make-local-variable 'svn-commit-msg-file) + (make-local-variable 'svn-commit-files) + (setq svn-commit-msg-file msg-file) + (setq svn-commit-files files) + (svn-run 'commit (append (list "-N" "-F" msg-file) files))) + (if window-conf + (set-window-configuration window-conf)))) + +(defun svn-commit-filter (proc str) + "Output filter function for `svn commit'." + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t) + (nomore)) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (not nomore) + (cond ((looking-at + "\\(Sending\\|Adding\\|Transmitting file\\|Deleting\\) .*\n") + ;; Ignore these expected and uninteresting messages + (delete-region (match-beginning 0) + (match-end 0))) + ((looking-at "Committed revision \\([0-9]+\\).\n") + (svn-update-label svn-revision-label (match-string 1)) + (forward-line 1)) + ((looking-at ".*\n") + ;; Unexpected output is left in the buffer + (forward-line 1)) + (t + (setq nomore t))))))) + +(defun svn-commit-sentinel (proc reason) + "Sentinel function for `svn commit'." + (with-current-buffer (process-buffer proc) + (when (= (process-exit-status proc) 0) + (while svn-commit-files + (let* ((file (car svn-commit-files)) + (path (concat default-directory file)) + (pos (svn-file-pos file)) + (file-buffer (get-file-buffer path)) + (inhibit-read-only t)) + (when pos + (svn-update-status-flag pos ?\ ?\ ) + (svn-update-status-msg pos "Committed")) + (when (and file-buffer (fboundp 'vc-svn-workfile-version)) + (with-current-buffer file-buffer + ;; Use buffer-file-name instead of path to get the + ;; canonical file name used by vc + ;; TODO: use the version number written by the commit command + (vc-file-setprop buffer-file-name 'vc-workfile-version + (vc-svn-workfile-version buffer-file-name)) + (vc-mode-line buffer-file-name)))) + (setq svn-commit-files (cdr svn-commit-files)))) + (delete-file svn-commit-msg-file)) + (svn-default-sentinel proc reason)) + +;;; Svn log + +(defun svn-file-log (pos) + "List the change log of the selected file or directory." + (interactive "d") + (let ((file (or (svn-getprop pos 'file) + (svn-getprop pos 'dir)))) + (unless file + (error "No file or directory on this line")) + (svn-log (list file)))) + +(defun svn-log (arg) + "Run `svn log'. +Argument ARG is the command-line arguments, as a string or a list." + (interactive "ssvn log arguments: ") + (when (stringp arg) + (setq arg (split-string arg))) + (svn-run-with-output "log" arg + 'svn-log-mode)) + +(defvar svn-log-mode-map nil + "Keymap for `svn-log-mode'.") +(unless svn-log-mode-map + (setq svn-log-mode-map (make-sparse-keymap)) + (define-key svn-log-mode-map "\r" 'svn-log-show-diff) + (define-key svn-log-mode-map "n" 'svn-log-next) + (define-key svn-log-mode-map "p" 'svn-log-prev) + (define-key svn-log-mode-map "e" 'svn-log-edit) + (define-key svn-log-mode-map "+" 'svn-log-expand) + (define-key svn-log-mode-map "-" 'svn-log-compact) + (define-key svn-log-mode-map "=" 'svn-log-diff) + ) + +(defun svn-update-log-entry (verbose-p) + "Update the log entry under point, using verbose output if +VERBOSE-P." + (save-excursion + (end-of-line) + (re-search-backward svn-log-entry-start-re nil t) + (let ((start (point))) + (unless (re-search-forward "^r\\([0-9]+\\) |" nil t) + (error "Found no commit")) + (let* ((commit-id (string-to-int (match-string 1))) + (new (svn-run-hidden 'log + (append (and verbose-p '("-v")) + '("-r") + (list (int-to-string commit-id))))) + (text (with-current-buffer new + (goto-char (point-min)) + (unless (re-search-forward svn-log-entry-start-re nil t) + (error "Failed finding log entry start")) + (unless (re-search-forward svn-log-entry-start-re nil t) + (error "Failed finding log entry end")) + (buffer-substring (point-min) (match-beginning 0)))) + (inhibit-read-only t)) + (re-search-forward svn-log-entry-start-re nil 'limit) + (goto-char (match-beginning 0)) + (delete-region start (point)) + (insert text))))) + +(defun svn-log-expand () + "Show verbose log entry information." + (interactive) + (svn-update-log-entry t)) + +(defun svn-log-compact () + "Show compact log entry information." + (interactive) + (svn-update-log-entry nil)) + +(defun svn-log-mode () + "Major mode for viewing Subversion logs. + +\\{svn-log-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'svn-log-mode + mode-name "Svn log") + (use-local-map svn-log-mode-map) + (setq paragraph-start "^commit")) + +(defconst svn-log-entry-start-re "^-\\{72\\}$") + +(defun svn-log-find-revision (commit-id) + (let (found start) + (save-excursion + (goto-char (point-min)) + (while (and (re-search-forward svn-log-entry-start-re nil t) + (setq start (point)) + (re-search-forward "^r\\([0-9]+\\) |" nil t) + (if (/= (string-to-int (match-string 1)) commit-id) + t + (setq found t) + nil)))) + (when found + (goto-char start) + (beginning-of-line) + t))) + +(defun svn-log-current-commit () + (save-excursion + (end-of-line) + (re-search-backward svn-log-entry-start-re nil t) + (unless (re-search-forward "^r\\([0-9]+\\) |" nil t) + (error "Found no commit")) + (string-to-int (match-string 1)))) + +(defun svn-log-show-diff () + "Show the changes introduced by the changeset under point." + (interactive) + (let ((commit-id (svn-log-current-commit)) + (diff-buf (get-buffer-create "*svn diff*")) + (dir default-directory) + (inhibit-read-only t)) + (display-buffer diff-buf) + (with-current-buffer diff-buf + (diff-mode) + (setq buffer-read-only t) + (erase-buffer) + (setq default-directory dir) + (svn-call-process svn-program diff-buf + "diff" "-r" + (format "%d:%d" (1- commit-id) commit-id))))) + +(defun svn-log-edit-files (commit-id) + (let ((root (svn-repository-root)) + result) + (with-current-buffer + (svn-run-hidden 'log (list "-v" "-r" + (int-to-string commit-id) + root)) + (goto-char (point-min)) + (unless (re-search-forward "^Changed paths:" nil t) + (error "Cannot find list of changes")) + (while (re-search-forward + "^ \\(\\S-+\\)\\s-+\\(.*?\\)\\( (from .*)$\\)?$" + nil t) + (let ((how (match-string 1)) + (file (match-string 2)) + (tail (match-string 3))) + (when (string-match "\\([^/]*/\\)?\\([^/]*\\)$" file) + (setq file (match-string 0 file))) + (setq result (cons (concat how " " file) result))))) + (nreverse result))) + +(defun svn-log-diff () + "Run `svn diff' for the current log entry." + (interactive) + (let ((commit-id (svn-log-current-commit))) + (svn-run-with-output "diff" (list "-c" (number-to-string commit-id)) + 'diff-mode))) + +(defun svn-log-edit () + "Edit the log message for the revision under point." + (interactive) + (let* ((commit-id (svn-log-current-commit)) + (log (svn-propget commit-id "svn:log")) + (cwd default-directory) + (parent-buffer (current-buffer)) + (buffer (get-buffer-create (format "*svn log message of r%d*" + commit-id)))) + (log-edit 'svn-log-edit-done t + `(lambda () (svn-log-edit-files ,commit-id)) + buffer) + (insert log) + (set (make-local-variable 'svn-commit-id) commit-id) + (set (make-local-variable 'svn-directory) cwd) + (set (make-local-variable 'svn-parent-buffer) parent-buffer) + (setq default-directory cwd) + (message (substitute-command-keys + "Press \\[log-edit-done] when you are done editing.")))) + +(defun svn-log-edit-done () + (interactive) + (setq default-directory svn-directory) ; just in case the user cd'd + (message "Changing log message...") + (let ((commit-id svn-commit-id)) + (svn-propset commit-id "svn:log" (buffer-string)) + (when (buffer-name svn-parent-buffer) + (save-excursion + (set-buffer svn-parent-buffer) + (when (svn-log-find-revision commit-id) + (svn-update-log-entry nil))))) + (kill-buffer nil) + (message "Changing log message... done")) + +(defun svn-log-next () + "Move to the next changeset in the log." + (interactive) + (end-of-line) + (unless (re-search-forward svn-log-entry-start-re nil t) + (error "Found no commit")) + (beginning-of-line) + (svn-log-show-diff)) + +(defun svn-log-prev () + "Move to the previous changeset in the log." + (interactive) + (beginning-of-line) + (unless (re-search-backward svn-log-entry-start-re nil t) + (error "Found no commit")) + (svn-log-show-diff)) + +(defun svn-new-label (&optional pos) + (unless pos (setq pos (point))) + (let ((start (make-marker)) + (stop (make-marker))) + (set-marker start pos) + (set-marker stop pos) + (list start stop))) + +(defun svn-update-label (label str) + (let ((start (car label)) + (stop (cadr label)) + (inhibit-read-only t)) + (delete-region start stop) + (set-marker-insertion-type stop t) + (save-excursion + (goto-char start) + (insert str)))) + +;;; Svn propedit + +(defun svn-prop-args (file-or-rev) + "Returns a list of arguments to the 'svn prop...' commands, to +make them act on FILE-OR-REV (a file name or a revision number)." + (if (integerp file-or-rev) + (list "--revprop" "-r" (int-to-string file-or-rev)) + (list file-or-rev))) + +(defun svn-prop-description (file-or-rev) + "Returns a human-readable description of FILE-OR-REV (a file +name or revision number)." + (if (integerp file-or-rev) + (format "revision %d" file-or-rev) + file-or-rev)) + +(defun svn-propget (file-or-rev propname) + "Return the Subversion property PROPNAME of FILE-OR-REV (file +name or revision number)." + (with-current-buffer + (svn-run-hidden 'propget + (cons propname + (svn-prop-args file-or-rev))) + (substring (buffer-string) 0 -1))) ; trim final newline added by svn + +(defun svn-get-props (file) + "Return an alist containing the properties of FILE" + ;; First retrieve the property names, and then the value of each. + ;; We can't use proplist -v because is output is ambiguous when values + ;; consist of multiple lines. + (if (string-equal (svn-run-for-stdout 'info (list file)) "") + (error "%s is not under version control" file)) + (let (propnames) + (with-current-buffer (svn-run-hidden 'proplist (list file)) + (goto-char (point-min)) + (when (looking-at "Properties on ") + (forward-line 1) + (while (looking-at " \\(.+\\)$") + (setq propnames (cons (match-string 1) propnames)) + (forward-line 1)))) + (mapcar (lambda (propname) + (cons propname (svn-propget file propname))) + propnames))) + +(defun svn-propedit (file) + "Edit properties of FILE." + (interactive (list (expand-file-name + (or (svn-getprop (point) 'file) + (read-file-name "Edit properties of file: " + default-directory + nil t + (svn-getprop (point) 'dir)))))) + (let ((local-file (svn-local-file-name file))) + (when (string-equal local-file "") + (setq local-file ".") + (setq file (file-name-as-directory file))) + (svn-check-running) + (let ((buf-name (format "*propedit %s*" local-file))) + (if (get-buffer buf-name) + (kill-buffer buf-name)) + (let ((prop-alist (svn-get-props local-file)) + (propedit-buf (get-buffer-create buf-name))) + (switch-to-buffer-other-window propedit-buf) + (svn-propedit-mode) + (insert + "# Properties of " local-file "\n" + "#\n" + "# Lines are on the form PROPNAME: VALUE for single-line values,\n" + "# or just PROPNAME: followed by one or more lines starting with > for\n" + "# multi-line values. Lines starting with # are ignored.\n" + "#\n" + "# Change, add, delete or rename properties just by editing this\n" + "# buffer; then press " + (substitute-command-keys "\\[svn-propedit-done]") + " to save changes.\n\n") + (mapc (lambda (prop) + (let* ((value (cdr prop)) + (lines nil) + (len (length value)) + (ofs 0)) + ;; Split value in lines - we can't use split-string because + ;; its behaviour is not consistent across Emacs versions. + (while (<= ofs len) + (let* ((nl (or (string-match "\n" value ofs) len))) + (setq lines (cons (substring value ofs nl) lines)) + (setq ofs (+ nl 1)))) + (setq lines (nreverse lines)) + ;; The lines list now contains one string per line, and + ;; an empty list at the end if the string finished in a \n. + + (insert (car prop) ":") + (if (> (length lines) 1) + (progn + (insert "\n") + (mapc (lambda (line) (insert ">" line "\n")) + lines)) + (insert " " (or (car lines) "") "\n")))) + (sort prop-alist #'(lambda (a b) (string< (car a) (car b))))) + (make-local-variable 'svn-propedit-file) + (setq svn-propedit-file file) + (setq default-directory (file-name-directory file)) + (message + (substitute-command-keys + "Press \\[svn-propedit-done] when you are done editing.")))))) + +(defvar svn-propedit-mode-map nil + "Keymap for `svn-propedit-mode'.") +(unless svn-propedit-mode-map + (setq svn-propedit-mode-map (make-sparse-keymap)) + (define-key svn-propedit-mode-map "\C-c\C-c" 'svn-propedit-done)) + +(defun svn-propedit-mode () + "Major mode for editing Subversion properties." + (interactive) + (kill-all-local-variables) + (setq major-mode 'svn-propedit-mode + mode-name "Svn propedit") + (use-local-map svn-propedit-mode-map) + (setq font-lock-defaults + '((("^#.*$" ;comment + . 'font-lock-comment-face) + ("^\\([^ \t\n#>][^ \t\n]*\\):" ;property name + . (1 'bold)) + ("^[^ \t\n#>][^ \t\n]*: *\\(.*\\)$" ;property value + . (1 'font-lock-function-name-face)) + ("^>" ;multi-line marker + . 'bold) + ("^>\\(.*\\)$" ;property value (continued) + . (1 'font-lock-function-name-face)) + ) + nil ;keywords-only + nil ;case-fold + ;; syntax-alist: don't fontify quotes specially in any way + ((?\" . ".")) + nil ;syntax-begin + )) + (font-lock-mode)) + +(defun svn-props-from-buffer () + "Parse the current propedit buffer and return an alist of the properties." + (save-excursion + (let (prop-alist) + (goto-char (point-min)) + (while (not (eobp)) + (cond ((looking-at "^\\([^ \t\n#>][^ \t\n]*\\): *\\(.*\\)$") + (let ((prop-name (match-string 1)) + (value (match-string 2))) + (set-text-properties 0 (length prop-name) nil prop-name) + (set-text-properties 0 (length value) nil value) + (when (assoc prop-name prop-alist) + (error "Duplicated property %s" prop-name)) + (setq prop-alist (cons (cons prop-name value) prop-alist)))) + ((looking-at "^>\\(.*\\)$") + (let ((extra-line (match-string 1))) + (set-text-properties 0 (length extra-line) nil extra-line) + (when (null prop-alist) + (error "Continued line not preceded by property name")) + (let ((old-value (cdar prop-alist))) + (setcdr (car prop-alist) + (concat old-value "\n" extra-line)))))) + (forward-line 1)) + + ;; Remove the extra leading newline from multi-line values + (mapcar (lambda (prop) + (let ((name (car prop)) + (value (cdr prop))) + (if (and (not (equal value "")) + (equal (substring value 0 1) "\n")) + (cons name (substring value 1)) + prop))) + prop-alist)))) + +(defun svn-propdel (file prop-name) + "Delete FILE's property PROP-NAME." + (svn-run-hidden 'propdel (list prop-name file))) + +(defun svn-propset (file-or-rev prop-name prop-value) + "Set the property PROP-NAME to PROP-VALUE for FILE-OR-REV (a +file name or revision number)." + (let ((buf (svn-run-hidden 'propset (append (list prop-name prop-value) + (svn-prop-args file-or-rev))))) + (unless + (with-current-buffer buf + (goto-char (point-min)) + (looking-at "^property '.*' set on ")) + (switch-to-buffer buf) + (error "Failed setting property %s of %s" + prop-name + (svn-prop-description file-or-rev))))) + +(defun svn-propedit-done () + "Apply property changes to the file." + (interactive) + (let ((wc-props (svn-get-props svn-propedit-file)) + (new-props (svn-props-from-buffer)) + (changes 0)) + + ;; first remove properties that the user deleted from the buffer + (mapc (lambda (wc-prop) + (let ((prop-name (car wc-prop))) + (when (not (assoc prop-name new-props)) + (message "Deleting property %s" prop-name) + (svn-propdel svn-propedit-file prop-name) + (setq changes (1+ changes))))) + wc-props) + + ;; then set the properties that have changed or are new + (mapc (lambda (new-prop) + (let* ((prop-name (car new-prop)) + (wc-prop (assoc prop-name wc-props))) + (unless (equal new-prop wc-prop) + (message "Setting property %s" prop-name) + (svn-propset svn-propedit-file prop-name (cdr new-prop)) + (setq changes (1+ changes))))) + new-props) + (cond + ((> changes 1) (message "Changed %d properties." changes)) + ((= changes 0) (message "No properties changed.")))) + (svn-foreach-svn-buffer + svn-propedit-file + (lambda (local-file-name file-pos) + (svn-refresh-item local-file-name nil))) + (kill-buffer (current-buffer))) + +;;; Svn buffer + +(defvar svn-files-start nil) +(defvar svn-files-stop nil) +(defvar svn-url-label nil) +(defvar svn-revision-label nil) +(defvar svn-running-label nil) +(defvar svn-output-marker nil) + +(defvar svn-running nil) + +(defun create-svn-buffer (dir) + "Create a buffer for showing svn status. +Argument DIR is the directory to run svn in." + (let ((status-buf (create-file-buffer (concat dir "*svn*"))) + (inhibit-read-only t)) + (with-current-buffer status-buf + (setq default-directory dir) + (svn-status-mode) + + (make-local-variable 'svn-url-label) + (make-local-variable 'svn-revision-label) + (make-local-variable 'svn-running-label) + (make-local-variable 'svn-output-marker) + + (insert "Svn status for " dir) (newline) + (insert "URL: ") (setq svn-url-label (svn-new-label)) + (insert " revision " ) (setq svn-revision-label (svn-new-label)) + (newline) + (newline) + (insert "---- ") (setq svn-running-label (svn-new-label)) + (newline) + (setq svn-files-start (point-marker)) + (set-marker-insertion-type svn-files-start nil) + (setq svn-last-inserted-marker (point-marker)) + (set-marker-insertion-type svn-last-inserted-marker nil) + (insert "----") + (newline) + (setq svn-output-marker (point-marker)) + (set-marker-insertion-type svn-output-marker nil) + ;; Do this after inserting stuff + (setq svn-files-stop (copy-marker svn-files-start t)) + (setq buffer-read-only t)) + status-buf)) + +(defun switch-to-svn-buffer (dir) + "Switch to a (possibly new) buffer displaying status for DIR" + (setq dir (file-name-as-directory dir)) + (let ((buffers (buffer-list))) + (while (and buffers + (not (with-current-buffer (car buffers) + (and (eq major-mode 'svn-status-mode) + (string= default-directory dir))))) + (setq buffers (cdr buffers))) + (switch-to-buffer (if buffers + (car buffers) + (create-svn-buffer dir))))) + +(defun svn-in-dir-p (dir file) + "Return non-NIL if FILE is inside DIR" + (let ((l (length dir))) + (and (> (length file) l) + (string= dir (substring file 0 l))))) + +;;; Svn status + +(defun svn-status (dir) + "Run `svn status'. +Argument DIR is the directory to run svn status in." + (interactive "DDirectory: \n") + (switch-to-svn-buffer dir) + (let ((proc (svn-run 'info ()))) + (while (eq (process-status proc) 'run) + (accept-process-output proc 2 10000))) + ;; The sentinel isn't run by a-p-o, so we hack around it + (setq svn-running nil) + (svn-refresh) + (message + (substitute-command-keys + "Welcome to dsvn. Press \\[svn-status-help] for keyboard help summary."))) + +(defun svn-refresh (&optional clear) + "Run `svn status'. +If optional prefix argument CLEAR is non-NIL, clear the buffer first." + (interactive "P") + (svn-check-running) + (let ((inhibit-read-only t)) + (if clear + (delete-region svn-files-start svn-files-stop) + (put-text-property svn-files-start svn-files-stop 'svn-updated nil)) + (setq svn-last-inserted-filename nil) + (svn-run 'status '()))) + +(defun svn-run-status-v (files recursive) + "Run svn status -v on FILES. If not RECURSIVE, only applies to files and +directories explicitly listed in FILES." + + ;; The command 'svn status -N DIR' will process the immediate contents of + ;; DIR as well as DIR itself, but that is not what we want if running + ;; non-recursively. To compensate, filter the status output through a list + ;; of files and directories we are interested in. + + (let ((flag (if recursive nil '("-N"))) + (file-filter + (if recursive + nil + (mapcar (lambda (file) + ;; trim trailing slash for directory comparison to work + (if (equal (substring file -1) "/") + (substring file 0 -1) + file)) + files)))) + (svn-run-async 'status-v (append flag files) file-filter))) + +(defun svn-refresh-file () + "Run `svn status' on the selected files." + (interactive) + (svn-check-running) + (let ((actions (svn-actions)) + (inhibit-read-only t)) + (setq svn-last-inserted-filename nil) + (put-text-property svn-files-start svn-files-stop 'svn-updated t) + (mapc (lambda (pos) + (svn-setprop pos 'updated nil)) + (mapcar 'cadr actions)) + (svn-run-status-v (mapcar 'car actions) t)) + (svn-next-file 1)) + +(defun svn-local-file-name (file) + "Return file name relative the current directory, or raise an error if +outside." + (if (file-directory-p file) + (setq file (file-name-as-directory file))) + (let ((exp-default-dir (expand-file-name default-directory))) + (if (file-name-absolute-p file) + (let ((ddl (length exp-default-dir))) + (if (or (< (length file) ddl) + (not (string= (substring file 0 ddl) + exp-default-dir))) + (error "Outside working copy") + (substring file ddl))) + file))) + +(defun svn-refresh-item (file recursive) + "Refresh status for FILE. If RECURSIVE, do it recursively (for directories)." + (svn-check-running) + (let ((inhibit-read-only t)) + (setq svn-last-inserted-filename nil) + (let ((local-file (svn-local-file-name file))) + (svn-run-status-v (list local-file) recursive)))) + +(defun svn-refresh-one (file) + "Run `svn status' on FILE." + (interactive (list (expand-file-name + (read-file-name "Svn status on file: " + default-directory + nil t + (or (svn-getprop (point) 'file) + (svn-getprop (point) 'dir)))))) + (svn-refresh-item file t)) + +(defun svn-cleanup-status () + (save-excursion + (let ((inhibit-read-only t)) + (goto-char svn-files-start) + (while (< (point) svn-files-stop) + (if (or (svn-getprop (point) 'dir) + (svn-getprop (point) 'updated)) + (forward-line) + (svn-update-status-flag (point) ?\ ?\ ) + (svn-update-status-msg (point) "") + (forward-line)))))) + +;; Translate backslashes to forward slashes, because that is what +;; Emacs uses internally even on Windows and it permits us to compare +;; file name strings. +(defun svn-normalise-path (path) + (replace-regexp-in-string "\\\\" "/" path t t)) + +(defun svn-status-filter (proc str) + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (cond ((looking-at + "\\([ ACDGIMRX?!~][ CM][ L][ +][ S][ KOTB]\\)[ C]? \\([^ ].*\\)\n") + (let ((status (match-string 1)) + (filename (svn-normalise-path (match-string 2)))) + (delete-region (match-beginning 0) + (match-end 0)) + (svn-insert-file filename status)) + t) + ((looking-at + "\n\\|Performing status on external item at .*\n") + (delete-region (match-beginning 0) + (match-end 0)) + t)))))) + +(defun svn-status-sentinel (proc reason) + (with-current-buffer (process-buffer proc) + (svn-cleanup-status) + (svn-insert-dirs)) + (svn-default-sentinel proc reason)) + +(defun svn-status-v-filter (proc str) + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (looking-at + "\\([ ACDGIMRX?!~][ CM][ L][ +][ S][ KOTB]\\)[ C]? \\([* ]\\) \\(........\\) \\(........\\) \\(............\\) \\([^ ].*\\)\n") + (let ((status (match-string 1)) + (filename (svn-normalise-path (match-string 6)))) + (delete-region (match-beginning 0) + (match-end 0)) + (when (or (not svn-file-filter) + (member filename svn-file-filter)) + (svn-insert-file filename status))))))) + +(defun svn-status-v-sentinel (proc reason) + (with-current-buffer (process-buffer proc) + (svn-cleanup-status)) + (svn-default-sentinel proc reason)) + +;; info + +(defun svn-info-filter (proc str) + "Output filter function for `svn info'." + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t) + (nomore)) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (not nomore) + (cond ((looking-at "URL: \\(.*\\)\n") + (svn-update-label svn-url-label (match-string 1)) + (forward-line 1)) + ((looking-at "Revision: \\([0-9]+\\)\n") + (svn-update-label svn-revision-label (match-string 1)) + (forward-line 1)) + ((looking-at ".*\n") + ;; Unexpected output is left in the buffer + (forward-line 1)) + (t + (setq nomore t))))))) + +;; update + +(defun svn-update (dir) + "Run `svn update'. +Argument DIR is the directory to run svn status in." + (interactive "DDirectory: \n") + (switch-to-svn-buffer dir) + (svn-update-current)) + +(defun svn-update-current (&optional revision) + "Run `svn update' in the current buffer. +Update to REVISION, which defaults to HEAD. +With prefix arg, prompt for REVISION." + (interactive (list + (if current-prefix-arg + (read-string "update to revision (HEAD): " + nil nil "HEAD") + nil))) + (svn-check-running) + (make-local-variable 'svn-updated-files) + (setq svn-updated-files nil) + (let ((args (if revision + (list "-r" revision) + '()))) + (svn-run 'update args "Updating"))) + +(defconst svn-update-flag-name + '((?A . "Added") + (?D . "Deleted") + (?U . "Updated") + (?G . "Merged") + (?C . "Conflict"))) + +(defvar svn-merging nil) + +(defun svn-remap-update-to-status (status-char) + "Map a status character from the svn update command to the resulting status." + (if svn-merging + (cond ((memq status-char '(?U ?G)) + ?M) + (t + status-char)) + (cond ((memq status-char '(?A ?D ?U)) + ?\ ) + ((eq status-char ?G) + ?M) + (t + status-char)))) + +(defun svn-update-filter (proc str) + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t) + nomore) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (not nomore) + (cond ((looking-at + "\\([ ADUCG][ ADUCG][ B]\\) \\(.*\\)\n") + (let* ((status (match-string 1)) + (file-status (elt status 0)) + (prop-status (elt status 1)) + (filename (svn-normalise-path (match-string 2)))) + (delete-region (match-beginning 0) + (match-end 0)) + (svn-insert-file + filename + ;; Remap A and U to unmodified in file and prop status + (format "%c%c...." + (svn-remap-update-to-status file-status) + (svn-remap-update-to-status prop-status)) + ;; Optimize for some common cases + (cond ((= prop-status ?\ ) + (cdr (assq file-status svn-update-flag-name))) + ((= file-status ?\ ) + (let ((s (format "P %s" + (cdr (assq prop-status + svn-update-flag-name))))) + (if (> (length s) 9) + (substring s 0 9) + s))) + (t + status))) + (setq svn-updated-files (cons filename svn-updated-files)))) + ((looking-at "At revision \\([0-9]+\\)\\.\n") + (svn-update-label svn-revision-label (match-string 1)) + (forward-line 1)) + ((and (not svn-merging) + (looking-at "Updated to revision \\([0-9]+\\)\\.\n")) + (svn-update-label svn-revision-label (match-string 1)) + (forward-line 1)) + ((looking-at ".*\n") + ;; Unexpected output is left in the buffer + (forward-line 1)) + (t + (setq nomore t))))))) + +(defun svn-update-sentinel (proc reason) + (with-current-buffer (process-buffer proc) + (svn-insert-dirs) + (mapc #'svn-revert-if-needed svn-updated-files)) + (svn-default-sentinel proc reason)) + +(defun svn-revert-if-needed (filename) + "Revert buffer visiting FILENAME if any, because the file is believed to have +been modified." + (let ((buf (find-buffer-visiting filename))) + (when (and buf (not (buffer-modified-p buf))) + (with-current-buffer buf + (let ((was-ro buffer-read-only)) + (condition-case nil + (revert-buffer t t) + (error nil)) + (when was-ro (toggle-read-only 1))))))) + +(defun svn-complete-url (url pred all) + (string-match "\\`\\(.*/\\)\\([^/]*\\)\\'" url) + (let* ((base-url (match-string 1 url)) + (match-file (match-string 2 url)) + (match-len (length match-file)) + (files)) + (with-current-buffer (svn-run-hidden 'ls (list base-url)) + (goto-char (point-min)) + (while (looking-at ".+$") + (let ((file (match-string 0))) + (if (and (>= (length file) match-len) + (string= match-file (substring file 0 match-len))) + (setq files (cons file files))) + (forward-line 1)))) + (setq files (nreverse files)) + (cond (all + (mapcar (lambda (f) (concat base-url f)) + files)) + ((and (= (length files) 1) + (string= (car files) match-file)) + t) + (t + (try-completion url + (mapcar (lambda (s) (cons (concat base-url s) nil)) + files) + pred))))) + +(defvar svn-switch-history nil) + +(defun svn-switch (url) + "Run `svn switch'." + (interactive (list (completing-read "Switch to (URL): " + 'svn-complete-url + nil nil + (svn-current-url) + 'svn-switch-history))) + (svn-check-running) + (make-local-variable 'svn-updated-files) + (setq svn-updated-files nil) + (svn-update-label svn-url-label url) + (svn-run 'switch (list url))) + +(defun svn-switch-filter (proc str) + "Filter function for 'svn switch' output." + ;; The output is identical(?) to svn update + (svn-update-filter proc str)) + +(defun svn-switch-sentinel (proc reason) + ;; switch is basically a glorified update + (svn-update-sentinel proc reason)) + +;; merge + +(defun svn-merge (from-url from-rev to-url to-rev) + "Run `svn merge'." + (interactive (list (completing-read "Merge from (URL): " + 'svn-complete-url + nil nil + (svn-current-url) + 'svn-switch-history) + (read-string "Merge from revision (HEAD): " + nil nil "HEAD") + (completing-read "Merge to (URL): " + 'svn-complete-url + nil nil + (car svn-switch-history) + 'svn-switch-history) + (read-string "Merge to revision (HEAD): " + nil nil "HEAD"))) + (svn-check-running) + (make-local-variable 'svn-updated-files) + (setq svn-updated-files nil) + (svn-run 'merge (list (format "%s@%s" from-url from-rev) + (format "%s@%s" to-url to-rev)))) + +(defun svn-merge-filter (proc str) + "Filter function for 'svn merge' output." + ;; The output is similar to svn update + (let ((svn-merging t)) + (svn-update-filter proc str))) + +(defun svn-merge-sentinel (proc reason) + ;; merge is basically a glorified update + (svn-update-sentinel proc reason)) + + +(defvar svn-last-inserted-filename nil) +(defvar svn-last-inserted-marker nil) + +(defsubst svn-file-name< (fn1 fn2) + "Compare two filenames, FN1 and FN2 and decide the sort order" + (let ((dir1 (or (file-name-directory fn1) "")) + (dir2 (or (file-name-directory fn2) ""))) + (cond ((and (< (length dir1) (length dir2)) + (string= dir1 (substring dir2 0 (length dir1)))) + t) + ((and (> (length dir1) (length dir2)) + (string= dir2 (substring dir1 0 (length dir2)))) + nil) + (t + (string< fn1 fn2))))) + +(defun svn-insert-file (filename status &optional info) + (save-excursion + (save-restriction + (narrow-to-region (1- svn-files-start) svn-files-stop) + (if svn-last-inserted-filename + (goto-char svn-last-inserted-marker) + ;; Move to the middle of the list and start there + (let ((line-count (count-lines svn-files-start svn-files-stop))) + (goto-char svn-files-start) + (forward-line (/ line-count 2)) + (setq svn-last-inserted-filename + (or (svn-getprop (point) 'file) + (svn-getprop (point) 'dir))))) + ;; Scan for the place to insert the new file, or replace an + ;; existing line + (cond ((null svn-last-inserted-filename) + nil) + ((svn-file-name< filename svn-last-inserted-filename) + ;;(if (not (bobp)) + ;; (forward-line -1)) + (while (and (not (bobp)) + (not (svn-file-name< (or (svn-getprop (point) 'file) + (svn-getprop (point) 'dir)) + filename))) + (forward-line -1)) + (forward-line 1)) + (t + (while (and (not (eobp)) + (svn-file-name< (or (svn-getprop (point) 'file) + (svn-getprop (point) 'dir)) + filename)) + (forward-line 1)))) + (let ((marked nil)) + (when (string= filename (svn-getprop (point) 'file)) + (setq marked (svn-getprop (point) 'mark)) + (delete-region (point) (progn (forward-line 1) (point)))) + (set-marker svn-last-inserted-marker (point)) + (insert " " + (if info (format "%-9s " info) " ") + status + (if marked " * " " ") + filename) + (newline) + (add-text-properties svn-last-inserted-marker (point) + (append (list 'svn-file filename + 'svn-updated t + 'svn-mark marked) + (if marked + (list 'face 'svn-mark-face) + ())))))) + (setq svn-last-inserted-filename filename)) + +(defun svn-remove-line (pos) + (save-excursion + (goto-char pos) + (forward-line 1) + (delete-region pos (point)))) + +(defun svn-insert-dirs () + (interactive) + (save-excursion + (save-restriction + (narrow-to-region svn-files-start svn-files-stop) + (goto-char (point-min)) + (let ((inhibit-read-only t) + (current-dir nil)) + (while (not (eobp)) + (let ((dir (svn-getprop (point) 'dir))) + (if dir + (setq current-dir dir) + (let* ((start (point)) + (file (svn-getprop (point) 'file)) + (dir (or (file-name-directory file) + ""))) + (when (not (string= dir current-dir)) + (setq current-dir dir) + (if (string= dir "") + (insert " Top-level directory:") + (insert " Directory " dir ":")) + (newline) + ;; Next line only needed on XEmacs + (remove-text-properties start (point) '(svn-file nil)) + (add-text-properties start (point) + (list 'face 'bold + 'svn-dir dir)))))) + (forward-line 1)))))) + +(defun svn-file-pos (filename) + "Move to the line containing file information for FILENAME." + (let ((pos svn-files-start)) + (while (and pos + (not (string= filename (get-text-property pos 'svn-file)))) + (setq pos (next-single-property-change pos 'svn-file))) + pos)) + +(defun svn-update-file-status (filename status-char) + (let ((inhibit-read-only t)) + (save-excursion + (svn-goto-file filename) + (beginning-of-line) + (delete-char 1) + (insert status-char)))) + +(defun set-svn-process-status (status) + (let ((description (car svn-running))) + (svn-update-label svn-running-label + (cond ((eq status 'running) + (format "%s..." + (or description "Running"))) + ((eq status 'finished) + "") ; "Finished") + ((eq status 'failed) + "Failed") + (t + "")))) + (cond ((eq status 'running) + (setq mode-line-process ": running")) + (t + (setq mode-line-process nil)))) + +(defvar svn-status-mode-map nil + "Keymap for `svn-status-mode'.") + +(defun svn-status-set-default-mode-map () + (setq svn-status-mode-map (make-sparse-keymap)) + (define-key svn-status-mode-map "a" 'svn-add-file) + (define-key svn-status-mode-map "c" 'svn-commit) + (define-key svn-status-mode-map "f" 'svn-find-file) + (define-key svn-status-mode-map [mouse-2] 'svn-mouse-find-file) + (define-key svn-status-mode-map "\r" 'svn-find-file) + (define-key svn-status-mode-map "g" 'svn-refresh) + (define-key svn-status-mode-map "\M-u" 'svn-update-current) + (define-key svn-status-mode-map " " 'svn-toggle-mark) + (define-key svn-status-mode-map "m" 'svn-mark-forward) + (define-key svn-status-mode-map "\177" 'svn-unmark-backward) + (define-key svn-status-mode-map "u" 'svn-unmark-forward) + (define-key svn-status-mode-map "\M-\177" 'svn-unmark-all) + (define-key svn-status-mode-map "o" 'svn-find-file-other-window) + (define-key svn-status-mode-map "r" 'svn-remove-file) + (define-key svn-status-mode-map "=" 'svn-diff-file) + (define-key svn-status-mode-map "p" 'svn-previous-file) + (define-key svn-status-mode-map "n" 'svn-next-file) + (define-key svn-status-mode-map "l" 'svn-file-log) + (define-key svn-status-mode-map "s" 'svn-refresh-file) + (define-key svn-status-mode-map "S" 'svn-refresh-one) + (define-key svn-status-mode-map "x" 'svn-expunge) + (define-key svn-status-mode-map "U" 'svn-revert) + (define-key svn-status-mode-map "R" 'svn-resolve) + (define-key svn-status-mode-map "M" 'svn-move) + (define-key svn-status-mode-map "D" 'svn-insert-dirs) + (define-key svn-status-mode-map "\M-s" 'svn-switch) + (define-key svn-status-mode-map "\M-m" 'svn-merge) + (define-key svn-status-mode-map "q" 'bury-buffer) + (define-key svn-status-mode-map "?" 'svn-status-help) + (define-key svn-status-mode-map "P" 'svn-propedit) +) + +(unless svn-status-mode-map (svn-status-set-default-mode-map)) + +(defun svn-status-mode () + "Major mode for Subversion status buffers. + +\\{svn-status-mode-map}" + (interactive) + (kill-all-local-variables) + + (make-local-variable 'svn-files-start) + (make-local-variable 'svn-files-stop) + (make-local-variable 'svn-last-inserted-marker) + (make-local-variable 'svn-last-inserted-filename) + (make-local-variable 'svn-running) + + (set (make-local-variable 'list-buffers-directory) + (expand-file-name "*svn*")) + + (setq major-mode 'svn-status-mode + mode-name "Svn status") + (use-local-map svn-status-mode-map) + (setq goal-column svn-status-mark-col)) + + +(defun svn-goto-file (filename) + (let ((pos (next-single-property-change (point-min) 'svn-file))) + (while (and pos + (not (string= (svn-getprop pos 'file) filename))) + (setq pos (next-single-property-change pos 'svn-file))) + (if pos + (goto-char pos)))) + +(defsubst svn-getprop (pos prop) + (get-text-property pos (intern (concat "svn-" (symbol-name prop))))) + +(defsubst svn-setprop (pos prop value) + (save-excursion + (goto-char pos) + (beginning-of-line) + (let ((start (point))) + (forward-line) + (put-text-property start (point) + (intern (concat "svn-" (symbol-name prop))) + value)))) + +(defsubst svn-file-status (pos) + "Get the file status for the file at POS." + (char-after (+ pos svn-status-flags-col))) + +(defsubst svn-prop-status (pos) + "Get the property status for the file at POS." + (char-after (+ pos svn-status-flags-col 1))) + +(defface svn-mark-face + '((((type tty) (class color)) + (:background "cyan" :foreground "black")) + (((class color) (background light)) + (:background "yellow2")) + (((class color) (background dark)) + (:background "darkblue")) + (t (:inverse-video t))) + "Face used to highlight marked files" + :group 'dsvn) + +(defun svn-highlight-line (mark) + (save-excursion + (beginning-of-line) + (let ((start (point))) + (forward-line) + (let ((end (point)) + (prop (list 'face 'svn-mark-face))) + (if mark + (add-text-properties start end prop) + (remove-text-properties start end prop)))))) + +(defun svn-set-mark (pos mark) + "Update the mark on the status line at POS. +Set it if MARK is non-NIL, and clear it if MARK is NIL." + (save-excursion + (let ((inhibit-read-only t)) + (goto-char (+ pos svn-status-mark-col)) + (delete-char 1) + (insert-and-inherit (if mark "*" " ")) + (svn-highlight-line mark) + (forward-line 1) + (put-text-property pos (point) 'svn-mark mark)))) + +(defun svn-actions (&optional pred) + "Return a list of lists (FILE POS) to act on. +Optional argument PRED is a predicate function that is called with POS as +argument." + (let ((files ()) + (pos (next-single-property-change (point-min) 'svn-file))) + (while pos + (when (and (get-text-property pos 'svn-mark) + (or (not pred) + (funcall pred pos))) + (setq files (cons (list (get-text-property pos 'svn-file) + pos) + files))) + (setq pos (next-single-property-change pos 'svn-file))) + (if (null files) + (let ((file (svn-getprop (point) 'file))) + (unless file + (error "No file on this line")) + (when (and pred + (not (funcall pred (line-beginning-position)))) + (error "Invalid file")) + (list (list file + (save-excursion + (beginning-of-line) + (point))))) + (reverse files)))) + +(defun svn-action-files (&optional pred) + "Return a list of file names to act on. +Optional argument PRED is a predicate function that is called with POS as +argument." + (mapcar 'car (svn-actions pred))) + +(defun svn-find-file (pos) + "Find the file under point." + (interactive "d") + (let ((filename (or (svn-getprop pos 'file) + (svn-getprop pos 'dir)))) + (if filename + (find-file filename) + (error "No file on this line")))) + +(defun svn-mouse-find-file (ev) + "Find the file clicked on." + (interactive "e") + (svn-find-file (posn-point (event-start ev)))) + +(defun svn-find-file-other-window () + "Find the file under point." + (interactive) + (let ((filename (or (svn-getprop (point) 'file) + (svn-getprop (point) 'dir)))) + (if filename + (find-file-other-window filename) + (error "No file on this line")))) + +(defun svn-add-file () + "Add the selected files to version control." + (interactive) + (let ((actions (svn-action-files + (lambda (pos) + (or (eq (svn-file-status pos) ?\?) + (error "%s is already under version control" + (svn-getprop pos 'file))))))) + (svn-run 'add actions "Adding files"))) + +(defun svn-add-filter (proc str) + "Output filter function for `svn add'." + ;; This filter is shared with the delete command + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (looking-at + ;; What format is this, really? + "\\([AD] \\)..... \\(.*\\)\n") + (let ((status (concat (match-string 1) " ")) + (filename (svn-normalise-path (match-string 2)))) + (delete-region (match-beginning 0) + (match-end 0)) + (svn-insert-file filename status)))))) + +(defun svn-can-undo-deletion-p (actions) + "Whether all marked files/directories can be deleted undoably" + (or (null actions) + (and (let* ((fp (car actions)) + (pos (cadr fp))) + ;; We can safely remove unmodified files under version control, + ;; and idempotently already deleted files. + (memq (svn-file-status pos) '(?\ ?D))) + (svn-can-undo-deletion-p (cdr actions))))) + +(defun svn-plural (count noun) + (format "%d %s" count + (if (= count 1) + noun + (if (equal (substring noun -1) "y") + (concat (substring noun 0 -1) "ies") + (concat noun "s"))))) + +(defun svn-delete-dir-tree (file) + "Remove a file or directory tree." + (cond ((file-symlink-p file) + ;; In Emacs 21, delete-file refuses to delete a symlink to a + ;; directory. We work around it by overwriting the symlink + ;; with a dangling link first. (We can't do that in later + ;; Emacs versions, because make-symbolic-link may decide to + ;; create the link inside the old link target directory.) + (when (<= emacs-major-version 21) + (make-symbolic-link "/a/file/that/does/not/exist" file t)) + (delete-file file)) + + ((file-directory-p file) + (mapc #'(lambda (f) + (unless (or (equal f ".") (equal f "..")) + (svn-delete-dir-tree (concat file "/" f)))) + (directory-files file)) + (delete-directory file)) + + (t ; regular file + (delete-file file)))) + +(defun svn-remove-file () + "Remove the selected files and directories." + (interactive) + (let* ((actions (svn-actions)) + (dir-count + (length (delq nil (mapcar (lambda (fp) + (file-directory-p (car fp))) + actions)))) + (nondir-count (- (length actions) dir-count)) + (inhibit-read-only t)) + (when (or (svn-can-undo-deletion-p actions) + (y-or-n-p + (format "Really remove %s? " + (cond ((zerop dir-count) + (svn-plural nondir-count "file")) + ((zerop nondir-count) + (svn-plural dir-count "directory")) + (t + (concat + (svn-plural dir-count "directory") + " and " + (svn-plural nondir-count "file"))))))) + (let ((svn-files ())) + (mapc (lambda (fp) + (let ((file (car fp)) + (pos (cadr fp))) + (if (/= (svn-file-status pos) ?\?) + (setq svn-files (cons file svn-files)) + (svn-delete-dir-tree file) + (svn-remove-line pos)))) + ;; traverse the list backwards, to keep buffer positions of + ;; remaining files valid + (reverse actions)) + (when svn-files + (svn-run 'delete (cons "--force" svn-files) "Removing files")))))) + +(defun svn-delete-filter (proc str) + (svn-add-filter proc str)) + +(defun svn-revert () + "Revert the selected files." + (interactive) + (let ((files (svn-action-files + (lambda (pos) + (or (memq (svn-file-status pos) '(?D ?A ?M ?C ?!)) + (memq (svn-prop-status pos) '(?D ?A ?M ?C ?!)) + (error "%s has no local changes" + (svn-getprop pos 'file))))))) + (when (y-or-n-p (format "Really revert %d %s? " + (length files) + (if (> (length files) 1) + "files" + "file"))) + (make-local-variable 'svn-reverted-files) + (setq svn-reverted-files files) + (svn-run 'revert files "Reverting files")))) + +(defun svn-revert-sentinel (proc reason) + (svn-default-sentinel proc reason) + (if (= (process-exit-status proc) 0) + (with-current-buffer (process-buffer proc) + (let ((inhibit-read-only t)) + (svn-run-status-v svn-reverted-files nil)))) + (mapc #'svn-revert-if-needed svn-reverted-files)) + +(defun svn-resolve () + "Mark the selected files as resolved." + (interactive) + (let ((files (svn-action-files + (lambda (pos) + (or (= (svn-file-status pos) ?C) + (= (svn-prop-status pos) ?C) + (error "%s has no conflicts" + (svn-getprop pos 'file))))))) + (make-local-variable 'svn-resolved-files) + (setq svn-resolved-files files) + (svn-run 'resolved files "Marking resolved files"))) + +(defun svn-resolved-sentinel (proc reason) + (svn-default-sentinel proc reason) + (if (= (process-exit-status proc) 0) + (with-current-buffer (process-buffer proc) + (let ((inhibit-read-only t)) + (svn-run-status-v svn-resolved-files nil))))) + +(defun svn-move () + "Move/rename the selected file." + (interactive) + (let ((files (svn-action-files))) + (if (/= (length files) 1) + (error "Can only rename one file at a time")) + (when (file-directory-p (car files)) + (error "Can only move files")) + (let* ((src (car files)) + (dir (file-name-directory src)) + (dst (completing-read "Move to: " + 'svn-complete-url + nil nil + dir + 'svn-switch-history))) + (svn-run 'move (list src dst) "Moving file")))) + +(defun svn-move-filter (proc str) + (save-excursion + (set-buffer (process-buffer proc)) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert str) + (goto-char svn-output-marker) + (while (looking-at + "\\([AD] \\) \\(.*\\)\n") + (let ((status (match-string 1)) + (filename (svn-normalise-path (match-string 2)))) + (if (string= status "A ") + (setq status "A + ")) + (delete-region (match-beginning 0) + (match-end 0)) + (svn-insert-file filename status)))))) + +(defun svn-toggle-file-mark () + "Toggle the mark for the file under point." + (let ((mark (svn-getprop (point) 'mark))) + (svn-set-mark (line-beginning-position) (not mark)))) + +(defun svn-toggle-mark () + "Toggle the mark for the file under point, or files in the dir under point." + (interactive) + (cond ((svn-getprop (point) 'file) + (svn-toggle-file-mark)) + ((svn-getprop (point) 'dir) + (let ((dir (svn-getprop (point) 'dir)) + file) + (save-excursion + (forward-line 1) + (setq file (svn-getprop (point) 'file)) + (while (and file + (svn-in-dir-p dir file)) + (svn-toggle-file-mark) + (forward-line 1) + (setq file (svn-getprop (point) 'file)))))))) + +(defun svn-change-mark-forward (mark) + "Set or clear the mark for the file under point and move to next line." + (cond ((svn-getprop (point) 'file) + (svn-set-mark (line-beginning-position) mark) + (let (pos (svn-next-file-pos)) + (if pos + (svn-next-file 1) + (next-line 1)))) + ((svn-getprop (point) 'dir) + (let ((dir (svn-getprop (point) 'dir)) + file) + (forward-line 1) + (setq file (svn-getprop (point) 'file)) + (while (and file + (svn-in-dir-p dir file)) + (svn-set-mark (point) mark) + (forward-line 1) + (setq file (svn-getprop (point) 'file))) + (move-to-column goal-column))) + (t + (error "No file on line")))) + +(defun svn-mark-forward () + "Set the mark for the file under point and move to next line." + (interactive) + (svn-change-mark-forward t)) + +(defun svn-mark-backward () + "Set the mark for the file under point and move to next line." + (interactive) + (svn-previous-file 1) + (svn-set-mark (line-beginning-position) t)) + +(defun svn-unmark-forward () + "Unset the mark for the file on the previous line." + (interactive) + (svn-change-mark-forward nil)) + +(defun svn-unmark-backward () + "Unset the mark for the file on the previous line." + (interactive) + (svn-previous-file 1) + (svn-set-mark (line-beginning-position) nil)) + +(defun svn-unmark-all () + "Unset the mark for the file on the previous line." + (interactive) + (let ((pos-list (mapcar 'cadr (svn-actions)))) + (while pos-list + (svn-set-mark (car pos-list) nil) + (setq pos-list (cdr pos-list))))) + +(defun svn-diff-file (all) + "Show diff for the file under point. +If the prefix argument ALL is non-NIL, show diff for all selected +files instead." + (interactive "P") + (let ((files (if all + (svn-action-files) + (list (or (svn-getprop (point) 'file) + (svn-getprop (point) 'dir) + (error "No file on line")))))) + (unless (svn-run-with-output "diff" files 'diff-mode) + (message "No difference found")))) + +(defun svn-previous-file (arg) + "Move to the ARGth previous line containing file information." + (interactive "p") + (let ((pos (previous-single-property-change (point) 'svn-file))) + (if (not pos) + (error "No previous file")) + + ;; Usually we have just found the beginning of the current line + (when (string= (get-text-property pos 'svn-file) + (svn-getprop (point) 'file)) + (setq pos (previous-single-property-change pos 'svn-file)) + (if (not pos) + (error "No previous file"))) + + ;; Skip lines that don't contain file info + (when (null (get-text-property pos 'svn-file)) + (setq pos (previous-single-property-change pos 'svn-file)) + (if (not pos) + (error "No previous file"))) + + (goto-char (+ pos goal-column)) + (if (> arg 1) + (svn-previous-file (1- arg))))) + +(defun svn-next-file-pos () + (let ((pos (next-single-property-change (point) 'svn-file))) + (and pos + ;; Skip lines that don't contain file info + (if (null (get-text-property pos 'svn-file)) + (next-single-property-change pos 'svn-file) + pos)))) + +(defun svn-next-file (arg) + "Move to the ARGth next line containing file information." + (interactive "p") + (let ((pos (svn-next-file-pos))) + (if pos + (goto-char (+ pos goal-column)) + ;; Allow stepping past last file + (if (< (point) svn-files-stop) + (next-line 1) + (error "No next file"))) + + (if (> arg 1) + (svn-next-file (1- arg))))) + +(defun svn-expunge () + "Remove entried for unmodified files." + (interactive) + (save-excursion + (let ((inhibit-read-only t) + (last-dir "/")) + (goto-char svn-files-stop) + (forward-line -1) + (while (>= (point) svn-files-start) + (let ((dir (svn-getprop (point) 'dir))) + (if dir + (progn + (when last-dir + ;; If this is a superdirectory, leave it + (unless (and (> (length dir) (length last-dir)) + (string= (substring dir 0 (length last-dir)) + last-dir)) + (svn-remove-line (point)))) + (setq last-dir dir)) + (let ((file-status (svn-file-status (point))) + (prop-status (svn-prop-status (point)))) + (if (and (memq file-status '(?\ ?I ?X)) + (eq prop-status ?\ )) + (svn-remove-line (point)) + (setq last-dir nil))))) + (forward-line -1)))) + (move-to-column goal-column) + (setq svn-last-inserted-filename nil)) + + +(defun svn-format-help-column (table) + (mapcar (lambda (cmd-desc) + (let ((cmd (car cmd-desc)) + (desc (cadr cmd-desc))) + (format "%-4s %s" + (key-description (car (where-is-internal cmd))) + desc))) + table)) + +(defun svn-merge-columns-list (columns fmt) + (let ((first-lines (mapcar #'car columns))) + (and (eval `(or ,@first-lines)) + (cons (mapconcat (lambda (str) (format fmt (or str ""))) + first-lines " | ") + (svn-merge-columns-list (mapcar #'cdr columns) fmt))))) + +(defun svn-merge-columns (columns width) + (mapconcat #'identity + (svn-merge-columns-list columns (format "%%-%ds" width)) + "\n")) + +(defun svn-status-help () + "Display keyboard help for the svn-status buffer." + (interactive) + (message (svn-merge-columns + (list (svn-format-help-column + '((svn-commit "commit marked files") + (svn-add-file "add marked files") + (svn-remove-file "remove marked files") + (svn-revert "revert marked files") + (svn-update-current "update working copy") + (svn-resolve "resolve conflicts") + (svn-move "rename/move files") + (svn-switch "switch working tree") + (svn-merge "merge into WC") + (svn-propedit "edit properties"))) + (svn-format-help-column + '((svn-mark-forward "mark and go down") + (svn-unmark-backward "go up and unmark") + (svn-unmark-forward "unmark and go down") + (svn-toggle-mark "toggle mark") + (svn-unmark-all "unmark all"))) + (svn-format-help-column + '((svn-find-file "visit file") + (svn-find-file-other-window "visit file other win") + (svn-diff-file "show file diff") + (svn-file-log "show file log") + (svn-refresh "refresh all files") + (svn-refresh-file "refresh marked files") + (svn-refresh-one "refresh named file") + (svn-expunge "expunge unchanged")))) + 24))) + +;;; Hooks + +(defun svn-buffer-list () + "Return a list of svn status buffers." + (let ((buffers ()) + (all-buffers (buffer-list))) + (while all-buffers + (let ((buf (car all-buffers))) + (if (eq (with-current-buffer buf major-mode) + 'svn-status-mode) + (setq buffers (cons buf buffers)))) + (setq all-buffers (cdr all-buffers))) + buffers)) + +(defun svn-update-status-flag (pos flag &optional prop-flag) + "Update the status flag column for file at position POS. +Argument FLAG is the character to use." + (save-excursion + (goto-char (+ pos svn-status-flags-col)) + (insert-and-inherit flag) + (delete-char 1) + (when prop-flag + (insert-and-inherit prop-flag) + (delete-char 1)))) + +(defun svn-update-status-msg (pos msg) + "Update the message column for file at position POS. +Argument MSG is the character to use." + (save-excursion + (goto-char (+ pos svn-status-msg-col)) + (delete-char 9) + (insert-and-inherit (format "%9s" msg)))) + +(defun svn-foreach-svn-buffer (file-name function) + "Call FUNCTION for each svn status buffer that contains FILE-NAME. +The current buffer will be the svn status buffer, and the arguments to +the function is the local form of the filename and the buffer position +where the file information is." + (let* ((svn-buffers (svn-buffer-list)) + (inhibit-read-only t) + (file-path (file-truename file-name))) + (while svn-buffers + (with-current-buffer (car svn-buffers) + (let ((dir (file-truename default-directory))) + (when (and (>= (length file-path) (length dir)) + (string= dir (substring file-path 0 (length dir)))) + (let* ((local-file-name (substring file-path (length dir))) + (file-pos (svn-file-pos local-file-name))) + (funcall function local-file-name file-pos))))) + (setq svn-buffers (cdr svn-buffers))))) + +(defun svn-after-save () + "Update svn status buffer when saving a file." + (svn-foreach-svn-buffer + (buffer-file-name) + (lambda (local-file-name file-pos) + (if file-pos + (let ((old-status (svn-file-status file-pos))) + (when (= old-status ?\ ) + (svn-update-status-flag file-pos ?M)) + (svn-update-status-msg file-pos "")) + (svn-run-status-v (list local-file-name) nil)))) + nil) + +(add-hook 'after-save-hook 'svn-after-save) + +(defun svn-after-commit () + "Update svn status buffer when committing a file from `vc-mode'." + (svn-foreach-svn-buffer + (buffer-file-name) + (lambda (local-file-name file-pos) + (if file-pos + (progn + (svn-update-status-flag file-pos ?\ ) + (svn-update-status-msg file-pos "Committed")) + (svn-insert-file local-file-name " " "Committed")))) + nil) + +(add-hook 'vc-checkin-hook 'svn-after-commit) + +(defun svn-after-vc-command (command file-or-files flags) + (when (and (string= command "svn") + ;; Ignore command that do not modify file + (not (member (car flags) '("ann" "annotate" "blame" + "diff" "praise" "status")))) + (mapc (lambda (file) + (svn-foreach-svn-buffer + file + (lambda (local-file-name file-pos) + (svn-refresh-item local-file-name t)))) + ;; In emacs versions prior to 23, the argument is a single file. + (if (listp file-or-files) + file-or-files + (list file-or-files))))) + +(add-hook 'vc-post-command-functions 'svn-after-vc-command) + +(setq uniquify-list-buffers-directory-modes + (cons 'svn-status-mode + uniquify-list-buffers-directory-modes)) + +(provide 'dsvn) + +;;; dsvn.el ends here --- subversion-1.7.9.orig/debian/contrib/emacs/psvn.el +++ subversion-1.7.9/debian/contrib/emacs/psvn.el @@ -0,0 +1,6523 @@ +;;; psvn.el --- Subversion interface for emacs +;; Copyright (C) 2002-2009 by Stefan Reichoer + +;; Author: Stefan Reichoer +;; $Id: psvn.el 915036 2010-02-22 19:47:55Z mf $ + +;; 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 intrepid with svn 1.5.1 + +;; 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.apache.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 +;; Or you can check it out from the subversion repository: +;; svn co http://svn.apache.org/repos/asf/subversion/trunk/contrib/client-side/emacs emacs-svn + +;; 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: + +(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)) + +(defconst svn-psvn-revision "$Id: psvn.el 915036 2010-02-22 19:47:55Z mf $" + "The revision number of psvn.") + +;;; 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-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.") +(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-status-temp-dir + (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) (file-name-as-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: ") + (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-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 there is no .svn directory, examine if there is CVS and run +`cvs-examine'. Otherwise ask if to run `dired'." + (interactive (list (svn-read-directory-name "SVN status directory: " + nil default-directory nil) + current-prefix-arg)) + (let ((svn-dir (format "%s%s" + (file-name-as-directory dir) + (svn-wc-adm-dir-name))) + (cvs-dir (format "%sCVS" (file-name-as-directory dir)))) + (cond + ((file-directory-p svn-dir) + (setq arg (svn-status-possibly-negate-meaning-of-arg arg 'svn-status)) + (svn-status-1 dir arg)) + ((and (file-directory-p cvs-dir) + (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)) + (set-buffer cur-buf) + (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* ((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) + (unless (file-executable-p default-directory) + (message "psvn: workaround in %s needed: %s no longer exists" (current-buffer) default-directory) + (cd (expand-file-name "~"))) + (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)) + (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) + (let ((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.apache.org/repos/asf/subversion/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 (* 2 (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'." + (let ((url) + (repository-root) + (last-changed-author)) + (save-excursion + (set-buffer svn-process-buffer-name) + (goto-char (point-min)) + (let ((case-fold-search t)) + (search-forward "url: ") + (setq url (buffer-substring-no-properties (point) (svn-point-at-eol))) + (when (search-forward "repository root: " nil t) + (setq repository-root (buffer-substring-no-properties (point) (svn-point-at-eol)))) + (when (search-forward "last changed author: " nil t) + (setq last-changed-author (buffer-substring-no-properties (point) (svn-point-at-eol)))))) + (setq svn-status-base-info `((url ,url) (repository-root ,repository-root) (last-changed-author ,last-changed-author))))) + +(defun svn-status-base-info->url () + "Extract the url part from `svn-status-base-info'." + (if svn-status-base-info + (cadr (assoc 'url svn-status-base-info)) + "")) + +(defun svn-status-base-info->repository-root () + "Extract the repository-root part from `svn-status-base-info'." + (if svn-status-base-info + (cadr (assoc 'repository-root svn-status-base-info)) + "")) + +(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-name prefix file-info-list postfix) + "Create an svn client argument file" + ;; create the arg file on the remote host when we will run svn on this host! + (setq file-name (svn-expand-filename-for-remote-access file-name)) + ;; (message "svn-status-create-arg-file %s: %s" default-directory file-name) + (with-temp-file file-name + (insert prefix) + (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))) + + (insert postfix)))) + +(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-temp-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-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-temp-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-temp-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-temp-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-temp-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-temp-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 (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-temp-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-temp-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))))) + (unless svn-client-version + (svn-status-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-temp-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))) + (let ((content + (with-temp-buffer + (if (string= revision "BASE") + (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-temp-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-temp-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. + +Note: This mode does not yet work on XEmacs... +It is probably because the revisions are in 'before-string properties of overlays + +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 ov (make-overlay (point) (point))) + (overlay-put ov 'svn-blame-line-info t) + (setq s (buffer-substring-no-properties (svn-point-at-bol) (+ (svn-point-at-bol) info-end-col))) + (overlay-put ov 'before-string (propertize s 'face 'svn-status-blame-rev-number-face)) + (overlay-put ov 'rev-info (delete "" (split-string s " "))) + (delete-region (svn-point-at-bol) (+ (svn-point-at-bol) info-end-col)) + (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-run nil t 'parse-info "info" ".") + (with-current-buffer svn-process-buffer-name + ;; (message "svn-status-repo-for-path: %s: default-directory: %s directory: %s old-process-default-dir: %s" svn-process-buffer-name default-directory directory old-process-default-dir) + (setq default-directory old-process-default-dir) + (goto-char (point-min)) + (let ((case-fold-search t)) + (if (search-forward "repository root: " nil t) + (buffer-substring-no-properties (point) (svn-point-at-eol)) + (when (search-forward "repository uuid: " nil t) + (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) + (concat "Svn Repo UUID: " (buffer-substring-no-properties (point) (svn-point-at-eol))))))))) + +(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) + (unless svn-client-version + (svn-status-version)) + (let* ((base-dir start-dir) + (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))) + ;; (message "repository-root: %s start-dir: %s" repository-root start-dir) + (if (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 + (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))))) + (setq base-dir (and in-tree 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-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)))))) + +;; -------------------------------------------------------------------------------- +;; 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)))) + (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 +;; End: +;;; psvn.el ends here --- subversion-1.7.9.orig/debian/contrib/svn-clean +++ subversion-1.7.9/debian/contrib/svn-clean @@ -0,0 +1,275 @@ +#!/usr/bin/perl + +# svn-clean - Wipes out unversioned files from SVN working copy. +# Copyright (C) 2004, 2005, 2006 Simon Perreault +# +# This program 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 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +use strict; +use Cwd; +use File::Path; +use Getopt::Long; +use Pod::Usage; + +# Try to use SVN module if available. +my $use_svn_module = eval { require SVN::Client }; + +my $CWD = getcwd; + +my @exclude = (); +my $force = 0; +my $quiet = 0; +my $print = 0; +my $help = 0; +my $man = 0; +my $nonrecursive = 0; +my @paths = ($CWD); +GetOptions( + "exclude=s" => \@exclude, + "force" => \$force, + "non-recursive|N" => \$nonrecursive, + "quiet" => \$quiet, + "print" => \$print, + "help|?" => \$help, + "man" => \$man +) or pod2usage(2); +pod2usage(1) if $help; +pod2usage( -exitstatus => 0, -verbose => 2 ) if $man; +@paths = map { Cwd::abs_path($_) } @ARGV if @ARGV; + +# Precompile regexes. +$_ = qr/$_/ foreach @exclude; + +my %svn_clean_ignore; +if ($use_svn_module) { + + # Create SVN client object. No need for connection to remote server. + my $ctx = new SVN::Client; + + for my $path (@paths) { + my $ign = $ctx->propget('svn-clean:ignore', $path, undef, 1); + for my $dir (keys %$ign) { + for (split /\n/, $ign->{$dir}) { + for (glob "$dir/$_") { + $svn_clean_ignore{$_} = 1 if -e $_; + } + } + } + # Call handler function with status info for each file. + $ctx->status( $path, undef, \&clean, !$nonrecursive, 1, 0, 1 ); + } + exit 0; +} +else { + warn "Warning: Not using SVN Perl modules, this might be slow.\n" + unless $quiet; + + my @command = qw(svn propget svn-clean:ignore); + push @command, '-R' unless $nonrecursive; + open PG, '-|', @command, @paths; + my $dir; + while () { + if (s/(.*?) - //) { + $dir = $1; + } + chomp; + for (glob "$dir/$_") { + $svn_clean_ignore{$_} = 1 if -e $_; + } + } + close PG; + + @command = qw(svn status --no-ignore -v); + if ($nonrecursive) { + push @command, '-N'; + } + + # Main file-wiping loop. + if ( $^O eq 'MSWin32' ) { + + # Perl on Windows currently doesn't have list pipe opens. + open SVN, join( ' ', @command, @paths ) . '|' + or die "Can't call program \"svn\": $!\n"; + } + else { + open SVN, "-|", @command, @paths + or die "Can't call program \"svn\": $!\n"; + } + LINE: while () { + if (/^([\?ID])/) { + my $file = (split)[-1]; + next if $svn_clean_ignore{$file}; + foreach my $ex (@exclude) { + if ( $file =~ $ex ) { + print "excluded $file\n" unless $quiet or $print; + next LINE; + } + } + if ( $1 eq 'D' ) { + next unless -f $file; + } + else { + next unless -e $file; + } + if ($print) { + print "$file\n"; + } + else { + rmtree( $file, !$quiet, !$force ); + } + } + } +} + +# Main file-wiping function. +sub clean { + my ( $path, $status ) = @_; + return if $svn_clean_ignore{$path}; + + # Use relative path for pretty-printing. + if ( $path =~ s/^\Q$CWD\E\/?//o ) { + + # If the substitution succeeded, we should have a relative path. Make + # sure we don't delete critical stuff. + return if $path =~ /^\//; + } + + # Find files needing to be removed. + if ( $status->text_status == $SVN::Wc::Status::unversioned + or $status->text_status == $SVN::Wc::Status::ignored + or $status->text_status == $SVN::Wc::Status::deleted ) + { + foreach my $ex (@exclude) { + if ( $path =~ $ex ) { + print "excluded $path\n" unless $quiet or $print; + return; + } + } + + # Make sure the file exists before removing it. Do not remove deleted + # directories as they are needed to remove the files they contain when + # committing. + lstat $path or stat $path; + if ( + -e _ + and ( not -d _ + or $status->text_status != $SVN::Wc::Status::deleted ) + ) + { + if ($print) { + print "$path\n"; + } + else { + rmtree( $path, !$quiet, !$force ); + } + } + } +} + +__END__ + +=head1 NAME + +svn-clean - Wipes out unversioned files from Subversion working copy + +=head1 SYNOPSIS + +svn-clean [options] [directory or file ...] + +=head1 DESCRIPTION + +B will scan the given files and directories recursively and find +unversioned files and directories (files and directories that are not present in +the Subversion repository). After the scan is done, these files and directories +will be deleted. Files which match patterns in the I dir +property will be spared, much as the I property works for B. + +If no file or directory is given, B defaults to the current directory +("."). + +B uses the SVN Perl modules if they are available. This is much +faster than parsing the output of the B command-line client. + +=head1 OPTIONS + +=over 8 + +=item B<-e>, B<--exclude> + +A regular expression for filenames to be exluded. For example, the following +command will skip files ending in ".zip": + +=over 8 + +svn-clean --exclude '\.zip$' + +=back + +Multiple exclude patterns can be specified. If at least one matches, then the +file is skipped. For example, the following command will skip files ending in +".jpg" or ".png": + +=over 8 + +svn-clean --exclude '\.jpg$' --exclude '\.png$' + +=back + +The following command will skip the entire "build" subdirectory: + +=over 8 + +svn-clean --exclude '^build(/|$)' + +=back + +=item B<-f>, B<--force> + +Files to which you do not have delete access (if running under VMS) or write +access (if running under another OS) will not be deleted unless you use this +option. + +=item B<-N>, B<--non-recursive> + +Do not search recursively for unversioned files and directories. Unversioned +directories will still be deleted along with all their contents. + +=item B<-q>, B<--quiet> + +Do not print progress info. In particular, do not print a message each time a +file is examined, giving the name of the file, and indicating whether "rmdir" or +"unlink" is used to remove it, or that it's skipped. + +=item B<-p>, B<--print> + +Do not delete anything. Instead, print the name of every file and directory that +would have been deleted. + +=item B<-?>, B<-h>, B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=back + +=head1 AUTHOR + +Simon Perreault + +=cut --- subversion-1.7.9.orig/debian/contrib/svn-fast-backup +++ subversion-1.7.9/debian/contrib/svn-fast-backup @@ -0,0 +1,285 @@ +#!/usr/bin/env python2.4 + +# svn-fast-backup: use rsync snapshots for very fast FSFS repository backup. +# Multiple FSFS backups share data via hardlinks, meaning old backups are +# almost free, since a newer revision of a repository is almost a complete +# superset of an older revision. + +# This is good for replacing incremental log-dump+restore-style backups +# because it is just as space-conserving and even faster; there is no +# inter-backup state (old backups are essentially caches); each backup +# directory is self-contained. It keeps the same interface as svn-hot-backup +# (if you use --force), but only works for FSFS repositories. + +# Author: Karl Chen + +## quarl 2005-08-17 initial version +## quarl 2005-09-01 refactor, documentation; new options: --force, --keep, +## --simulate, --trace + +# $HeadURL: http://svn.apache.org/repos/asf/subversion/branches/1.6.x/contrib/server-side/svn-fast-backup $ +# $LastChangedRevision: 923804 $ +# $LastChangedDate: 2010-03-16 15:22:28 +0000 (Tue, 16 Mar 2010) $ +# $LastChangedBy: cmpilato $ + +# Originally based on svn-hot-backup.py, whose copyright notice states: + +# ==================================================================== +# Copyright (c) 2000-2004 CollabNet. All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://subversion.tigris.org/license-1.html. +# If newer versions of this license are posted there, you may use a +# newer version instead, at your option. +# +# This software consists of voluntary contributions made by many +# individuals. For exact contribution history, see the revision +# history and logs, available at http://subversion.tigris.org/. +# ==================================================================== + +###################################################################### + +import sys, os, re +import getopt +import subprocess # python2.4 + +###################################################################### +# Global Settings + +svnlook = "svnlook" # Path to svnlook +svnadmin = "svnadmin" # Path to svnadmin +rsync = "rsync" # Path to rsync + +###################################################################### +# Command line arguments + +def usage(): + raise SystemExit("""Syntax: %s [OPTIONS] repos_path backup_dir + +Makes a hot backup of a Subversion FSFS repository at REPOS_PATH to +BACKUP_DIR/repos-rev. + +If a previous version exists, make hard links of its files using rsync. +As multiple FSFS backups share data via hardlinks, old backups use +almost no space, since a newer revision of a repository is almost a complete +superset of an older revision (excluding direct repository modifications). + +Keeps up to N backups and deletes the rest. (N includes the current backup.) + +OPTIONS: + -h, --help This screen + -q, --quiet Quieter than usual + -k, --keep=N Keep N backups instead of 64 + -k, --keep=all Keep all backups (never delete any) + -f, --force Make a new backup even if one with current revision exists + -t, --trace Show actions + -s, --simulate Don't perform actions + +""" %sys.argv[0]) + +class Options: pass + +def default_options(): + options = Options() + options.force = False + options.trace = False + options.simulate = False + options.quiet = False + options.keep = 64 # Number of backups to keep around + return options + +def parse_commandline(): + options = default_options() + + try: + opts, args = getopt.getopt(sys.argv[1:], 'qhk:fts', ['quiet', 'help', 'keep=', 'force', + 'trace', 'simulate']) + except getopt.GetoptError, e: + print >>sys.stderr, "Error:", e + usage() + + for (o,a) in opts: + if o == '-h' or o == '--help': + usage() + elif o == '-q' or o == '--quiet': + options.quiet = True + elif o == '-f' or o == '--force': + options.force = True + elif o == '-t' or o == '--trace': + options.trace = True + elif o == '-s' or o == '--simulate': + options.simulate = True + elif o == '-k' or o == '--keep': + if a.strip().lower() == 'all': + options.keep = 0 + else: + options.keep = int(a) + else: + raise Exception("Internal error") + + if len(args) != 2: + usage() + + # Path to repository + options.repo_dir = args[0] + + # Where to store the repository backup. The backup will be placed in a + # *subdirectory* of this location, named after the youngest revision. + + options.backup_dir = os.path.abspath(args[1]) + + options.repo = os.path.basename(os.path.abspath(options.repo_dir)) + + return options + +def comparator(a, b): + # We pass in filenames so there is never a case where they are equal. + regexp = re.compile("-(?P[0-9]+)(-(?P[0-9]+))?$") + matcha = regexp.search(a) + matchb = regexp.search(b) + reva = int(matcha.groupdict()['revision']) + revb = int(matchb.groupdict()['revision']) + if (reva < revb): + return -1 + elif (reva > revb): + return 1 + else: + inca = matcha.groupdict()['increment'] + incb = matchb.groupdict()['increment'] + if not inca: + return -1 + elif not incb: + return 1; + elif (int(inca) < int(incb)): + return -1 + else: + return 1 + +def pipe(command): + return subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip() + +def readfile(filename): + try: + return open(filename).read().strip() + except: + return '' + +def runcmd(cmd): + if options.trace: + print >>sys.stderr, '#', cmd + if options.simulate: + return 0 + return subprocess.call(cmd) + +def deltree(path): + runcmd(['rm', '-r', path]) + +def get_youngest_revision(): + if readfile(os.path.join('db', 'fs-type')) != 'fsfs': + raise SystemExit("Path '%s' doesn't contain a FSFS repository"%options.repo_dir) + + return pipe([svnlook,"youngest","."]) + +def list_repo_backups(): + '''Return a sorted list of backups for this repository.''' + regexp = re.compile(options.repo + "-[0-9]+(-[0-9]+)?$") + directory_list = [x for x in os.listdir(options.backup_dir) if regexp.match(x)] + directory_list.sort(comparator) + return directory_list + +def delete_old_backups(): + if options.keep <= 0: + return + + for item in list_repo_backups()[:-options.keep]: + old_backup_subdir = os.path.join(options.backup_dir, item) + print " Removing old backup: ", old_backup_subdir + deltree(old_backup_subdir) + +def find_next_backup_name(youngest): + # If there is already a backup of this revision, then append the next + # highest increment to the path. We still need to do a backup because the + # repository might have changed despite no new revision having been + # created. We find the highest increment and add one rather than start + # from 1 and increment because the starting increments may have already + # been removed due to options.keep. + + regexp = re.compile(options.repo + "-" + youngest + "(-(?P[0-9]+))?$") + directory_list = os.listdir(options.backup_dir) + young_list = [ x for x in directory_list if regexp.match(x) ] + young_list.sort(comparator) + + if not young_list: + return "%s-%s" %(options.repo, youngest) + + # Backups for this revision exist already. + + if not options.force: + if not options.quiet: + print "Backup already exists at",young_list[-1] + raise SystemExit + + increment = int(regexp.match(young_list[-1]).groupdict()['increment'] or '0') + + return "%s-%s-%d" %(options.repo, youngest, increment+1) + +def do_rsync_backup(): + youngest = get_youngest_revision() + + if not options.quiet: + print "Beginning hot backup of '%s' (youngest revision is %s)..." %(options.repo, youngest), + + backup_subdir = os.path.join(options.backup_dir, find_next_backup_name(youngest)) + backup_tmpdir = backup_subdir + '.tmp' + + if os.path.exists(backup_tmpdir): + raise SystemExit("%s: Backup in progress? '%s' exists -- aborting."%(sys.argv[0],backup_tmpdir)) + + if not options.simulate: + os.mkdir(backup_tmpdir) # ensures atomicity + + if os.path.exists(backup_subdir): + # Check again after doing mkdir (which serves as a mutex acquire) -- + # just in case another process just finished the same backup. + if not options.quiet: + print "Backup already exists at",backup_subdir + raise SystemExit + + previous_backups = list_repo_backups() + + ### Use rsync to make a copy. + # We need to copy the 'current' file first. + # Don't copy the transactions/ directory. + # See http://svn.apache.org/repos/asf/subversion/trunk/notes/fsfs + + rsync_dest = os.path.join(backup_tmpdir,'') + + # copy db/current. -R tells rsync to use relative pathnames. + if runcmd([rsync, '-aR', 'db/current', rsync_dest]): + raise Exception("%s: rsync failed" %sys.argv[0]) + + # Now copy everything else. + cmd = [rsync, '-a', + '--exclude', 'db/current', + '--exclude', 'db/transactions/*', + '--exclude', 'db/log.*', + '.', rsync_dest] + # If there's a previous backup, make hard links against the latest. + if previous_backups: + cmd += ['--link-dest', os.path.join(options.backup_dir, previous_backups[-1])] + + if runcmd(cmd): + raise Exception("%s: rsync failed" %sys.argv[0]) + + # Rename to final name. + if not options.simulate: + os.rename(backup_tmpdir, backup_subdir) + + print "Finished backup to", backup_subdir + + +options = parse_commandline() +os.chdir(options.repo_dir) +do_rsync_backup() +delete_old_backups() --- subversion-1.7.9.orig/debian/contrib/svn_apply_autoprops.py +++ subversion-1.7.9/debian/contrib/svn_apply_autoprops.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python + +# This script reads the auto-properties defined in the +# $HOME/.subversion/config file and applies them recursively to all +# the files and directories in the current working copy. It may +# behave differently than the Subversion command line; where the +# subversion command line may only apply a single matching +# auto-property to a single pathname, this script will apply all +# matching lines to a single pathname. +# +# To do: +# 1) Switch to using the Subversion Python bindings. +# 2) Allow a command line option to specify the configuration file to +# load the auto-properties from. +# +# $HeadURL: http://svn.apache.org/repos/asf/subversion/branches/1.6.x/contrib/client-side/svn_apply_autoprops.py $ +# $LastChangedRevision: 860861 $ +# $LastChangedDate: 2006-07-20 03:41:28 +0000 (Thu, 20 Jul 2006) $ +# $LastChangedBy: blair $ +# +# Copyright (C) 2005,2006 Blair Zajac +# +# This script 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 of the License, or +# (at your option) any later version. +# +# This script 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. +# +# A copy of the GNU General Public License can be obtained by writing +# to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA. + +import fnmatch +import os +import re +import sys + +# The path to the Subversion configuration file. +SVN_CONFIG_FILENAME = '$HOME/.subversion/config' + +# The name of Subversion's private directory in working copies. +SVN_WC_ADM_DIR_NAME = '.svn' + +def get_autoprop_lines(fd): + lines = [] + reading_autoprops = 0 + + re_start_autoprops = re.compile('^\s*\[auto-props\]\s*') + re_end_autoprops = re.compile('^\s*\[\w+\]\s*') + + for line in fd.xreadlines(): + if reading_autoprops: + if re_end_autoprops.match(line): + reading_autoprops = 0 + continue + else: + if re_start_autoprops.match(line): + reading_autoprops = 1 + continue + + if reading_autoprops: + lines += [line] + + return lines + +def process_autoprop_lines(lines): + result = [] + + for line in lines: + # Split the line on the = separating the fnmatch string from the + # properties. + try: + (fnmatch, props) = line.split('=', 1) + except ValueError: + continue + + # Remove leading and trailing whitespace from the fnmatch and + # properties. + fnmatch = fnmatch.strip() + props = props.strip() + + # Create a list of property name and property values. Remove all + # leading and trailing whitespce from the propery names and + # values. + props_list = [] + for prop in props.split(';'): + prop = prop.strip() + if not len(prop): + continue + try: + (prop_name, prop_value) = prop.split('=', 1) + prop_name = prop_name.strip() + prop_value = prop_value.strip() + except ValueError: + prop_name = prop + prop_value = '*' + if len(prop_name): + props_list += [(prop_name, prop_value)] + + result += [(fnmatch, props_list)] + + return result + +def filter_walk(autoprop_lines, dirname, filenames): + # Do no descend into directories that do not have a .svn directory. + try: + filenames.remove(SVN_WC_ADM_DIR_NAME) + except ValueError: + filenames = [] + print "Will not process files in '%s' because it does not have a '%s' " \ + "directory." \ + % (dirname, SVN_WC_ADM_DIR_NAME) + return + + filenames.sort() + + # Find those filenames that match each fnmatch. + for autoprops_line in autoprop_lines: + fnmatch_str = autoprops_line[0] + prop_list = autoprops_line[1] + + matching_filenames = fnmatch.filter(filenames, fnmatch_str) + if not matching_filenames: + continue + + for prop in prop_list: + command = ['svn', 'propset', prop[0], prop[1]] + for f in matching_filenames: + command += ["%s/%s" % (dirname, f)] + + status = os.spawnvp(os.P_WAIT, 'svn', command) + if status: + print 'Command "%s" failed with exit status %s' \ + % (command, status) + sys.exit(1) + +def main(): + config_filename = os.path.expandvars(SVN_CONFIG_FILENAME) + try: + fd = file(config_filename) + except IOError: + print "Cannot open svn configuration file '%s' for reading: %s" \ + % (config_filename, sys.exc_value.strerror) + + autoprop_lines = get_autoprop_lines(fd) + + fd.close() + + autoprop_lines = process_autoprop_lines(autoprop_lines) + + os.path.walk('.', filter_walk, autoprop_lines) + +if __name__ == '__main__': + sys.exit(main()) --- subversion-1.7.9.orig/debian/contrib/svn_load_dirs/LICENSE_AFL3.txt +++ subversion-1.7.9/debian/contrib/svn_load_dirs/LICENSE_AFL3.txt @@ -0,0 +1,190 @@ +http://www.opensource.org/licenses/academic.php + +Academic Free License ("AFL") v. 3.0 + +This Academic Free License (the "License") applies to any original +work of authorship (the "Original Work") whose owner (the "Licensor") +has placed the following licensing notice adjacent to the copyright +notice for the Original Work: + + Licensed under the Academic Free License version 3.0 + + 1) Grant of Copyright License. Licensor grants You a worldwide, + royalty-free, non-exclusive, sublicensable license, for the + duration of the copyright, to do the following: + a) to reproduce the Original Work in copies, either alone or as + part of a collective work; + b) to translate, adapt, alter, transform, modify, or arrange the + Original Work, thereby creating derivative works ("Derivative + Works") based upon the Original Work; + c) to distribute or communicate copies of the Original Work and + Derivative Works to the public, under any license of your + choice that does not contradict the terms and conditions, + including Licensor's reserved rights and remedies, in this + Academic Free License; + d) to perform the Original Work publicly; and + e) to display the Original Work publicly. + + 2) Grant of Patent License. Licensor grants You a worldwide, + royalty-free, non- exclusive, sublicensable license, under patent + claims owned or controlled by the Licensor that are embodied in + the Original Work as furnished by the Licensor, for the duration + of the patents, to make, use, sell, offer for sale, have made, and + import the Original Work and Derivative Works. + + 3) Grant of Source Code License. The term "Source Code" means the + preferred form of the Original Work for making modifications to it + and all available documentation describing how to modify the + Original Work. Licensor agrees to provide a machine-readable copy + of the Source Code of the Original Work along with each copy of + the Original Work that Licensor distributes. Licensor reserves the + right to satisfy this obligation by placing a machine-readable + copy of the Source Code in an information repository reasonably + calculated to permit inexpensive and convenient access by You for + as long as Licensor continues to distribute the Original Work. + + 4) Exclusions From License Grant. Neither the names of Licensor, nor + the names of any contributors to the Original Work, nor any of + their trademarks or service marks, may be used to endorse or + promote products derived from this Original Work without express + prior permission of the Licensor. Except as expressly stated + herein, nothing in this License grants any license to Licensor's + trademarks, copyrights, patents, trade secrets or any other + intellectual property. No patent license is granted to make, use, + sell, offer for sale, have made, or import embodiments of any + patent claims other than the licensed claims defined in Section + 2. No license is granted to the trademarks of Licensor even if + such marks are included in the Original Work. Nothing in this + License shall be interpreted to prohibit Licensor from licensing + under terms different from this License any Original Work that + Licensor otherwise would have a right to license. + + 5) External Deployment. The term "External Deployment" means the use, + distribution, or communication of the Original Work or Derivative + Works in any way such that the Original Work or Derivative Works + may be used by anyone other than You, whether those works are + distributed or communicated to those persons or made available as + an application intended for use over a network. As an express + condition for the grants of license hereunder, You must treat any + External Deployment by You of the Original Work or a Derivative + Work as a distribution under section 1(c). + + 6) Attribution Rights. You must retain, in the Source Code of any + Derivative Works that You create, all copyright, patent, or + trademark notices from the Source Code of the Original Work, as + well as any notices of licensing and any descriptive text + identified therein as an "Attribution Notice." You must cause the + Source Code for any Derivative Works that You create to carry a + prominent Attribution Notice reasonably calculated to inform + recipients that You have modified the Original Work. + + 7) Warranty of Provenance and Disclaimer of Warranty. Licensor + warrants that the copyright in and to the Original Work and the + patent rights granted herein by Licensor are owned by the Licensor + or are sublicensed to You under the terms of this License with the + permission of the contributor(s) of those copyrights and patent + rights. Except as expressly stated in the immediately preceding + sentence, the Original Work is provided under this License on an + "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, + including, without limitation, the warranties of non-infringement, + merchantability or fitness for a particular purpose. THE ENTIRE + RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This + DISCLAIMER OF WARRANTY constitutes an essential part of this + License. No license to the Original Work is granted by this + License except under this disclaimer. + + 8) Limitation of Liability. Under no circumstances and under no legal + theory, whether in tort (including negligence), contract, or + otherwise, shall the Licensor be liable to anyone for any + indirect, special, incidental, or consequential damages of any + character arising as a result of this License or the use of the + Original Work including, without limitation, damages for loss of + goodwill, work stoppage, computer failure or malfunction, or any + and all other commercial damages or losses. This limitation of + liability shall not apply to the extent applicable law prohibits + such limitation. + + 9) Acceptance and Termination. If, at any time, You expressly + assented to this License, that assent indicates your clear and + irrevocable acceptance of this License and all of its terms and + conditions. If You distribute or communicate copies of the + Original Work or a Derivative Work, You must make a reasonable + effort under the circumstances to obtain the express assent of + recipients to the terms of this License. This License conditions + your rights to undertake the activities listed in Section 1, + including your right to create Derivative Works based upon the + Original Work, and doing so without honoring these terms and + conditions is prohibited by copyright law and international + treaty. Nothing in this License is intended to affect copyright + exceptions and limitations (including "fair use" or "fair + dealing"). This License shall terminate immediately and You may no + longer exercise any of the rights granted to You by this License + upon your failure to honor the conditions in Section 1(c). + +10) Termination for Patent Action. This License shall terminate + automatically and You may no longer exercise any of the rights + granted to You by this License as of the date You commence an + action, including a cross-claim or counterclaim, against Licensor + or any licensee alleging that the Original Work infringes a + patent. This termination provision shall not apply for an action + alleging patent infringement by combinations of the Original Work + with other software or hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating + to this License may be brought only in the courts of a + jurisdiction wherein the Licensor resides or in which Licensor + conducts its primary business, and under the laws of that + jurisdiction excluding its conflict-of-law provisions. The + application of the United Nations Convention on Contracts for the + International Sale of Goods is expressly excluded. Any use of the + Original Work outside the scope of this License or after its + termination shall be subject to the requirements and penalties of + copyright or patent law in the appropriate jurisdiction. This + section shall survive the termination of this License. + +12) Attorneys' Fees. In any action to enforce the terms of this + License or seeking damages relating thereto, the prevailing party + shall be entitled to recover its costs and expenses, including, + without limitation, reasonable attorneys' fees and costs incurred + in connection with such action, including any appeal of such + action. This section shall survive the termination of this + License. + +13) Miscellaneous. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. + +14) Definition of "You" in This License. "You" throughout this + License, whether in upper or lower case, means an individual or a + legal entity exercising rights under, and complying with all of + the terms of, this License. For legal entities, "You" includes any + entity that controls, is controlled by, or is under common control + with you. For purposes of this definition, "control" means (i) the + power, direct or indirect, to cause the direction or management of + such entity, whether by contract or otherwise, or (ii) ownership + of fifty percent (50%) or more of the outstanding shares, or (iii) + beneficial ownership of such entity. + +15) Right to Use. You may use the Original Work in all ways not + otherwise restricted or conditioned by this License or by law, and + Licensor promises not to interfere with or be responsible for such + uses by You. + +16) Modification of This License. This License is Copyright © 2005 + Lawrence Rosen. Permission is granted to copy, distribute, or + communicate this License without modification. Nothing in this + License permits You to modify this License as applied to the + Original Work or to Derivative Works. However, You may modify the + text of this License and copy, distribute or communicate your + modified version (the "Modified License") and apply it to other + original works of authorship subject to the following conditions: + (i) You may not indicate in any way that your Modified License is + the "Academic Free License" or "AFL" and you may not use those + names in the name of your Modified License; (ii) You must replace + the notice specified in the first paragraph above with the notice + "Licensed under " or with a notice + of your own that is not confusingly similar to the notice in this + License; and (iii) You may not claim that your original works are + open source software unless your Modified License has been + approved by Open Source Initiative (OSI) and You comply with its + license review and certification process. --- subversion-1.7.9.orig/debian/contrib/svn_load_dirs/svn_load_dirs.README +++ subversion-1.7.9/debian/contrib/svn_load_dirs/svn_load_dirs.README @@ -0,0 +1,270 @@ +Introduction +============ + +This Perl script is designed to load a number of directories into +Subversion. This is useful if you have a number of .zip's or +tar.{Z,gz,bz2}'s for a particular package and want to load them into +Subversion. + +Command Line Options +==================== + +Run the script with no command line arguments to see all the command +line options it takes. + +When Not To Use This Script +=========================== + +This script assumes that these packages were not previously in a +source control system, in particular CVS, because then you would use +another script to migrate the repository over, and in CVS' case, you +would use cvs2svn. This script will properly tag each release in the +tags directory if you use the -t command line option. + +Automatically Setting Properties On New Files & Directories +=========================================================== + +The script also accepts a separate configuration file for applying +properties to specific files and directories matching a regular +expression that are *added* to the repository. This script will not +modify properties of already existing files or directories in the +repository. This configuration file is specified to svn_load_dirs.pl +using the -p command line option. The format of the file is either +two or four columns: + +regular_expression control property_name property_value + + The `regular_expression' is a Perl style regular expression. It is + matched in a case-insensitive against filenames. + + The `control' must either be set to `break' or `cont'. It is used + to tell svn_load_dirs.pl if the following lines in the + configuration file should be examined for a match or if all + matching should stop. If `control' is set to `break', then no more + lines from the configuration file will be matched. If `control' is + set to `cont', which is short for continue, then more comparisons + will be made. Multiple properties can be set for one file or + directory this way. + + The last two, `property_name' and `property_value' are optional and + are applied to matching files and directories. + +If you have whitespace in any of the `regular_expression', +`property_name' or `property_value' columns, you must surround the +value with either a single or double quote. You can protect single or +double quotes with a \ character. The \ character is removed by this +script *only* for whitespace and quote characters, so you do not need +to protect any other characters, beyond what you would normally +protect for the regular expression. + +This sample configuration file was used to load on a Unix box a number +of Zip files containing Windows files with CRLF end of lines. + + \.doc$ break svn:mime-type application/msword + \.ds(p|w)$ break svn:eol-style CRLF + \.ilk$ break svn:eol-style CRLF + \.ncb$ break svn:eol-style CRLF + \.opt$ break svn:eol-style CRLF + \.exe$ break svn:mime-type application/octet-stream + dos2unix-eol\.sh$ break + .* break svn:eol-style native + +In this example, all the files should be converted to the native end +of line style, which the last line of the configuration handles. The +exception is dos2unix-eol.sh, which contains embedded CR's used to +find and replace Windows CRLF end of line characters with Unix's LF +characters. Since svn and svn_load_dirs.pl converts all CR, CRLF and +LF's to the native end of line style when `svn:eol-style' is set to +`native', this file should be left untouched. Hence, the `break' with +no property settings. + +The Windows Visual C++ and Visual Studio files (*.dsp, *.dsw, etc.) +should retain their CRLF line endings on any operating system and any +*.doc files are always treated as binary files, hence the +`svn:mime-type' setting of `application/msword'. + +Example Import +============== + +An example import follows: + +Steps: + +1) Unpack your .tar.{Z,gz,bz2}'s or .zips into a directory that is not + in a Subversion repository. + + Example: + + I'll use an example from my Orca distribution: + + % cd /tmp + % zcat orca-0.18.tar.gz | tar xf - + % zcat orca-0.27b2.tar.gz | tar xf - + +2) Decide on the directory structure you want to use to contain the + project you are loading. + + There are three main directory structures you can use. If you have + a single project, then use the structure Subversion uses for + itself, that is + + /branches + /tags + /trunk + + and load the project into /trunk and the tags into the tags + directory. + + If you have more than one project and you want to treat each + project separately, then use one of the following structures: + + /branches + /tags + /tags/project1 + /tags/project2 + /tags/project3 + /trunk + /trunk/project1 + /trunk/project2 + /trunk/project3 + + or + + /project1/branches + /project1/tags + /project1/trunk + /project2/branches + /project2/tags + /project2/trunk + + Example: + + To load Orca using the second directory structure into the + subversion repository rooted at http://svn.orcaware.com:8000/repos + + % cd /tmp + % svn co http://svn.orcaware.com:8000/repos + % cd repos + % mkdir tags tags/orca trunk trunk/orca + % svn add tags trunk + % svn commit -m 'Create initial directory tree structure for projects.' + + This script will create any subdirectories required to import your + directories into the repository, so these steps may not be required. + +3) Decide on the URL to use to access the subversion repository with + this script and the relative directory paths to the directories to + import your project into and to place the tags into. + + The usage of the script is + + ./svn_load_dirs.pl [-t tag_dir] svn_url import_dir dir_v1 [dir_v2 [..]] + + The import_dir and tag_dir command line options are directory paths + relative to svn_url and tell the script where to load your project + and optionally the tags. Both import_dir and tag_dir cannot + contain any ..'s and so svn_url must contain both import_dir and + tag_dir. + + This script supports importing your directories into subdirectories + of the root of the subversion repository. + + Example: + + In the previous step, if you wanted to load a project named orca + into the second directory structure, say + + /orca/branches + /orca/tags + /orca/trunk + + and you didn't care about tags, then you could use as svn_url the + URL + + http://svn.orcaware.com:8000/repos/orca + + and use . as import_dir. + + In this case, the script will only check out the orca subdirectory. + This is handy if the entire repository is very large and you don't + want this script to check the whole repository under /repos out to + load files into it. + + The only caveat is that svn_url must exist already in the + repository. So in this case, you would have to already have + created the orca subdirectory in the repository. + +4) Decide on the tags you want on your directories. If you don't want + any tags, then ignore this step. + + The script takes a -t command line argument that is a directory + path relative to the svn_url that you supply to this script from + step 3 above. Again, the URL from step 3 does not need to be the + URL of the root of the subversion repository, so you can work in + the subdirectory just fine. + + Look at the directories that will be loaded into the repository and + come up with a Perl regular expression that matches only the + portion of the directory name that identifies each directory. You + may need to rename your directories so that they contain a version + number you can use to tag them properly. + + The regular expression should be placed into the directory path + given to -t surrounded by @'s. Make sure to protect the regular + expression from the shell by using quotes. + + You can have multiple sets of regular expressions in the directory + path. + + There is no way to escape the @ characters. + + Example: + + For the Orca directories orca-0.18 and orca-0.27b2 I can use the + regular expression \d+\.\w+. I want the tags to be located in + the tags/orca/VERSION_NUMBER directory. So I would use: + + -t 'tags/orca/@\d+\.\w+@' + +5) Back up your Subversion repository in case you are not happy with + the results of running the script or the script fails for some + reason. + + Example: + + % /opt/i386-linux/apache-2.0/bin/apachectl stop + % cd /export/svn + % tar cvf repos_backup.tar repos + % /opt/i386-linux/apache-2.0/bin/apachectl start + +6) Run this script. The first argument is the root of the Subversion + package directory where you want to install the directories. The + directories are loaded in order that they appear on the command + line. + + Example: + + svn_load_dirs.pl http://svn.orcaware.com:8000/repos \ + trunk/orca -t 'tags/orca/@\d+\.\w+@' orca-0.18 orca-0.27b2 + + The output from this script are: + + A Added file or directory. + U File's contents have been updated. + d File or directory is deleted because an enclosing directory is + deleted. + D File or directory is deleted. + +7) Check the results by either checking out a new tree and or browsing + the repository with a browser. If they are not what you want, back + out the changes. + + Example: + + These commands back out the changes: + + % /opt/i386-linux/apache-2.0/bin/apachectl stop + % cd /export/svn + % rm -fr repos + % tar xvf repos_backup.tar + % /opt/i386-linux/apache-2.0/bin/apachectl start --- subversion-1.7.9.orig/debian/contrib/svn_load_dirs/svn_load_dirs.pl +++ subversion-1.7.9/debian/contrib/svn_load_dirs/svn_load_dirs.pl @@ -0,0 +1,2049 @@ +#!/usr/bin/perl -w + +# Copyright (c) 2002,2003,2004,2005,2006,2007,2009 Dolby. All rights reserved. +# +# Licensed under the Academic Free License version 3.0. See LICENSE_AFL3.txt +# or http://www.opensource.org/licenses/academic.php for a copy of the license +# text. + +# $HeadURL: http://svn.apache.org/repos/asf/subversion/branches/1.6.x/contrib/client-side/svn_load_dirs/svn_load_dirs.pl.in $ +# $LastChangedDate: 2009-10-12 12:57:16 +0000 (Mon, 12 Oct 2009) $ +# $LastChangedBy: hwright $ +# $LastChangedRevision: 880030 $ + +$| = 1; + +use strict; +use Carp; +use Cwd; +use Digest::MD5 2.20; +use File::Copy 2.03; +use File::Find; +use File::Path 1.0404; +use File::Temp 0.12 qw(tempdir tempfile); +use Getopt::Long 2.25; +use Text::Wrap; +use URI 1.17; +use English; + +$Text::Wrap::columns = 72; + +# Specify the location of the svn command. +my $svn = '/usr/bin/svn'; + +# Process the command line options. + +# The base URL for the portion of the repository to work in. Note +# that this does not have to be the root of the subversion repository, +# it can point to a subdirectory in the repository. +my $repos_base_url; + +# The relative path from the repository base URL to work in to the +# directory to load the input directories into. +my $repos_load_rel_path; + +# To specify where tags, which are simply copies of the imported +# directory, should be placed relative to the repository base URL, use +# the -t command line option. This value must contain regular +# expressions that match portions of the input directory names to +# create an unique tag for each input directory. The regular +# expressions are surrounded by a specified character to distinguish +# the regular expression from the normal directory path. +my $opt_import_tag_location; + +# Do not ask for any user input. Just go ahead and do everything. +my $opt_no_user_input; + +# Do not automatically set the svn:executable property based on the +# file's exe bit. +my $opt_no_auto_exe; + +# Username to use for commits. +my $opt_svn_username; + +# Password to use for commits. +my $opt_svn_password; + +# Verbosity level. +my $opt_verbose; + +# Path to already checked-out working copy. +my $opt_existing_wc_dir; + +# List of filename patterns to ignore (as in .subversion/config's +# "global-ignores" option). +my $opt_glob_ignores; + +# This is the character used to separate regular expressions occuring +# in the tag directory path from the path itself. +my $REGEX_SEP_CHAR = '@'; + +# This specifies a configuration file that contains a list of regular +# expressions to check against a file and the properties to set on +# matching files. +my $property_config_filename; + +GetOptions('no_user_input' => \$opt_no_user_input, + 'no_auto_exe' => \$opt_no_auto_exe, + 'property_cfg_filename=s' => \$property_config_filename, + 'svn_password=s' => \$opt_svn_password, + 'svn_username=s' => \$opt_svn_username, + 'tag_location=s' => \$opt_import_tag_location, + 'verbose+' => \$opt_verbose, + 'wc=s' => \$opt_existing_wc_dir, + 'glob_ignores=s' => \$opt_glob_ignores) + or &usage; +&usage("$0: too few arguments") if @ARGV < 2; + +$repos_base_url = shift; +$repos_load_rel_path = shift; + +# Check that the repository base URL and the import directories do not +# contain any ..'s. +if ($repos_base_url =~ /\.{2}/) + { + die "$0: repos base URL $repos_base_url cannot contain ..'s.\n"; + } +if ($repos_load_rel_path =~ /\.{2}/) + { + die "$0: repos import relative directory path $repos_load_rel_path ", + "cannot contain ..'s.\n"; + } + +# If there are no directories listed on the command line, then the +# directories are read from standard input. In this case, the +# -no_user_input command line option must be specified. +if (!@ARGV and !$opt_no_user_input) + { + &usage("$0: must use -no_user_input if no dirs listed on command line."); + } + +# The tag option cannot be used when directories are read from +# standard input because tags may collide and no user input can be +# taken to verify that the input is ok. +if (!@ARGV and $opt_import_tag_location) + { + &usage("$0: cannot use -tag_location when dirs are read from stdin."); + } + +# If the tag directory is set, then the import directory cannot be '.'. +if (defined $opt_import_tag_location and $repos_load_rel_path eq '.') + { + &usage("$0: cannot set import_dir to '.' and use -t command line option."); + } + +# Set the svn command line options that are used anytime svn connects +# to the repository. +my @svn_use_repos_cmd_opts; +&set_svn_use_repos_cmd_opts($opt_svn_username, $opt_svn_password); + +# Check that the tag directories do not contain any ..'s. Also, the +# import and tag directories cannot be absolute. +if (defined $opt_import_tag_location and $opt_import_tag_location =~ /\.{2}/) + { + die "$0: repos tag relative directory path $opt_import_tag_location ", + "cannot contain ..'s.\n"; + } +if ($repos_load_rel_path =~ m|^/|) + { + die "$0: repos import relative directory path $repos_load_rel_path ", + "cannot start with /.\n"; + } +if (defined $opt_import_tag_location and $opt_import_tag_location =~ m|^/|) + { + die "$0: repos tagrelative directory path $opt_import_tag_location ", + "cannot start with /.\n"; + } + +if (defined $opt_existing_wc_dir) + { + unless (-e $opt_existing_wc_dir) + { + die "$0: working copy '$opt_existing_wc_dir' does not exist.\n"; + } + + unless (-d _) + { + die "$0: working copy '$opt_existing_wc_dir' is not a directory.\n"; + } + + unless (-d "$opt_existing_wc_dir/.svn") + { + die "$0: working copy '$opt_existing_wc_dir' does not have .svn ", + "directory.\n"; + } + + $opt_existing_wc_dir = Cwd::abs_path($opt_existing_wc_dir) + } + +# If no glob_ignores specified, try to deduce from config file, +# or use the default below. +my $ignores_str = + '*.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store'; + +if ( defined $opt_glob_ignores) + { + $ignores_str = $opt_glob_ignores; + } +elsif ( -f "$ENV{HOME}/.subversion/config" ) + { + open my $conf, "$ENV{HOME}/.subversion/config"; + while (<$conf>) + { + if ( /^global-ignores\s*=\s*(.*?)\s*$/ ) + { + $ignores_str = $1; + last; + } + } + } + +my @glob_ignores = map + { + s/\./\\\./g; s/\*/\.\*/g; "^$_\$"; + } split(/\s+/, $ignores_str); +unshift @glob_ignores, '\.svn$'; + +# Convert the string URL into a URI object. +$repos_base_url =~ s|/*$||; +my $repos_base_uri = URI->new($repos_base_url); + +# Check that $repos_load_rel_path is not a directory here implying +# that a command line option was forgotten. +if ($repos_load_rel_path ne '.' and -d $repos_load_rel_path) + { + die "$0: import_dir '$repos_load_rel_path' is a directory.\n"; + } + +# The remaining command line arguments should be directories. Check +# that they all exist and that there are no duplicates. +if (@ARGV) + { + my %dirs; + foreach my $dir (@ARGV) + { + unless (-e $dir) + { + die "$0: directory '$dir' does not exist.\n"; + } + + unless (-d _) + { + die "$0: directory '$dir' is not a directory.\n"; + } + + if ($dirs{$dir}) + { + die "$0: directory '$dir' is listed more than once on command ", + "line.\n"; + } + $dirs{$dir} = 1; + } + } + +# Create the tag locations and print them for the user to review. +# Check that there are no duplicate tags. +my %load_tags; +if (@ARGV and defined $opt_import_tag_location) + { + my %seen_tags; + + foreach my $load_dir (@ARGV) + { + my $load_tag = &get_tag_dir($load_dir); + + print "Directory $load_dir will be tagged as $load_tag\n"; + + if ($seen_tags{$load_tag}) + { + die "$0: duplicate tag generated.\n"; + } + $seen_tags{$load_tag} = 1; + + $load_tags{$load_dir} = $load_tag; + } + + exit 0 unless &get_answer("Please examine identified tags. Are they " . + "acceptable? (Y/n) ", 'ny', 1); + print "\n"; + } + +# Load the property configuration filename, if one was specified, into +# an array of hashes, where each hash contains a regular expression +# and a property to apply to the file if the regular expression +# matches. +my @property_settings; +if (defined $property_config_filename and length $property_config_filename) + { + open(CFG, $property_config_filename) + or die "$0: cannot open '$property_config_filename' for reading: $!\n"; + + my $ok = 1; + + while (my $line = ) + { + next if $line =~ /^\s*$/; + next if $line =~ /^\s*#/; + + # Split the input line into words taking into account that + # single or double quotes may define a single word with + # whitespace in it. The format for the file is + # regex control property_name property_value + my @line = &split_line($line); + next if @line == 0; + + unless (@line == 2 or @line == 4) + { + warn "$0: line $. of '$property_config_filename' has to have 2 ", + "or 4 columns.\n"; + $ok = 0; + next; + } + my ($regex, $control, $property_name, $property_value) = @line; + + unless ($control eq 'break' or $control eq 'cont') + { + warn "$0: line $. of '$property_config_filename' has illegal ", + "value for column 3 '$control', must be 'break' or 'cont'.\n"; + $ok = 0; + next; + } + + # Compile the regular expression. + my $re; + eval { $re = qr/$regex/i }; + if ($@) + { + warn "$0: line $. of '$property_config_filename' regex '$regex' ", + "does not compile:\n$@\n"; + $ok = 0; + next; + } + + push(@property_settings, {name => $property_name, + value => $property_value, + control => $control, + re => $re}); + } + close(CFG) + or warn "$0: error in closing '$property_config_filename' for ", + "reading: $!\n"; + + exit 1 unless $ok; + } + +# Check that the svn base URL works by running svn log on it. Only +# get the HEAD revision log message; there's no need to waste +# bandwidth seeing all of the log messages. +print "Checking that the base URL is a Subversion repository.\n"; +read_from_process($svn, 'log', '-r', 'HEAD', + @svn_use_repos_cmd_opts, $repos_base_uri); +print "\n"; + +my $orig_cwd = cwd; + +# The first step is to determine the root of the svn repository. Do +# this with the svn log command. Take the svn_url hostname and port +# as the initial url and append to it successive portions of the final +# path until svn log succeeds. +print "Finding the root URL of the Subversion repository.\n"; +my $repos_root_uri; +my $repos_root_uri_path; +my $repos_base_path_segment; +{ + my $r = $repos_base_uri->clone; + my @path_segments = grep { length($_) } $r->path_segments; + my @repos_base_path_segments = @path_segments; + unshift(@path_segments, ''); + $r->path(''); + my @r_path_segments; + + while (@path_segments) + { + $repos_root_uri_path = shift @path_segments; + push(@r_path_segments, $repos_root_uri_path); + $r->path_segments(@r_path_segments); + if (safe_read_from_pipe($svn, 'log', '-r', 'HEAD', + @svn_use_repos_cmd_opts, $r) == 0) + { + $repos_root_uri = $r; + last; + } + shift @repos_base_path_segments; + } + $repos_base_path_segment = join('/', @repos_base_path_segments); +} + +if ($repos_root_uri) + { + print "Determined that the svn root URL is $repos_root_uri.\n\n"; + } +else + { + die "$0: cannot determine root svn URL.\n"; + } + +# Create a temporary directory for svn to work in. +my $temp_dir = tempdir( "svn_load_dirs_XXXXXXXXXX", TMPDIR => 1 ); + +# Put in a signal handler to clean up any temporary directories. +sub catch_signal { + my $signal = shift; + warn "$0: caught signal $signal. Quitting now.\n"; + exit 1; +} + +$SIG{HUP} = \&catch_signal; +$SIG{INT} = \&catch_signal; +$SIG{TERM} = \&catch_signal; +$SIG{PIPE} = \&catch_signal; + +# Create an object that when DESTROY'ed will delete the temporary +# directory. The CLEANUP flag to tempdir should do this, but they +# call rmtree with 1 as the last argument which takes extra security +# measures that do not clean up the .svn directories. +my $temp_dir_cleanup = Temp::Delete->new; + +# Determine the native end of line style for this system. Do this the +# most portable way, by writing a file with a single \n in non-binary +# mode and then reading the file in binary mode. +my $native_eol = &determine_native_eol; + +# Check if all the directories exist to load the directories into the +# repository. If not, ask if they should be created. For tags, do +# not create the tag directory itself, that is done on the svn cp. +{ + print "Finding if any directories need to be created in repository.\n"; + + my @dirs_to_create; + my @urls_to_create; + my %seen_dir; + my @load_tags_without_last_segment; + + # Assume that the last portion of the tag directory contains the + # version number and remove it from the directories to create, + # because the tag directory will be created by svn cp. + foreach my $load_tag (sort values %load_tags) + { + # Skip this tag if there is only one segment in its name. + my $index = rindex($load_tag, '/'); + next if $index == -1; + + # Trim off the last segment and record the result. + push(@load_tags_without_last_segment, substr($load_tag, 0, $index)); + } + + foreach my $dir ($repos_load_rel_path, @load_tags_without_last_segment) + { + next unless length $dir; + my $d = ''; + foreach my $segment (split('/', $dir)) + { + $d = length $d ? "$d/$segment" : $segment; + my $url = "$repos_base_url/$d"; + unless ($seen_dir{$d}) + { + $seen_dir{$d} = 1; + if (safe_read_from_pipe($svn, 'log', '-r', 'HEAD', + @svn_use_repos_cmd_opts, $url) != 0) + { + push(@dirs_to_create, $d); + push(@urls_to_create, $url); + } + } + } + } + + if (@dirs_to_create) + { + print "The following directories do not exist and need to exist:\n"; + foreach my $dir (@dirs_to_create) + { + print " $dir\n"; + } + exit 0 unless &get_answer("You must add them now to load the " . + "directories. Continue (Y/n)? ", 'ny', 1); + + my $message = "Create directories to load project into.\n\n"; + + foreach my $dir (@dirs_to_create) + { + if (length $repos_base_path_segment) + { + $message .= "* $repos_base_path_segment/$dir: New directory.\n"; + } + else + { + $message .= "* $dir: New directory.\n"; + } + } + $message = wrap('', ' ', $message); + + read_from_process($svn, 'mkdir', @svn_use_repos_cmd_opts, + '-m', $message, @urls_to_create); + } + else + { + print "No directories need to be created to prepare repository.\n"; + } +} + +# Either checkout a new working copy from the repository or use an +# existing working copy. +if (defined $opt_existing_wc_dir) + { + # Update an already existing working copy. + print "Not checking out anything; using existing working directory at\n"; + print "$opt_existing_wc_dir\n"; + + chdir($opt_existing_wc_dir) + or die "$0: cannot chdir '$opt_existing_wc_dir': $!\n"; + + read_from_process($svn, 'update', @svn_use_repos_cmd_opts); + } +else + { + # Check out the svn repository starting at the svn URL into a + # fixed directory name. + my $checkout_dir_name = 'my_import_wc'; + + # Check out only the directory being imported to, otherwise the + # checkout of the entire base URL can be very huge, if it contains + # a large number of tags. + my $checkout_url; + if ($repos_load_rel_path eq '.') + { + $checkout_url = $repos_base_url; + } + else + { + $checkout_url = "$repos_base_url/$repos_load_rel_path"; + } + + print "Checking out $checkout_url into $temp_dir/$checkout_dir_name\n"; + + chdir($temp_dir) + or die "$0: cannot chdir '$temp_dir': $!\n"; + + read_from_process($svn, 'checkout', + @svn_use_repos_cmd_opts, + $checkout_url, $checkout_dir_name); + + chdir($checkout_dir_name) + or die "$0: cannot chdir '$checkout_dir_name': $!\n"; + } + +# At this point, the current working directory is the top level +# directory of the working copy. Record the absolute path to this +# location because the script will chdir back here later on. +my $wc_import_dir_cwd = cwd; + +# Set up the names for the path to the import and tag directories. +my $repos_load_abs_path; +if ($repos_load_rel_path eq '.') + { + $repos_load_abs_path = length($repos_base_path_segment) ? + $repos_base_path_segment : "/"; + } +else + { + $repos_load_abs_path = length($repos_base_path_segment) ? + "$repos_base_path_segment/$repos_load_rel_path" : + $repos_load_rel_path; + } + +# Now go through each source directory and copy each file from the +# source directory to the target directory. For new target files, add +# them to svn. For files that no longer exist, delete them. +my $print_rename_message = 1; +my @load_dirs = @ARGV; +while (defined (my $load_dir = &get_next_load_dir)) + { + my $load_tag = $load_tags{$load_dir}; + + if (defined $load_tag) + { + print "\nLoading $load_dir and will save in tag $load_tag.\n"; + } + else + { + print "\nLoading $load_dir.\n"; + } + + # The first hash is keyed by the old name in a rename and the + # second by the new name. The last variable contains a list of + # old and new filenames in a rename. + my %rename_from_files; + my %rename_to_files; + my @renamed_filenames; + + unless ($opt_no_user_input) + { + my $repeat_loop; + do + { + $repeat_loop = 0; + + my %add_files; + my %del_files; + + # Get the list of files and directories in the repository + # working copy. This hash is called %del_files because + # each file or directory will be deleted from the hash + # using the list of files and directories in the source + # directory, leaving the files and directories that need + # to be deleted. + %del_files = &recursive_ls_and_hash($wc_import_dir_cwd); + + # This anonymous subroutine finds all the files and + # directories in the directory to load. It notes the file + # type and for each file found, it deletes it from + # %del_files. + my $wanted = sub + { + s#^\./##; + return if $_ eq '.'; + + my $source_path = $_; + my $dest_path = "$wc_import_dir_cwd/$_"; + + my ($source_type) = &file_info($source_path); + my ($dest_type) = &file_info($dest_path); + + # Fail if the destination type exists but is of a + # different type of file than the source type. + if ($dest_type ne '0' and $source_type ne $dest_type) + { + die "$0: does not handle changing source and destination ", + "type for '$source_path'.\n"; + } + + if ($source_type ne 'd' and + $source_type ne 'f' and + $source_type ne 'l') + { + warn "$0: skipping loading file '$source_path' of type ", + "'$source_type'.\n"; + unless ($opt_no_user_input) + { + print STDERR "Press return to continue: "; + ; + } + return; + } + + unless (defined delete $del_files{$source_path}) + { + $add_files{$source_path}{type} = $source_type; + } + }; + + # Now change into the directory containing the files to + # load. First change to the original directory where this + # script was run so that if the specified directory is a + # relative directory path, then the script can change into + # it. + chdir($orig_cwd) + or die "$0: cannot chdir '$orig_cwd': $!\n"; + chdir($load_dir) + or die "$0: cannot chdir '$load_dir': $!\n"; + + find({no_chdir => 1, + preprocess => sub { sort { $b cmp $a } + grep { $_ !~ /^[._]svn$/ } @_ }, + wanted => $wanted + }, '.'); + + # At this point %add_files contains the list of new files + # and directories to be created in the working copy tree + # and %del_files contains the files and directories that + # need to be deleted. Because there may be renames that + # have taken place, give the user the opportunity to + # rename any deleted files and directories to ones being + # added. + my @add_files = sort keys %add_files; + my @del_files = sort keys %del_files; + + # Because the source code management system may keep the + # original renamed file or directory in the working copy + # until a commit, remove them from the list of deleted + # files or directories. + &filter_renamed_files(\@del_files, \%rename_from_files); + + # Now change into the working copy directory in case any + # renames need to be performed. + chdir($wc_import_dir_cwd) + or die "$0: cannot chdir '$wc_import_dir_cwd': $!\n"; + + # Only do renames if there are both added and deleted + # files and directories. + if (@add_files and @del_files) + { + my $max = @add_files > @del_files ? @add_files : @del_files; + + # Print the files that have been added and deleted. + # Find the deleted file with the longest name and use + # that for the width of the filename column. Add one + # to the filename width to let the directory / + # character be appended to a directory name. + my $line_number_width = 4; + my $filename_width = 0; + foreach my $f (@del_files) + { + my $l = length($f); + $filename_width = $l if $l > $filename_width; + } + ++$filename_width; + my $printf_format = "%${line_number_width}d"; + + if ($print_rename_message) + { + $print_rename_message = 0; + print "\n", + "The following table lists files and directories that\n", + "exist in either the Subversion repository or the\n", + "directory to be imported but not both. You now have\n", + "the opportunity to match them up as renames instead\n", + "of deletes and adds. This is a Good Thing as it'll\n", + "make the repository take less space.\n\n", + "The left column lists files and directories that\n", + "exist in the Subversion repository and do not exist\n", + "in the directory being imported. The right column\n", + "lists files and directories that exist in the\n", + "directory being imported. Match up a deleted item\n", + "from the left column with an added item from the\n", + "right column. Note the line numbers on the left\n", + "which you type into this script to have a rename\n", + "performed.\n"; + } + + # Sort the added and deleted files and directories by + # the lowercase versions of their basenames instead of + # their complete path, which makes finding files that + # were moved into different directories easier to + # match up. + @add_files = map { $_->[0] } + sort { $a->[1] cmp $b->[1] } + map { [$_->[0], lc($_->[1])] } + map { [$_, m#([^/]+)$#] } + @add_files; + @del_files = map { $_->[0] } + sort { $a->[1] cmp $b->[1] } + map { [$_->[0], lc($_->[1])] } + map { [$_, m#([^/]+)$#] } + @del_files; + + RELIST: + + for (my $i=0; $i<$max; ++$i) + { + my $add_filename = ''; + my $del_filename = ''; + if ($i < @add_files) + { + $add_filename = $add_files[$i]; + if ($add_files{$add_filename}{type} eq 'd') + { + $add_filename .= '/'; + } + } + if ($i < @del_files) + { + $del_filename = $del_files[$i]; + if ($del_files{$del_filename}{type} eq 'd') + { + $del_filename .= '/'; + } + } + + if ($i % 22 == 0) + { + print + "\n", + " " x $line_number_width, + " ", + "Deleted", " " x ($filename_width-length("Deleted")), + " ", + "Added\n"; + } + + printf $printf_format, $i; + print " ", $del_filename, + "_" x ($filename_width - length($del_filename)), + " ", $add_filename, "\n"; + + if (($i+1) % 22 == 0) + { + unless (&get_answer("Continue printing (Y/n)? ", + 'ny', 1)) + { + last; + } + } + } + + # Get the feedback from the user. + my $line; + my $add_filename; + my $add_index; + my $del_filename; + my $del_index; + my $got_line = 0; + do { + print "Enter two indexes for each column to rename, ", + "(R)elist, or (F)inish: "; + $line = ; + $line = '' unless defined $line; + if ($line =~ /^R$/i ) + { + goto RELIST; + } + + if ($line =~ /^F$/i) + { + $got_line = 1; + } + elsif ($line =~ /^(\d+)\s+(\d+)$/) + { + print "\n"; + + $del_index = $1; + $add_index = $2; + if ($del_index >= @del_files) + { + print "Delete index $del_index is larger than ", + "maximum index of ", scalar @del_files - 1, + ".\n"; + $del_index = undef; + } + if ($add_index > @add_files) + { + print "Add index $add_index is larger than maximum ", + "index of ", scalar @add_files - 1, ".\n"; + $add_index = undef; + } + $got_line = defined $del_index && defined $add_index; + + # Check that the file or directory to be renamed + # has the same file type. + if ($got_line) + { + $add_filename = $add_files[$add_index]; + $del_filename = $del_files[$del_index]; + if ($add_files{$add_filename}{type} ne + $del_files{$del_filename}{type}) + { + print "File types for $del_filename and ", + "$add_filename differ.\n"; + $got_line = undef; + } + } + } + } until ($got_line); + + if ($line !~ /^F$/i) + { + print "Renaming $del_filename to $add_filename.\n"; + + $repeat_loop = 1; + + # Because subversion cannot rename the same file + # or directory twice, which includes doing a + # rename of a file in a directory that was + # previously renamed, a commit has to be + # performed. Check if the file or directory being + # renamed now would cause such a problem and + # commit if so. + my $do_commit_now = 0; + foreach my $rename_to_filename (keys %rename_to_files) + { + if (contained_in($del_filename, + $rename_to_filename, + $rename_to_files{$rename_to_filename}{type})) + { + $do_commit_now = 1; + last; + } + } + + if ($do_commit_now) + { + print "Now committing previously run renames.\n"; + &commit_renames($load_dir, + \@renamed_filenames, + \%rename_from_files, + \%rename_to_files); + } + + push(@renamed_filenames, $del_filename, $add_filename); + { + my $d = $del_files{$del_filename}; + $rename_from_files{$del_filename} = $d; + $rename_to_files{$add_filename} = $d; + } + + # Check that any required directories to do the + # rename exist. + my @add_segments = split('/', $add_filename); + pop(@add_segments); + my $add_dir = ''; + my @add_dirs; + foreach my $segment (@add_segments) + { + $add_dir = length($add_dir) ? "$add_dir/$segment" : + $segment; + unless (-d $add_dir) + { + push(@add_dirs, $add_dir); + } + } + + if (@add_dirs) + { + read_from_process($svn, 'mkdir', @add_dirs); + } + + read_from_process($svn, 'mv', + $del_filename, $add_filename); + } + } + } while ($repeat_loop); + } + + # If there are any renames that have not been committed, then do + # that now. + if (@renamed_filenames) + { + &commit_renames($load_dir, + \@renamed_filenames, + \%rename_from_files, + \%rename_to_files); + } + + # At this point all renames have been performed. Now get the + # final list of files and directories in the working copy + # directory. The %add_files hash will contain the list of files + # and directories to add to the working copy and %del_files starts + # with all the files already in the working copy and gets files + # removed that are in the imported directory, which results in a + # list of files that should be deleted. %upd_files holds the list + # of files that have been updated. + my %add_files; + my %del_files = &recursive_ls_and_hash($wc_import_dir_cwd); + my %upd_files; + + # This anonymous subroutine copies files from the source directory + # to the working copy directory. + my $wanted = sub + { + s#^\./##; + return if $_ eq '.'; + + my $source_path = $_; + my $dest_path = "$wc_import_dir_cwd/$_"; + + my ($source_type, $source_is_exe) = &file_info($source_path); + my ($dest_type) = &file_info($dest_path); + + return if ($source_type ne 'd' and + $source_type ne 'f' and + $source_type ne 'l'); + + # Fail if the destination type exists but is of a different + # type of file than the source type. + if ($dest_type ne '0' and $source_type ne $dest_type) + { + die "$0: does not handle changing source and destination type ", + "for '$source_path'.\n"; + } + + # Determine if the file is being added or is an update to an + # already existing file using the file's digest. + my $del_info = delete $del_files{$source_path}; + if (defined $del_info) + { + if (defined (my $del_digest = $del_info->{digest})) + { + my $new_digest = &digest_hash_file($source_path); + if ($new_digest ne $del_digest) + { + print "U $source_path\n"; + $upd_files{$source_path} = $del_info; + } + } + } + else + { + print "A $source_path\n"; + $add_files{$source_path}{type} = $source_type; + + # Create an array reference to hold the list of properties + # to apply to this object. + unless (defined $add_files{$source_path}{properties}) + { + $add_files{$source_path}{properties} = []; + } + + # Go through the list of properties for a match on this + # file or directory and if there is a match, then apply + # the property to it. + foreach my $property (@property_settings) + { + my $re = $property->{re}; + if ($source_path =~ $re) + { + my $property_name = $property->{name}; + my $property_value = $property->{value}; + + # The property value may not be set in the + # configuration file, since the user may just want + # to set the control flag. + if (defined $property_name and defined $property_value) + { + # Ignore properties that do not apply to + # directories. + if ($source_type eq 'd') + { + if ($property_name eq 'svn:eol-style' or + $property_name eq 'svn:executable' or + $property_name eq 'svn:keywords' or + $property_name eq 'svn:mime-type') + { + next; + } + } + + # Ignore properties that do not apply to + # files. + if ($source_type eq 'f') + { + if ($property_name eq 'svn:externals' or + $property_name eq 'svn:ignore') + { + next; + } + } + + print "Adding to '$source_path' property ", + "'$property_name' with value ", + "'$property_value'.\n"; + + push(@{$add_files{$source_path}{properties}}, + $property); + } + + last if $property->{control} eq 'break'; + } + } + } + + # Add svn:executable to files that have their executable bit + # set. + if ($source_is_exe and !$opt_no_auto_exe) + { + print "Adding to '$source_path' property 'svn:executable' with ", + "value '*'.\n"; + my $property = {name => 'svn:executable', value => '*'}; + push (@{$add_files{$source_path}{properties}}, + $property); + } + + # Now make sure the file or directory in the source directory + # exists in the repository. + if ($source_type eq 'd') + { + if ($dest_type eq '0') + { + mkdir($dest_path) + or die "$0: cannot mkdir '$dest_path': $!\n"; + } + } + elsif + ($source_type eq 'l') { + my $link_target = readlink($source_path) + or die "$0: cannot readlink '$source_path': $!\n"; + if ($dest_type eq 'l') + { + my $old_target = readlink($dest_path) + or die "$0: cannot readlink '$dest_path': $!\n"; + return if ($old_target eq $link_target); + unlink($dest_path) + or die "$0: unlink '$dest_path' failed: $!\n"; + } + symlink($link_target, $dest_path) + or die "$0: cannot symlink '$dest_path' to '$link_target': $!\n"; + } + elsif + ($source_type eq 'f') { + # Only copy the file if the digests do not match. + if ($add_files{$source_path} or $upd_files{$source_path}) + { + copy($source_path, $dest_path) + or die "$0: copy '$source_path' to '$dest_path': $!\n"; + } + } + else + { + die "$0: does not handle copying files of type '$source_type'.\n"; + } + }; + + # Now change into the directory containing the files to load. + # First change to the original directory where this script was run + # so that if the specified directory is a relative directory path, + # then the script can change into it. + chdir($orig_cwd) + or die "$0: cannot chdir '$orig_cwd': $!\n"; + chdir($load_dir) + or die "$0: cannot chdir '$load_dir': $!\n"; + + find({no_chdir => 1, + preprocess => sub { sort { $b cmp $a } + grep { $_ !~ /^[._]svn$/ } @_ }, + wanted => $wanted + }, '.'); + + # The files and directories that are in %del_files are the files + # and directories that need to be deleted. Because svn will + # return an error if a file or directory is deleted in a directory + # that subsequently is deleted, first find all directories and + # remove from the list any files and directories inside those + # directories from this list. Work through the list repeatedly + # working from short to long names so that directories containing + # other files and directories will be deleted first. + my $repeat_loop; + do + { + $repeat_loop = 0; + my @del_files = sort {length($a) <=> length($b) || $a cmp $b} + keys %del_files; + &filter_renamed_files(\@del_files, \%rename_from_files); + foreach my $file (@del_files) + { + if ($del_files{$file}{type} eq 'd') + { + my $dir = "$file/"; + my $dir_length = length($dir); + foreach my $f (@del_files) + { + next if $file eq $f; + if (length($f) >= $dir_length and + substr($f, 0, $dir_length) eq $dir) + { + print "d $f\n"; + delete $del_files{$f}; + $repeat_loop = 1; + } + } + + # If there were any deletions of files and/or + # directories inside a directory that will be deleted, + # then restart the entire loop again, because one or + # more keys have been deleted from %del_files. + # Equally important is not to stop this loop if no + # deletions have been done, otherwise later + # directories that may contain files and directories + # to be deleted will not be deleted. + last if $repeat_loop; + } + } + } while ($repeat_loop); + + # What is left are files that are not in any directories to be + # deleted and directories to be deleted. To delete the files, + # deeper files and directories must be deleted first. Because we + # have a hash keyed by remaining files and directories to be + # deleted, instead of trying to figure out which directories and + # files are contained in other directories, just reverse sort by + # the path length and then alphabetically. + my @del_files = sort {length($b) <=> length($a) || $a cmp $b } + keys %del_files; + &filter_renamed_files(\@del_files, \%rename_from_files); + foreach my $file (@del_files) + { + print "D $file\n"; + } + + # Now change back to the trunk directory and run the svn commands. + chdir($wc_import_dir_cwd) + or die "$0: cannot chdir '$wc_import_dir_cwd': $!\n"; + + # If any of the added files have the svn:eol-style property set, + # then pass -b to diff, otherwise diff may fail because the end of + # lines have changed and the source file and file in the + # repository will not be identical. + my @diff_ignore_space_changes; + + if (keys %add_files) + { + my @add_files = sort {length($a) <=> length($b) || $a cmp $b} + keys %add_files; + my $target_filename = &make_targets_file(@add_files); + read_from_process($svn, 'add', '-N', '--targets', $target_filename); + unlink($target_filename); + + # Add properties on the added files. + foreach my $add_file (@add_files) + { + foreach my $property (@{$add_files{$add_file}{properties}}) + { + my $property_name = $property->{name}; + my $property_value = $property->{value}; + + if ($property_name eq 'svn:eol-style') + { + @diff_ignore_space_changes = ('-b'); + } + + # Write the value to a temporary file in case it's multi-line + my ($handle, $tmpfile) = tempfile(DIR => $temp_dir); + print $handle $property_value; + close($handle); + + read_from_process($svn, + 'propset', + $property_name, + '--file', + $tmpfile, + $add_file); + } + } + } + if (@del_files) + { + my $target_filename = &make_targets_file(@del_files); + read_from_process($svn, 'rm', '--targets', $target_filename); + unlink($target_filename); + } + + # Go through the list of updated files and check the svn:eol-style + # property. If it is set to native, then convert all CR, CRLF and + # LF's in the file to the native end of line characters. Also, + # modify diff's command line so that it will ignore the change in + # end of line style. + if (keys %upd_files) + { + my @upd_files = sort {length($a) <=> length($b) || $a cmp $b} + keys %upd_files; + foreach my $upd_file (@upd_files) + { + # Always append @BASE to a filename in case they contain a + # @ character, in which case the Subversion command line + # client will attempt to parse the characters after the @ + # as a revision and most likely fail, or if the characters + # after the @ are a valid revision, then it'll possibly + # get the incorrect information. So always append @BASE + # and any preceding @'s will be treated normally and the + # correct information will be retrieved. + my @command = ($svn, + 'propget', + 'svn:eol-style', + "$upd_file\@BASE"); + my @lines = read_from_process(@command); + next unless @lines; + if (@lines > 1) + { + warn "$0: '@command' returned more than one line of output: ", + "'@lines'.\n"; + next; + } + + my $eol_style = $lines[0]; + if ($eol_style eq 'native') + { + @diff_ignore_space_changes = ('-b'); + if (&convert_file_to_native_eol($upd_file)) + { + print "Native eol-style conversion modified $upd_file.\n"; + } + } + } + } + + my $message = wrap('', '', "Load $load_dir into $repos_load_abs_path.\n"); + read_from_process($svn, 'commit', + @svn_use_repos_cmd_opts, + '-m', $message); + + # If an update is not run now after a commit, then some file and + # directory paths will have an older revisions associated with + # them and any future commits will fail because they are out of + # date. + read_from_process($svn, 'update', @svn_use_repos_cmd_opts); + + # Now remove any files and directories to be deleted in the + # repository. + if (@del_files) + { + rmtree(\@del_files, 1, 0); + } + + # Now make the tag by doing a copy in the svn repository itself. + if (defined $load_tag) + { + my $repos_tag_abs_path = length($repos_base_path_segment) ? + "$repos_base_path_segment/$load_tag" : + $load_tag; + + my $from_url = $repos_load_rel_path eq '.' ? + $repos_load_rel_path : + "$repos_base_url/$repos_load_rel_path"; + my $to_url = "$repos_base_url/$load_tag"; + + $message = wrap("", + "", + "Tag $repos_load_abs_path as " . + "$repos_tag_abs_path.\n"); + read_from_process($svn, 'cp', @svn_use_repos_cmd_opts, + '-m', $message, $from_url, $to_url); + + # Now check out the tag and run a recursive diff between the + # original source directory and the tag for a consistency + # check. + my $checkout_dir_name = "my_tag_wc_named_$load_tag"; + print "Checking out $to_url into $temp_dir/$checkout_dir_name\n"; + + chdir($temp_dir) + or die "$0: cannot chdir '$temp_dir': $!\n"; + + read_from_process($svn, 'checkout', + @svn_use_repos_cmd_opts, + $to_url, $checkout_dir_name); + + chdir($checkout_dir_name) + or die "$0: cannot chdir '$checkout_dir_name': $!\n"; + + chdir($orig_cwd) + or die "$0: cannot chdir '$orig_cwd': $!\n"; + read_from_process('diff', '-u', @diff_ignore_space_changes, + '-x', '.svn', + '-r', $load_dir, "$temp_dir/$checkout_dir_name"); + } + } + +exit 0; + +sub usage +{ + warn "@_\n" if @_; + die "usage: $0 [options] svn_url svn_import_dir [dir_v1 [dir_v2 [..]]]\n", + " svn_url is the file:// or http:// URL of the svn repository\n", + " svn_import_dir is the path relative to svn_url where to load dirs\n", + " dir_v1 .. list dirs to import otherwise read from stdin\n", + "options are\n", + " -no_user_input don't ask yes/no questions and assume yes answer\n", + " -no_auto_exe don't set svn:executable for executable files\n", + " -p filename table listing properties to apply to matching files\n", + " -svn_username username to perform commits as\n", + " -svn_password password to supply to svn commit\n", + " -t tag_dir create a tag copy in tag_dir, relative to svn_url\n", + " -v increase program verbosity, multiple -v's allowed\n", + " -wc path use the already checked-out working copy at path\n", + " instead of checkout out a fresh working copy\n", + " -glob_ignores List of filename patterns to ignore (as in svn's\n", + " global-ignores config option)\n"; +} + +# Get the next directory to load, either from the command line or from +# standard input. +my $get_next_load_dir_init = 0; +my @get_next_load_dirs; +sub get_next_load_dir +{ + if (@ARGV) + { + unless ($get_next_load_dir_init) + { + $get_next_load_dir_init = 1; + @get_next_load_dirs = @ARGV; + } + return shift @get_next_load_dirs; + } + + if ($opt_verbose) + { + print "Waiting for next directory to import on standard input:\n"; + } + my $line = ; + + print "\n" if $opt_verbose; + + chomp $line; + if ($line =~ m|(\S+)\s+(\S+)|) + { + $line = $1; + set_svn_use_repos_cmd_opts($2, $opt_svn_password); + } + $line; +} + +# This constant stores the commonly used string to indicate that a +# subroutine has been passed an incorrect number of arguments. +use vars qw($INCORRECT_NUMBER_OF_ARGS); +$INCORRECT_NUMBER_OF_ARGS = "passed incorrect number of arguments.\n"; + +# Creates a temporary file in the temporary directory and stores the +# arguments in it for use by the svn --targets command line option. +# If any part of the file creation failed, exit the program, as +# there's no workaround. Use a unique number as a counter to the +# files. +my $make_targets_file_counter; +sub make_targets_file +{ + unless (@_) + { + confess "$0: make_targets_file $INCORRECT_NUMBER_OF_ARGS"; + } + + $make_targets_file_counter = 1 unless defined $make_targets_file_counter; + + my $filename = sprintf "%s/targets.%05d", + $temp_dir, + $make_targets_file_counter; + ++$make_targets_file_counter; + + open(TARGETS, ">$filename") + or die "$0: cannot open '$filename' for writing: $!\n"; + + foreach my $file (@_) + { + print TARGETS "$file\n"; + } + + close(TARGETS) + or die "$0: error in closing '$filename' for writing: $!\n"; + + $filename; +} + +# Set the svn command line options that are used anytime svn connects +# to the repository. +sub set_svn_use_repos_cmd_opts +{ + unless (@_ == 2) + { + confess "$0: set_svn_use_repos_cmd_opts $INCORRECT_NUMBER_OF_ARGS"; + } + + my $username = shift; + my $password = shift; + + @svn_use_repos_cmd_opts = ('--non-interactive'); + if (defined $username and length $username) + { + push(@svn_use_repos_cmd_opts, '--username', $username); + } + if (defined $password) + { + push(@svn_use_repos_cmd_opts, '--password', $password); + } +} + +sub get_tag_dir +{ + unless (@_ == 1) + { + confess "$0: get_tag_dir $INCORRECT_NUMBER_OF_ARGS"; + } + + my $load_dir = shift; + + # Take the tag relative directory, search for pairs of + # REGEX_SEP_CHAR's and use the regular expression inside the pair to + # put in the tag directory name. + my $tag_location = $opt_import_tag_location; + my $load_tag = ''; + while ((my $i = index($tag_location, $REGEX_SEP_CHAR)) >= 0) + { + $load_tag .= substr($tag_location, 0, $i, ''); + substr($tag_location, 0, 1, ''); + my $j = index($tag_location, $REGEX_SEP_CHAR); + if ($j < 0) + { + die "$0: -t value '$opt_import_tag_location' does not have ", + "matching $REGEX_SEP_CHAR.\n"; + } + my $regex = substr($tag_location, 0, $j, ''); + $regex = "($regex)" unless ($regex =~ /\(.+\)/); + substr($tag_location, 0, 1, ''); + my @results = $load_dir =~ m/$regex/; + $load_tag .= join('', @results); + } + $load_tag .= $tag_location; + + $load_tag; +} + +# Return a two element array. The first element is a single character +# that represents the type of object the path points to. The second +# is a boolean (1 for true, '' for false) if the path points to a file +# and if the file is executable. +sub file_info +{ + lstat(shift) or return ('0', ''); + -b _ and return ('b', ''); + -c _ and return ('c', ''); + -d _ and return ('d', ''); + -f _ and return ('f', -x _); + -l _ and return ('l', ''); + -p _ and return ('p', ''); + -S _ and return ('S', ''); + return '?'; +} + +# Start a child process safely without using /bin/sh. +sub safe_read_from_pipe +{ + unless (@_) + { + croak "$0: safe_read_from_pipe $INCORRECT_NUMBER_OF_ARGS"; + } + + my $openfork_available = "MSWin32" ne $OSNAME; + if ($openfork_available) + { + print "Running @_\n"; + my $pid = open(SAFE_READ, "-|"); + unless (defined $pid) + { + die "$0: cannot fork: $!\n"; + } + unless ($pid) + { + # child + open(STDERR, ">&STDOUT") + or die "$0: cannot dup STDOUT: $!\n"; + exec(@_) + or die "$0: cannot exec '@_': $!\n"; + } + } + else + { + # Redirect the comment into a temp file and use that to work around + # Windoze's (non-)handling of multi-line commands. + my @commandline = (); + my $command; + my $comment; + + while ($command = shift) + { + if ("-m" eq $command) + { + my $comment = shift; + my ($handle, $tmpfile) = tempfile(DIR => $temp_dir); + print $handle $comment; + close($handle); + + push(@commandline, "--file"); + push(@commandline, $tmpfile); + } + else + { + # Munge the command to protect it from the command line + $command =~ s/\"/\\\"/g; + if ($command =~ m"\s") { $command = "\"$command\""; } + if ($command eq "") { $command = "\"\""; } + if ($command =~ m"\n") + { + warn "$0: carriage return detected in command - may not work\n"; + } + push(@commandline, $command); + } + } + + print "Running @commandline\n"; + if ( $comment ) { print $comment; } + + # Now do the pipe. + open(SAFE_READ, "@commandline |") + or die "$0: cannot pipe to command: $!\n"; + } + + # parent + my @output; + while () + { + chomp; + push(@output, $_); + } + close(SAFE_READ); + my $result = $?; + my $exit = $result >> 8; + my $signal = $result & 127; + my $cd = $result & 128 ? "with core dump" : ""; + if ($signal or $cd) + { + warn "$0: pipe from '@_' failed $cd: exit=$exit signal=$signal\n"; + } + if (wantarray) + { + return ($result, @output); + } + else + { + return $result; + } +} + +# Use safe_read_from_pipe to start a child process safely and exit the +# script if the child failed for whatever reason. +sub read_from_process +{ + unless (@_) + { + croak "$0: read_from_process $INCORRECT_NUMBER_OF_ARGS"; + } + my ($status, @output) = &safe_read_from_pipe(@_); + if ($status) + { + print STDERR "$0: @_ failed with this output:\n", join("\n", @output), + "\n"; + unless ($opt_no_user_input) + { + print STDERR + "Press return to quit and clean up svn working directory: "; + ; + } + exit 1; + } + else + { + return @output; + } +} + +# Get a list of all the files and directories in the specified +# directory, the type of file and a digest hash of file types. +sub recursive_ls_and_hash +{ + unless (@_ == 1) + { + croak "$0: recursive_ls_and_hash $INCORRECT_NUMBER_OF_ARGS"; + } + + # This is the directory to change into. + my $dir = shift; + + # Get the current directory so that the script can change into the + # current working directory after changing into the specified + # directory. + my $return_cwd = cwd; + + chdir($dir) + or die "$0: cannot chdir '$dir': $!\n"; + + my %files; + + my $wanted = sub + { + s#^\./##; + return if $_ eq '.'; + my ($file_type) = &file_info($_); + my $file_digest; + if ($file_type eq 'f' or ($file_type eq 'l' and stat($_) and -f _)) + { + $file_digest = &digest_hash_file($_); + } + $files{$_} = {type => $file_type, + digest => $file_digest}; + }; + find({no_chdir => 1, + preprocess => sub + { + grep + { + my $ok=1; + foreach my $x (@glob_ignores) + { + if ( $_ =~ /$x/ ) {$ok=0;last;} + } + $ok + } @_ + }, + wanted => $wanted + }, '.'); + + chdir($return_cwd) + or die "$0: cannot chdir '$return_cwd': $!\n"; + + %files; +} + +# Given a list of files and directories which have been renamed but +# not commtited, commit them with a proper log message. +sub commit_renames +{ + unless (@_ == 4) + { + croak "$0: commit_renames $INCORRECT_NUMBER_OF_ARGS"; + } + + my $load_dir = shift; + my $renamed_filenames = shift; + my $rename_from_files = shift; + my $rename_to_files = shift; + + my $number_renames = @$renamed_filenames/2; + + my $message = "To prepare to load $load_dir into $repos_load_abs_path, " . + "perform $number_renames rename" . + ($number_renames > 1 ? "s" : "") . ".\n"; + + # Text::Wrap::wrap appears to replace multiple consecutive \n's with + # one \n, so wrap the text and then append the second \n. + $message = wrap("", "", $message) . "\n"; + while (@$renamed_filenames) + { + my $from = "$repos_load_abs_path/" . shift @$renamed_filenames; + my $to = "$repos_load_abs_path/" . shift @$renamed_filenames; + $message .= wrap("", " ", "* $to: Renamed from $from.\n"); + } + + # Change to the top of the working copy so that any + # directories will also be updated. + my $cwd = cwd; + chdir($wc_import_dir_cwd) + or die "$0: cannot chdir '$wc_import_dir_cwd': $!\n"; + read_from_process($svn, 'commit', @svn_use_repos_cmd_opts, '-m', $message); + read_from_process($svn, 'update', @svn_use_repos_cmd_opts); + chdir($cwd) + or die "$0: cannot chdir '$cwd': $!\n"; + + # Some versions of subversion have a bug where renamed files + # or directories are not deleted after a commit, so do that + # here. + my @del_files = sort {length($b) <=> length($a) || $a cmp $b } + keys %$rename_from_files; + rmtree(\@del_files, 1, 0); + + # Empty the list of old and new renamed names. + undef %$rename_from_files; + undef %$rename_to_files; +} + +# Take a one file or directory and see if its name is equal to a +# second or is contained in the second if the second file's file type +# is a directory. +sub contained_in +{ + unless (@_ == 3) + { + croak "$0: contain_in $INCORRECT_NUMBER_OF_ARGS"; + } + + my $contained = shift; + my $container = shift; + my $container_type = shift; + + if ($container eq $contained) + { + return 1; + } + + if ($container_type eq 'd') + { + my $dirname = "$container/"; + my $dirname_length = length($dirname); + + if ($dirname_length <= length($contained) and + $dirname eq substr($contained, 0, $dirname_length)) + { + return 1; + } + } + + return 0; +} + +# Take an array reference containing a list of files and directories +# and take a hash reference and remove from the array reference any +# files and directories and the files the directory contains listed in +# the hash. +sub filter_renamed_files +{ + unless (@_ == 2) + { + croak "$0: filter_renamed_files $INCORRECT_NUMBER_OF_ARGS"; + } + + my $array_ref = shift; + my $hash_ref = shift; + + foreach my $remove_filename (keys %$hash_ref) + { + my $remove_file_type = $hash_ref->{$remove_filename}{type}; + for (my $i=0; $i<@$array_ref;) + { + if (contained_in($array_ref->[$i], + $remove_filename, + $remove_file_type)) + { + splice(@$array_ref, $i, 1); + next; + } + ++$i; + } + } +} + +# Get a digest hash of the specified filename. +sub digest_hash_file +{ + unless (@_ == 1) + { + croak "$0: digest_hash_file $INCORRECT_NUMBER_OF_ARGS"; + } + + my $filename = shift; + + my $ctx = Digest::MD5->new; + if (open(READ, $filename)) + { + binmode READ; + $ctx->addfile(*READ); + close(READ); + } + else + { + die "$0: cannot open '$filename' for reading: $!\n"; + } + $ctx->digest; +} + +# Read standard input until a line contains the required input or an +# empty line to signify the default answer. +sub get_answer +{ + unless (@_ == 3) + { + croak "$0: get_answer $INCORRECT_NUMBER_OF_ARGS"; + } + + my $message = shift; + my $answers = shift; + my $def_ans = shift; + + return $def_ans if $opt_no_user_input; + + my $char; + do + { + print $message; + $char = ''; + my $line = ; + if (defined $line and length $line) + { + $char = substr($line, 0, 1); + $char = '' if $char eq "\n"; + } + } until $char eq '' or $answers =~ /$char/ig; + + return $def_ans if $char eq ''; + return pos($answers) - 1; +} + +# Determine the native end of line on this system by writing a \n in +# non-binary mode to an empty file and reading the same file back in +# binary mode. +sub determine_native_eol +{ + my $filename = "$temp_dir/svn_load_dirs_eol_test.$$"; + if (-e $filename) + { + unlink($filename) + or die "$0: cannot unlink '$filename': $!\n"; + } + + # Write the \n in non-binary mode. + open(NL_TEST, ">$filename") + or die "$0: cannot open '$filename' for writing: $!\n"; + print NL_TEST "\n"; + close(NL_TEST) + or die "$0: error in closing '$filename' for writing: $!\n"; + + # Read the \n in binary mode. + open(NL_TEST, $filename) + or die "$0: cannot open '$filename' for reading: $!\n"; + binmode NL_TEST; + local $/; + undef $/; + my $eol = ; + close(NL_TEST) + or die "$0: cannot close '$filename' for reading: $!\n"; + unlink($filename) + or die "$0: cannot unlink '$filename': $!\n"; + + my $eol_length = length($eol); + unless ($eol_length) + { + die "$0: native eol length on this system is 0.\n"; + } + + print "Native EOL on this system is "; + for (my $i=0; $i<$eol_length; ++$i) + { + printf "\\%03o", ord(substr($eol, $i, 1)); + } + print ".\n\n"; + + $eol; +} + +# Take a filename, open the file and replace all CR, CRLF and LF's +# with the native end of line style for this system. +sub convert_file_to_native_eol +{ + unless (@_ == 1) + { + croak "$0: convert_file_to_native_eol $INCORRECT_NUMBER_OF_ARGS"; + } + + my $filename = shift; + open(FILE, $filename) + or die "$0: cannot open '$filename' for reading: $!\n"; + binmode FILE; + local $/; + undef $/; + my $in = ; + close(FILE) + or die "$0: error in closing '$filename' for reading: $!\n"; + my $out = ''; + + # Go through the file and transform it byte by byte. + my $i = 0; + while ($i < length($in)) + { + my $cc = substr($in, $i, 2); + if ($cc eq "\015\012") + { + $out .= $native_eol; + $i += 2; + next; + } + + my $c = substr($cc, 0, 1); + if ($c eq "\012" or $c eq "\015") + { + $out .= $native_eol; + } + else + { + $out .= $c; + } + ++$i; + } + + return 0 if $in eq $out; + + my $tmp_filename = ".svn/tmp/svn_load_dirs.$$"; + open(FILE, ">$tmp_filename") + or die "$0: cannot open '$tmp_filename' for writing: $!\n"; + binmode FILE; + print FILE $out; + close(FILE) + or die "$0: cannot close '$tmp_filename' for writing: $!\n"; + rename($tmp_filename, $filename) + or die "$0: cannot rename '$tmp_filename' to '$filename': $!\n"; + + return 1; +} + +# Split the input line into words taking into account that single or +# double quotes may define a single word with whitespace in it. +sub split_line +{ + unless (@_ == 1) + { + croak "$0: split_line $INCORRECT_NUMBER_OF_ARGS"; + } + + my $line = shift; + + # Strip leading whitespace. Do not strip trailing whitespace which + # may be part of quoted text that was never closed. + $line =~ s/^\s+//; + + my $line_length = length $line; + my @words = (); + my $current_word = ''; + my $in_quote = ''; + my $in_protect = ''; + my $in_space = ''; + my $i = 0; + + while ($i < $line_length) + { + my $c = substr($line, $i, 1); + ++$i; + + if ($in_protect) + { + if ($c eq $in_quote) + { + $current_word .= $c; + } + elsif ($c eq '"' or $c eq "'") + { + $current_word .= $c; + } + else + { + $current_word .= "$in_protect$c"; + } + $in_protect = ''; + } + elsif ($c eq '\\') + { + $in_protect = $c; + } + elsif ($in_quote) + { + if ($c eq $in_quote) + { + $in_quote = ''; + } + else + { + $current_word .= $c; + } + } + elsif ($c eq '"' or $c eq "'") + { + $in_quote = $c; + } + elsif ($c =~ m/^\s$/) + { + unless ($in_space) + { + push(@words, $current_word); + $current_word = ''; + } + } + else + { + $current_word .= $c; + } + + $in_space = $c =~ m/^\s$/; + } + + # Handle any leftovers. + $current_word .= $in_protect if $in_protect; + push(@words, $current_word) if length $current_word; + + @words; +} + +# This package exists just to delete the temporary directory. +package Temp::Delete; + +sub new +{ + bless {}, shift; +} + +sub DESTROY +{ + print "Cleaning up $temp_dir\n"; + File::Path::rmtree([$temp_dir], 0, 0); +} --- subversion-1.7.9.orig/debian/contrib/svn_load_dirs/svn_load_dirs_property_table.example +++ subversion-1.7.9/debian/contrib/svn_load_dirs/svn_load_dirs_property_table.example @@ -0,0 +1,29 @@ +# This is sample table for svn_load_dirs.pl -p command line option. +\.(ai|eps|ps)$ break svn:mime-type application/postscript +\.bz2$ break svn:mime-type application/x-bzip2 +\.css$ break svn:mime-type text/css +\.doc$ break svn:mime-type application/msword +\.ds(p|w)$ break svn:eol-style CRLF +\.exe$ break svn:mime-type application/octet-stream +\.gif$ break svn:mime-type image/gif +\.gtar$ break svn:mime-type application/x-gtar +\.(gz|tgz)$ break svn:mime-type application/x-gzip +\.hqx$ break svn:mime-type application/mac-binhex40 +\.html?$ break svn:mime-type text/html +\.ilk$ break svn:eol-style CRLF +\.(jpeg|jpg|jpe)$ break svn:mime-type image/jpeg +\.js$ break svn:mime-type application/x-javascript +\.(mov|qt)$ break svn:mime-type video/quicktime +\.ncb$ break svn:eol-style CRLF +\.opt$ break svn:eol-style CRLF +\.pdf$ break svn:mime-type application/pdf +\.png$ break svn:mime-type image/png +\.pp(s|t)$ break svn:mime-type application/vnd.ms-powerpoint +\.rtf$ break svn:mime-type application/rtf +\.swf$ break svn:mime-type application/x-shockwave-flash +\.tar$ break svn:mime-type application/x-tar +\.tiff?$ break svn:mime-type image/tiff +\.xls$ break svn:mime-type application/vnd.ms-excel +\.zip$ break svn:mime-type application/zip +dos2unix-eol\.sh$ break +#.* break svn:eol-style native --- subversion-1.7.9.orig/debian/control +++ subversion-1.7.9/debian/control @@ -0,0 +1,167 @@ +Source: subversion +Section: vcs +Priority: optional +Maintainer: Peter Samuelson +Uploaders: Troy Heber , + Guilherme de S. Pastore +Build-Depends: debhelper, libneon27-gnutls-dev, libserf-dev (>= 1), zlib1g-dev, + libapr1-dev, libaprutil1-dev, libdb5.1-dev, + libsasl2-dev, + libsqlite3-dev (>= 3.4), libgnome-keyring-dev, libdbus-1-dev, kdelibs5-dev, + quilt, doxygen, autotools-dev, autoconf, libtool, swig, + python-all-dev, perl, libperl-dev, ruby1.8, ruby1.8-dev, + gcj-jdk (>= 4:4.4) [!alpha !arm !hppa !m68k !mips !mipsel !hurd-i386], + junit [!alpha !arm !hppa !m68k !mips !mipsel !hurd-i386] +Build-Conflicts: libsvn-dev (<< 1.7~) +Homepage: http://subversion.apache.org/ +Vcs-Svn: svn://svn.debian.org/pkg-subversion/src/1.7.x/ +Vcs-Browser: http://svn.debian.org/wsvn/pkg-subversion/src/1.7.x/ +Standards-Version: 3.9.3 + +Package: subversion +Architecture: any +Depends: libsvn1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} +Suggests: subversion-tools, db5.1-util, patch +Description: Advanced version control system + Apache Subversion, also known as svn, is a centralised version control + system. Version control systems allow many individuals (who may be + distributed geographically) to collaborate on a set of files (source + code, websites, etc). Subversion began with a CVS paradigm and + supports all the major features of CVS, but has evolved to support + many features that CVS users often wish they had. + . + This package includes the Subversion client (svn), repository + administration tools (svnadmin, svnlook) and a network server (svnserve). + +Package: libsvn1 +Section: libs +Architecture: any +Multi-Arch: same +Pre-Depends: multiarch-support +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Shared libraries used by Apache Subversion + This package includes shared libraries to manipulate Apache Subversion + (svn) repositories and working copies. See the 'subversion' package for + more information. + +Package: libsvn-dev +Section: libdevel +Priority: extra +Architecture: any +Depends: libsvn1 (= ${binary:Version}), libapr1-dev, libaprutil1-dev, + ${misc:Depends} +Suggests: libsvn-doc, zlib1g-dev, libneon27-gnutls-dev +Description: Development files for Apache Subversion libraries + This package contains the symlinks, headers, and object files needed + to compile and link programs which use libsvn1, the Apache Subversion + libraries. This package is needed only in order to compile software + that uses libsvn1. + +Package: libsvn-doc +Suggests: libsvn-dev +Section: doc +Priority: extra +Architecture: all +Depends: ${misc:Depends} +Description: Developer documentation for libsvn + This package contains development (API) documentation for libsvn1, the + Apache Subversion libraries. See the 'libsvn1' package for more information. + +Package: python-subversion +Section: python +Architecture: any +Pre-Depends: multiarch-support +Depends: ${shlibs:Depends}, ${python:Depends}, ${misc:Depends} +Provides: ${python:Provides} +Description: Python bindings for Apache Subversion + This is a set of Python interfaces to libsvn, the Apache Subversion + libraries. It is useful if you want to, for example, write a Python + script that manipulates a Subversion repository or working copy. See + the 'subversion' package for more information. + +Package: subversion-tools +Priority: extra +Architecture: all +Depends: subversion, ${misc:Depends} +Breaks: subversion (<< 1.7) +Replaces: subversion (<< 1.7) +Recommends: python-subversion, libsvn-perl, + libconfig-inifiles-perl, liburi-perl, + exim4 | mail-transport-agent, rsync, svn2cl +Suggests: libsvn-ruby1.8 +Description: Assorted tools related to Apache Subversion + This package includes miscellaneous tools for use with Apache Subversion + clients and servers: + * svn-backup-dumps: Incremental dumpfile-based backup script + * svn-bisect: Bisect revisions to find a regression + * svn-clean: Remove unversioned files from a working copy + * svn-fast-backup: rsync-based backup script for FSFS repositories + * svn-hot-backup: Backup script, primarily for BDB repositories + * svn_apply_autoprops: Apply property settings from + .subversion/config file to an existing repository + * svn_load_dirs: Sophisticated replacement for 'svn import' + * svnwrap: Set umask to 002 before calling svn or svnserve + * several example hook scripts: commit-access-control, commit-email, + log-police, mailer, svnperms, verify-po + . + NOTE that some of these scripts are unsupported by upstream, and may + change radically or disappear in future releases. Some of these + scripts require packages on the Recommends list. + +Package: libsvn-java +Section: java +Architecture: any +Depends: libsvn1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} +Conflicts: libsvn-jni +Replaces: libsvn-jni +Description: Java bindings for Apache Subversion + This is a set of Java classes which provide the functionality of + libsvn, the Apache Subversion libraries. It is useful if you want to, + for example, write a Java class that manipulates a Subversion repository + or working copy. See the 'subversion' package for more information. + +Package: libsvn-perl +Section: perl +Architecture: any +Pre-Depends: multiarch-support +Depends: ${perl:Depends}, ${shlibs:Depends}, ${misc:Depends} +Description: Perl bindings for Apache Subversion + This is a set of Perl interfaces to libsvn, the Apache Subversion libraries. + It is useful if you want to, for example, write a Perl script that + manipulates a Subversion repository or working copy. See the + 'subversion' package for more information. + +Package: ruby-svn +Section: ruby +Architecture: any +Multi-Arch: same +Pre-Depends: multiarch-support +Depends: ruby1.8, ${shlibs:Depends}, ${misc:Depends} +Provides: libsvn-ruby1.8 +Replaces: libsvn-ruby1.8 (<< 1.6.18dfsg-1) +Breaks: libsvn-ruby1.8 (<< 1.6.18dfsg-1) +Description: Ruby bindings for Apache Subversion + This is a set of Ruby interfaces to libsvn, the Apache Subversion libraries. + It is useful if you want to, for example, write a Ruby script that + manipulates a Subversion repository or working copy. See the + 'subversion' package for more information. + +Package: libsvn-ruby1.8 +Section: oldlibs +Priority: extra +Architecture: all +Depends: ruby-svn, ${misc:Depends} +Description: Ruby bindings for Apache Subversion (dummy package) + This is a transition package to install the Apache Subversion library + bindings for Ruby 1.8. You may remove this package if nothing depends + on it. + +Package: libsvn-ruby +Section: oldlibs +Priority: extra +Architecture: all +Depends: ruby-svn, ${misc:Depends} +Description: Ruby bindings for Apache Subversion (dummy package) + This is a transition package to install the Apache Subversion library + bindings for Ruby 1.8. You may remove this package if nothing depends + on it. --- subversion-1.7.9.orig/debian/copyright +++ subversion-1.7.9/debian/copyright @@ -0,0 +1,356 @@ +This package was put together by David Kimdon . +Current maintainer is Peter Samuelson . + +Source was downloaded from: + + http://subversion.apache.org/download/ + +Portions are licensed under the Apache License version 2.0, the GNU GPL +version 2, and the GNU GPL version 3, which on Debian systems can be +found respectively at /usr/share/common-licenses/Apache-2.0, +/usr/share/common-licenses/GPL-2, and /usr/share/common-licenses/GPL-3. + +==================================================================== + +Except where noted below, the Subversion software is: + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +==================================================================== + +For portions of the Python bindings test suite at +subversion/bindings/swig/python/tests/trac/: + + I. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + II. Copyright (C) 2003, 2004, 2005 Edgewall Software + Copyright (C) 2003, 2004, 2005 Jonas Borgström + Copyright (C) 2005 Christopher Lenz + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + the documentation and/or other materials provided with the + distribution. + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +==================================================================== + +debian/bin/svnwrap.sh is: + Copyright 2006 by Peter Samuelson + Permission is granted to everyone to use and distribute this work, + without limitation, modified or unmodified, in any way, for any purpose. + +debian/contrib/svn-clean is: + Copyright (C) 2004, 2005, 2006 Simon Perreault + + This program 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 + of the License, or (at your option) any later version. + + This program 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. + +debian/bin/svn-bisect is: + Copyright (C) 2008,2009 by Robert Millan + Copyright (C) 2009 by Peter Samuelson + + This program 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 3 of the License, or + (at your option) any later version. + + This program 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. + +debian/contrib/svn_apply_autoprops is: + Copyright (C) 2005,2006 Blair Zajac + + This script 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 of the License, or + (at your option) any later version. + + This script 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. + +debian/contrib/svn_load_dirs is: + Copyright (c) 2002,2003,2004,2005,2006,2007,2009 Dolby. All rights reserved. + + Licensed under the Academic Free License version 3.0: + + http://www.opensource.org/licenses/academic.php + + Academic Free License ("AFL") v. 3.0 + + This Academic Free License (the "License") applies to any original + work of authorship (the "Original Work") whose owner (the "Licensor") + has placed the following licensing notice adjacent to the copyright + notice for the Original Work: + + Licensed under the Academic Free License version 3.0 + + 1) Grant of Copyright License. Licensor grants You a worldwide, + royalty-free, non-exclusive, sublicensable license, for the + duration of the copyright, to do the following: + a) to reproduce the Original Work in copies, either alone or as + part of a collective work; + b) to translate, adapt, alter, transform, modify, or arrange the + Original Work, thereby creating derivative works ("Derivative + Works") based upon the Original Work; + c) to distribute or communicate copies of the Original Work and + Derivative Works to the public, under any license of your + choice that does not contradict the terms and conditions, + including Licensor's reserved rights and remedies, in this + Academic Free License; + d) to perform the Original Work publicly; and + e) to display the Original Work publicly. + + 2) Grant of Patent License. Licensor grants You a worldwide, + royalty-free, non- exclusive, sublicensable license, under patent + claims owned or controlled by the Licensor that are embodied in + the Original Work as furnished by the Licensor, for the duration + of the patents, to make, use, sell, offer for sale, have made, and + import the Original Work and Derivative Works. + + 3) Grant of Source Code License. The term "Source Code" means the + preferred form of the Original Work for making modifications to it + and all available documentation describing how to modify the + Original Work. Licensor agrees to provide a machine-readable copy + of the Source Code of the Original Work along with each copy of + the Original Work that Licensor distributes. Licensor reserves the + right to satisfy this obligation by placing a machine-readable + copy of the Source Code in an information repository reasonably + calculated to permit inexpensive and convenient access by You for + as long as Licensor continues to distribute the Original Work. + + 4) Exclusions From License Grant. Neither the names of Licensor, nor + the names of any contributors to the Original Work, nor any of + their trademarks or service marks, may be used to endorse or + promote products derived from this Original Work without express + prior permission of the Licensor. Except as expressly stated + herein, nothing in this License grants any license to Licensor's + trademarks, copyrights, patents, trade secrets or any other + intellectual property. No patent license is granted to make, use, + sell, offer for sale, have made, or import embodiments of any + patent claims other than the licensed claims defined in Section + 2. No license is granted to the trademarks of Licensor even if + such marks are included in the Original Work. Nothing in this + License shall be interpreted to prohibit Licensor from licensing + under terms different from this License any Original Work that + Licensor otherwise would have a right to license. + + 5) External Deployment. The term "External Deployment" means the use, + distribution, or communication of the Original Work or Derivative + Works in any way such that the Original Work or Derivative Works + may be used by anyone other than You, whether those works are + distributed or communicated to those persons or made available as + an application intended for use over a network. As an express + condition for the grants of license hereunder, You must treat any + External Deployment by You of the Original Work or a Derivative + Work as a distribution under section 1(c). + + 6) Attribution Rights. You must retain, in the Source Code of any + Derivative Works that You create, all copyright, patent, or + trademark notices from the Source Code of the Original Work, as + well as any notices of licensing and any descriptive text + identified therein as an "Attribution Notice." You must cause the + Source Code for any Derivative Works that You create to carry a + prominent Attribution Notice reasonably calculated to inform + recipients that You have modified the Original Work. + + 7) Warranty of Provenance and Disclaimer of Warranty. Licensor + warrants that the copyright in and to the Original Work and the + patent rights granted herein by Licensor are owned by the Licensor + or are sublicensed to You under the terms of this License with the + permission of the contributor(s) of those copyrights and patent + rights. Except as expressly stated in the immediately preceding + sentence, the Original Work is provided under this License on an + "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, + including, without limitation, the warranties of non-infringement, + merchantability or fitness for a particular purpose. THE ENTIRE + RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This + DISCLAIMER OF WARRANTY constitutes an essential part of this + License. No license to the Original Work is granted by this + License except under this disclaimer. + + 8) Limitation of Liability. Under no circumstances and under no legal + theory, whether in tort (including negligence), contract, or + otherwise, shall the Licensor be liable to anyone for any + indirect, special, incidental, or consequential damages of any + character arising as a result of this License or the use of the + Original Work including, without limitation, damages for loss of + goodwill, work stoppage, computer failure or malfunction, or any + and all other commercial damages or losses. This limitation of + liability shall not apply to the extent applicable law prohibits + such limitation. + + 9) Acceptance and Termination. If, at any time, You expressly + assented to this License, that assent indicates your clear and + irrevocable acceptance of this License and all of its terms and + conditions. If You distribute or communicate copies of the + Original Work or a Derivative Work, You must make a reasonable + effort under the circumstances to obtain the express assent of + recipients to the terms of this License. This License conditions + your rights to undertake the activities listed in Section 1, + including your right to create Derivative Works based upon the + Original Work, and doing so without honoring these terms and + conditions is prohibited by copyright law and international + treaty. Nothing in this License is intended to affect copyright + exceptions and limitations (including "fair use" or "fair + dealing"). This License shall terminate immediately and You may no + longer exercise any of the rights granted to You by this License + upon your failure to honor the conditions in Section 1(c). + + 10) Termination for Patent Action. This License shall terminate + automatically and You may no longer exercise any of the rights + granted to You by this License as of the date You commence an + action, including a cross-claim or counterclaim, against Licensor + or any licensee alleging that the Original Work infringes a + patent. This termination provision shall not apply for an action + alleging patent infringement by combinations of the Original Work + with other software or hardware. + + 11) Jurisdiction, Venue and Governing Law. Any action or suit relating + to this License may be brought only in the courts of a + jurisdiction wherein the Licensor resides or in which Licensor + conducts its primary business, and under the laws of that + jurisdiction excluding its conflict-of-law provisions. The + application of the United Nations Convention on Contracts for the + International Sale of Goods is expressly excluded. Any use of the + Original Work outside the scope of this License or after its + termination shall be subject to the requirements and penalties of + copyright or patent law in the appropriate jurisdiction. This + section shall survive the termination of this License. + + 12) Attorneys' Fees. In any action to enforce the terms of this + License or seeking damages relating thereto, the prevailing party + shall be entitled to recover its costs and expenses, including, + without limitation, reasonable attorneys' fees and costs incurred + in connection with such action, including any appeal of such + action. This section shall survive the termination of this + License. + + 13) Miscellaneous. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. + + 14) Definition of "You" in This License. "You" throughout this + License, whether in upper or lower case, means an individual or a + legal entity exercising rights under, and complying with all of + the terms of, this License. For legal entities, "You" includes any + entity that controls, is controlled by, or is under common control + with you. For purposes of this definition, "control" means (i) the + power, direct or indirect, to cause the direction or management of + such entity, whether by contract or otherwise, or (ii) ownership + of fifty percent (50%) or more of the outstanding shares, or (iii) + beneficial ownership of such entity. + + 15) Right to Use. You may use the Original Work in all ways not + otherwise restricted or conditioned by this License or by law, and + Licensor promises not to interfere with or be responsible for such + uses by You. + + 16) Modification of This License. This License is Copyright © 2005 + Lawrence Rosen. Permission is granted to copy, distribute, or + communicate this License without modification. Nothing in this + License permits You to modify this License as applied to the + Original Work or to Derivative Works. However, You may modify the + text of this License and copy, distribute or communicate your + modified version (the "Modified License") and apply it to other + original works of authorship subject to the following conditions: + (i) You may not indicate in any way that your Modified License is + the "Academic Free License" or "AFL" and you may not use those + names in the name of your Modified License; (ii) You must replace + the notice specified in the first paragraph above with the notice + "Licensed under " or with a notice + of your own that is not confusingly similar to the notice in this + License; and (iii) You may not claim that your original works are + open source software unless your Modified License has been + approved by Open Source Initiative (OSI) and You comply with its + license review and certification process. + +debian/contrib/emacs/psvn.el is: + Copyright (C) 2002-2009 by Stefan Reichoer + + 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. + +debian/contrib/emacs/dsvn.el is: + Copyright 2006-2010 Virtutech AB + Copyright 2010 Intel + + This program 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 of the + License, or (at your option) any later version. + + This program 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. --- subversion-1.7.9.orig/debian/dav_svn.conf +++ subversion-1.7.9/debian/dav_svn.conf @@ -0,0 +1,56 @@ +# dav_svn.conf - Example Subversion/Apache configuration +# +# For details and further options see the Apache user manual and +# the Subversion book. +# +# NOTE: for a setup with multiple vhosts, you will want to do this +# configuration in /etc/apache2/sites-available/*, not here. + +# ... +# URL controls how the repository appears to the outside world. +# In this example clients access the repository as http://hostname/svn/ +# Note, a literal /svn should NOT exist in your document root. +# + + # Uncomment this to enable the repository + #DAV svn + + # Set this to the path to your repository + #SVNPath /var/lib/svn + # Alternatively, use SVNParentPath if you have multiple repositories under + # under a single directory (/var/lib/svn/repo1, /var/lib/svn/repo2, ...). + # You need either SVNPath and SVNParentPath, but not both. + #SVNParentPath /var/lib/svn + + # Access control is done at 3 levels: (1) Apache authentication, via + # any of several methods. A "Basic Auth" section is commented out + # below. (2) Apache and , also commented out + # below. (3) mod_authz_svn is a svn-specific authorization module + # which offers fine-grained read/write access control for paths + # within a repository. (The first two layers are coarse-grained; you + # can only enable/disable access to an entire repository.) Note that + # mod_authz_svn is noticeably slower than the other two layers, so if + # you don't need the fine-grained control, don't configure it. + + # Basic Authentication is repository-wide. It is not secure unless + # you are using https. See the 'htpasswd' command to create and + # manage the password file - and the documentation for the + # 'auth_basic' and 'authn_file' modules, which you will need for this + # (enable them with 'a2enmod'). + #AuthType Basic + #AuthName "Subversion Repository" + #AuthUserFile /etc/apache2/dav_svn.passwd + + # To enable authorization via mod_authz_svn (enable that module separately): + # + #AuthzSVNAccessFile /etc/apache2/dav_svn.authz + # + + # The following three lines allow anonymous read, but make + # committers authenticate themselves. It requires the 'authz_user' + # module (enable it with 'a2enmod'). + # + #Require valid-user + # + +# --- subversion-1.7.9.orig/debian/dav_svn.load +++ subversion-1.7.9/debian/dav_svn.load @@ -0,0 +1,2 @@ +# Depends: dav +LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so --- subversion-1.7.9.orig/debian/libapache2-svn.README.Debian +++ subversion-1.7.9/debian/libapache2-svn.README.Debian @@ -0,0 +1,4 @@ +This apache module is configured in /etc/apache2/mods-available/dav_svn.conf + + + -- Guilherme de S. Pastore , Sat Aug 20 19:56:07 2005 --- subversion-1.7.9.orig/debian/libapache2-svn.dirs +++ subversion-1.7.9/debian/libapache2-svn.dirs @@ -0,0 +1 @@ +usr/share/doc/libapache2-svn --- subversion-1.7.9.orig/debian/libapache2-svn.examples +++ subversion-1.7.9/debian/libapache2-svn.examples @@ -0,0 +1 @@ +tools/xslt/svnindex.* --- subversion-1.7.9.orig/debian/libapache2-svn.install +++ subversion-1.7.9/debian/libapache2-svn.install @@ -0,0 +1,4 @@ +debian/tmp/usr/lib/apache2/modules/*_svn.so usr/lib/apache2/modules +debian/dav_svn.conf etc/apache2/mods-available +debian/dav_svn.load etc/apache2/mods-available +debian/authz_svn.load etc/apache2/mods-available --- subversion-1.7.9.orig/debian/libapache2-svn.lintian-overrides +++ subversion-1.7.9/debian/libapache2-svn.lintian-overrides @@ -0,0 +1,2 @@ +# this is config documentation, not "how to build the package" +libapache2-svn: package-contains-upstream-install-documentation usr/share/doc/libapache2-svn/INSTALL.authz.gz --- subversion-1.7.9.orig/debian/libapache2-svn.postinst +++ subversion-1.7.9/debian/libapache2-svn.postinst @@ -0,0 +1,18 @@ +#!/bin/sh -e + +case "$1" in + configure) + if [ -z "$2" ]; then + # Enable on new installs only + a2enmod dav_svn + fi + if [ -f '/etc/apache2/#enable_authz_svn#' ]; then + # Enable on upgrades where this used to be implied by dav_svn.load + a2enmod authz_svn + rm -f '/etc/apache2/#enable_authz_svn#' + fi + invoke-rc.d apache2 restart || true + ;; +esac + +#DEBHELPER# --- subversion-1.7.9.orig/debian/libapache2-svn.preinst +++ subversion-1.7.9/debian/libapache2-svn.preinst @@ -0,0 +1,15 @@ +#!/bin/sh -e + +#DEBHELPER# + +case "$1" in + install | upgrade) + # The transition from dav_svn.load with authz_svn_module in it, + # to a separate .load file, happened in 1.6.17dfsg-2. Here we + # signal the postinst, with a temp file, to enable authz_svn. + if grep -q '^LoadModule *authz_svn_module' \ + /etc/apache2/mods-enabled/dav_svn.load 2>/dev/null; then + touch '/etc/apache2/#enable_authz_svn#' + fi + ;; +esac --- subversion-1.7.9.orig/debian/libapache2-svn.prerm +++ subversion-1.7.9/debian/libapache2-svn.prerm @@ -0,0 +1,9 @@ +#!/bin/sh -e + +case "$1" in + remove) + a2dismod authz_svn dav_svn + ;; +esac + +#DEBHELPER# --- subversion-1.7.9.orig/debian/libsvn-dev.install +++ subversion-1.7.9/debian/libsvn-dev.install @@ -0,0 +1,4 @@ +debian/tmp/usr/include/subversion-1 +debian/tmp/usr/lib/*/*.a +debian/tmp/usr/lib/*/*.so +debian/tmp/usr/lib/*/*.la --- subversion-1.7.9.orig/debian/libsvn-dev.links +++ subversion-1.7.9/debian/libsvn-dev.links @@ -0,0 +1 @@ +usr/share/doc/libsvn1 usr/share/doc/libsvn-dev --- subversion-1.7.9.orig/debian/libsvn-dev.postinst +++ subversion-1.7.9/debian/libsvn-dev.postinst @@ -0,0 +1,12 @@ +#/bin/sh + +set -e + +pkgdir=/usr/share/doc/libsvn-dev +if [ -d $pkgdir ] && [ ! -L $pkgdir ]; then + if rmdir $pkgdir; then + ln -sf /usr/share/doc/libsvn1 $pkgdir + fi +fi + +#DEBHELPER# --- subversion-1.7.9.orig/debian/libsvn-doc.examples +++ subversion-1.7.9/debian/libsvn-doc.examples @@ -0,0 +1 @@ +tools/examples/*.c --- subversion-1.7.9.orig/debian/libsvn-java.install +++ subversion-1.7.9/debian/libsvn-java.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/*/libsvnjavahl*.so* usr/lib/jni +debian/tmp/usr/share/java usr/share --- subversion-1.7.9.orig/debian/libsvn-java.links +++ subversion-1.7.9/debian/libsvn-java.links @@ -0,0 +1 @@ +usr/share/doc/libsvn1 usr/share/doc/libsvn-java --- subversion-1.7.9.orig/debian/libsvn-java.postinst +++ subversion-1.7.9/debian/libsvn-java.postinst @@ -0,0 +1,12 @@ +#/bin/sh + +set -e + +pkgdir=/usr/share/doc/libsvn-java +if [ -d $pkgdir ] && [ ! -L $pkgdir ]; then + if rmdir $pkgdir; then + ln -sf /usr/share/doc/libsvn1 $pkgdir + fi +fi + +#DEBHELPER# --- subversion-1.7.9.orig/debian/libsvn-perl.install +++ subversion-1.7.9/debian/libsvn-perl.install @@ -0,0 +1,3 @@ +debian/tmp/usr/lib/perl5 +debian/tmp/usr/lib/*/libsvn_swig_perl*.so.* +debian/tmp/usr/share/man/man3/SVN::*.3perl --- subversion-1.7.9.orig/debian/libsvn-perl.lintian-overrides +++ subversion-1.7.9/debian/libsvn-perl.lintian-overrides @@ -0,0 +1,2 @@ +# nobody but us will ever link to this, so we don't ship a shlibs file +no-shlibs-control-file usr/lib/*/libsvn_swig_perl-1.so.* --- subversion-1.7.9.orig/debian/libsvn-ruby.links +++ subversion-1.7.9/debian/libsvn-ruby.links @@ -0,0 +1 @@ +usr/share/doc/ruby-svn usr/share/doc/libsvn-ruby --- subversion-1.7.9.orig/debian/libsvn-ruby.postinst +++ subversion-1.7.9/debian/libsvn-ruby.postinst @@ -0,0 +1,12 @@ +#/bin/sh + +set -e + +pkgdir=/usr/share/doc/libsvn-ruby +if [ -d $pkgdir ] && [ ! -L $pkgdir ]; then + if rmdir $pkgdir; then + ln -sf /usr/share/doc/ruby-svn $pkgdir + fi +fi + +#DEBHELPER# --- subversion-1.7.9.orig/debian/libsvn-ruby1.8.links +++ subversion-1.7.9/debian/libsvn-ruby1.8.links @@ -0,0 +1 @@ +usr/share/doc/ruby-svn usr/share/doc/libsvn-ruby1.8 --- subversion-1.7.9.orig/debian/libsvn-ruby1.8.postinst +++ subversion-1.7.9/debian/libsvn-ruby1.8.postinst @@ -0,0 +1,12 @@ +#/bin/sh + +set -e + +pkgdir=/usr/share/doc/libsvn-ruby1.8 +if [ -d $pkgdir ] && [ ! -L $pkgdir ]; then + if rmdir $pkgdir; then + ln -sf /usr/share/doc/ruby-svn $pkgdir + fi +fi + +#DEBHELPER# --- subversion-1.7.9.orig/debian/libsvn1.install +++ subversion-1.7.9/debian/libsvn1.install @@ -0,0 +1,9 @@ +debian/tmp/usr/lib/*/libsvn_ra*.so.1* +debian/tmp/usr/lib/*/libsvn_fs*.so.1* +debian/tmp/usr/lib/*/libsvn_wc-1.so.1* +debian/tmp/usr/lib/*/libsvn_delta-1.so.1* +debian/tmp/usr/lib/*/libsvn_subr-1.so.1* +debian/tmp/usr/lib/*/libsvn_client-1.so.1* +debian/tmp/usr/lib/*/libsvn_repos-1.so.1* +debian/tmp/usr/lib/*/libsvn_diff-1.so.1* +debian/tmp/usr/lib/*/libsvn_auth_*.so.1* --- subversion-1.7.9.orig/debian/libsvn1.lintian-overrides +++ subversion-1.7.9/debian/libsvn1.lintian-overrides @@ -0,0 +1,20 @@ +# These aren't really for external use; arguably should move to a subdir. +shlib-missing-in-control-file libsvn_fs_util-1 * +shlib-missing-in-control-file libsvn_fs_fs-1 * +shlib-missing-in-control-file libsvn_ra_serf-1 * +shlib-missing-in-control-file libsvn_ra_neon-1 * +shlib-missing-in-control-file libsvn_ra_local-1 * +shlib-missing-in-control-file libsvn_fs_base-1 * +shlib-missing-in-control-file libsvn_auth_kwallet-1 * +shlib-missing-in-control-file libsvn_auth_gnome_keyring-1 * +# Intentional, so people don't try to use private symbols. +symbols-declares-dependency-on-other-package libsvn-private +# Harmless, fixed in dh compat level 8 +symbols-declared-but-not-shlib libsvn_ra_serf-1 1 +symbols-declared-but-not-shlib libsvn_fs_base-1 1 +symbols-declared-but-not-shlib libsvn_auth_gnome_keyring-1 1 +symbols-declared-but-not-shlib libsvn_fs_util-1 1 +symbols-declared-but-not-shlib libsvn_auth_kwallet-1 1 +symbols-declared-but-not-shlib libsvn_ra_neon-1 1 +symbols-declared-but-not-shlib libsvn_fs_fs-1 1 +symbols-declared-but-not-shlib libsvn_ra_local-1 1 --- subversion-1.7.9.orig/debian/libsvn1.symbols +++ subversion-1.7.9/debian/libsvn1.symbols @@ -0,0 +1,1372 @@ +libsvn_client-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_client_add2@Base 1.4 + svn_client_add3@Base 1.4 + svn_client_add4@Base 1.5 + svn_client_add@Base 1.4 + svn_client_add_to_changelist@Base 1.5 + svn_client_args_to_target_array2@Base 1.7 + svn_client_args_to_target_array@Base 1.6 + svn_client_blame2@Base 1.4 + svn_client_blame3@Base 1.4 + svn_client_blame4@Base 1.5 + svn_client_blame5@Base 1.7 + svn_client_blame@Base 1.4 + svn_client_cat2@Base 1.4 + svn_client_cat@Base 1.4 + svn_client_checkout2@Base 1.4 + svn_client_checkout3@Base 1.5 + svn_client_checkout@Base 1.4 + svn_client_cleanup@Base 1.4 + svn_client_commit2@Base 1.4 + svn_client_commit3@Base 1.4 + svn_client_commit4@Base 1.5 + svn_client_commit5@Base 1.7 + svn_client_commit@Base 1.4 + svn_client_commit_item2_dup@Base 1.4 + svn_client_commit_item3_create@Base 1.6 + svn_client_commit_item3_dup@Base 1.5 + svn_client_commit_item_create@Base 1.5 + svn_client_copy2@Base 1.4 + svn_client_copy3@Base 1.4 + svn_client_copy4@Base 1.5 + svn_client_copy5@Base 1.6 + svn_client_copy6@Base 1.7 + svn_client_copy@Base 1.4 + svn_client_create_context@Base 1.4 + svn_client_delete2@Base 1.4 + svn_client_delete3@Base 1.5 + svn_client_delete4@Base 1.7 + svn_client_delete@Base 1.4 + svn_client_diff2@Base 1.4 + svn_client_diff3@Base 1.4 + svn_client_diff4@Base 1.5 + svn_client_diff5@Base 1.7 + svn_client_diff@Base 1.4 + svn_client_diff_peg2@Base 1.4 + svn_client_diff_peg3@Base 1.4 + svn_client_diff_peg4@Base 1.5 + svn_client_diff_peg5@Base 1.7 + svn_client_diff_peg@Base 1.4 + svn_client_diff_summarize2@Base 1.5 + svn_client_diff_summarize@Base 1.4 + svn_client_diff_summarize_dup@Base 1.4 + svn_client_diff_summarize_peg2@Base 1.5 + svn_client_diff_summarize_peg@Base 1.4 + svn_client_export2@Base 1.4 + svn_client_export3@Base 1.4 + svn_client_export4@Base 1.5 + svn_client_export5@Base 1.7 + svn_client_export@Base 1.4 + svn_client_get_changelists@Base 1.5 + svn_client_get_simple_prompt_provider@Base 1.4 + svn_client_get_simple_provider@Base 1.4 + svn_client_get_ssl_client_cert_file_provider@Base 1.4 + svn_client_get_ssl_client_cert_prompt_provider@Base 1.4 + svn_client_get_ssl_client_cert_pw_file_provider@Base 1.4 + svn_client_get_ssl_client_cert_pw_prompt_provider@Base 1.4 + svn_client_get_ssl_server_trust_file_provider@Base 1.4 + svn_client_get_ssl_server_trust_prompt_provider@Base 1.4 + svn_client_get_username_prompt_provider@Base 1.4 + svn_client_get_username_provider@Base 1.4 + svn_client_get_wc_root@Base 1.7 + svn_client_import2@Base 1.4 + svn_client_import3@Base 1.5 + svn_client_import4@Base 1.7 + svn_client_import@Base 1.4 + svn_client_info2@Base 1.5 + svn_client_info2_dup@Base 1.7 + svn_client_info3@Base 1.7 + svn_client_info@Base 1.4 + svn_client_list2@Base 1.5 + svn_client_list@Base 1.4 + svn_client_lock@Base 1.4 + svn_client_log2@Base 1.4 + svn_client_log3@Base 1.4 + svn_client_log4@Base 1.5 + svn_client_log5@Base 1.6 + svn_client_log@Base 1.4 + svn_client_ls2@Base 1.4 + svn_client_ls3@Base 1.4 + svn_client_ls@Base 1.4 + svn_client_merge2@Base 1.4 + svn_client_merge3@Base 1.5 + svn_client_merge4@Base 1.7 + svn_client_merge@Base 1.4 + svn_client_merge_peg2@Base 1.4 + svn_client_merge_peg3@Base 1.5 + svn_client_merge_peg4@Base 1.7 + svn_client_merge_peg@Base 1.4 + svn_client_merge_reintegrate@Base 1.5 + svn_client_mergeinfo_get_merged@Base 1.5 + svn_client_mergeinfo_log@Base 1.7 + svn_client_mergeinfo_log_eligible@Base 1.5 + svn_client_mergeinfo_log_merged@Base 1.5 + svn_client_min_max_revisions@Base 1.7 + svn_client_mkdir2@Base 1.4 + svn_client_mkdir3@Base 1.5 + svn_client_mkdir4@Base 1.7 + svn_client_mkdir@Base 1.4 + svn_client_move2@Base 1.4 + svn_client_move3@Base 1.4 + svn_client_move4@Base 1.4 + svn_client_move5@Base 1.5 + svn_client_move6@Base 1.7 + svn_client_move@Base 1.4 + svn_client_open_ra_session@Base 1.4 + svn_client_patch@Base 1.7 + svn_client_propget2@Base 1.4 + svn_client_propget3@Base 1.5 + svn_client_propget4@Base 1.7 + svn_client_propget@Base 1.4 + svn_client_proplist2@Base 1.4 + svn_client_proplist3@Base 1.5 + svn_client_proplist@Base 1.4 + svn_client_proplist_item_dup@Base 1.4 + svn_client_propset2@Base 1.4 + svn_client_propset3@Base 1.5 + svn_client_propset@Base 1.4 + svn_client_propset_local@Base 1.7 + svn_client_propset_remote@Base 1.7 + svn_client_relocate2@Base 1.7 + svn_client_relocate@Base 1.4 + svn_client_remove_from_changelists@Base 1.5 + svn_client_resolve@Base 1.5 + svn_client_resolved@Base 1.4 + svn_client_revert2@Base 1.5 + svn_client_revert@Base 1.4 + svn_client_revprop_get@Base 1.4 + svn_client_revprop_list@Base 1.4 + svn_client_revprop_set2@Base 1.6 + svn_client_revprop_set@Base 1.4 + svn_client_root_url_from_path@Base 1.5 + svn_client_status2@Base 1.4 + svn_client_status3@Base 1.5 + svn_client_status4@Base 1.6 + svn_client_status5@Base 1.7 + svn_client_status@Base 1.4 + svn_client_status_dup@Base 1.7 + svn_client_suggest_merge_sources@Base 1.5 + svn_client_switch2@Base 1.5 + svn_client_switch3@Base 1.7 + svn_client_switch@Base 1.4 + svn_client_unlock@Base 1.4 + svn_client_update2@Base 1.4 + svn_client_update3@Base 1.5 + svn_client_update4@Base 1.7 + svn_client_update@Base 1.4 + svn_client_upgrade@Base 1.7 + svn_client_url_from_path2@Base 1.7 + svn_client_url_from_path@Base 1.4 + svn_client_uuid_from_path2@Base 1.7 + svn_client_uuid_from_path@Base 1.4 + svn_client_uuid_from_url@Base 1.4 + svn_client_version@Base 1.4 + svn_info_dup@Base 1.4 +libsvn_delta-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_compat_wrap_file_rev_handler@Base 1.5 + svn_delta_default_editor@Base 1.4 + svn_delta_depth_filter_editor@Base 1.5 + svn_delta_get_cancellation_editor@Base 1.4 + svn_delta_noop_window_handler@Base 1.4 + svn_delta_path_driver@Base 1.4 + svn_delta_version@Base 1.4 + svn_editor_abort@Base 1.7 + svn_editor_add_absent@Base 1.7 + svn_editor_add_directory@Base 1.7 + svn_editor_add_file@Base 1.7 + svn_editor_add_symlink@Base 1.7 + svn_editor_complete@Base 1.7 + svn_editor_copy@Base 1.7 + svn_editor_create@Base 1.7 + svn_editor_delete@Base 1.7 + svn_editor_move@Base 1.7 + svn_editor_set_props@Base 1.7 + svn_editor_set_target@Base 1.7 + svn_editor_set_text@Base 1.7 + svn_editor_setcb_abort@Base 1.7 + svn_editor_setcb_add_absent@Base 1.7 + svn_editor_setcb_add_directory@Base 1.7 + svn_editor_setcb_add_file@Base 1.7 + svn_editor_setcb_add_symlink@Base 1.7 + svn_editor_setcb_complete@Base 1.7 + svn_editor_setcb_copy@Base 1.7 + svn_editor_setcb_delete@Base 1.7 + svn_editor_setcb_many@Base 1.7 + svn_editor_setcb_move@Base 1.7 + svn_editor_setcb_set_props@Base 1.7 + svn_editor_setcb_set_target@Base 1.7 + svn_editor_setcb_set_text@Base 1.7 + svn_txdelta@Base 1.4 + svn_txdelta_apply@Base 1.4 + svn_txdelta_apply_instructions@Base 1.4 + svn_txdelta_compose_windows@Base 1.4 + svn_txdelta_md5_digest@Base 1.4 + svn_txdelta_next_window@Base 1.4 + svn_txdelta_parse_svndiff@Base 1.4 + svn_txdelta_read_svndiff_window@Base 1.4 + svn_txdelta_run@Base 1.6 + svn_txdelta_send_stream@Base 1.4 + svn_txdelta_send_string@Base 1.4 + svn_txdelta_send_txstream@Base 1.4 + svn_txdelta_skip_svndiff_window@Base 1.4 + svn_txdelta_stream_create@Base 1.4 + svn_txdelta_target_push@Base 1.4 + svn_txdelta_to_svndiff2@Base 1.4 + svn_txdelta_to_svndiff3@Base 1.7 + svn_txdelta_to_svndiff@Base 1.4 + svn_txdelta_window_dup@Base 1.4 +libsvn_diff-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_diff_close_patch_file@Base 1.7 + svn_diff_contains_conflicts@Base 1.4 + svn_diff_contains_diffs@Base 1.4 + svn_diff_diff3@Base 1.4 + svn_diff_diff3_2@Base 1.7 + svn_diff_diff4@Base 1.4 + svn_diff_diff4_2@Base 1.7 + svn_diff_diff@Base 1.4 + svn_diff_diff_2@Base 1.7 + svn_diff_file_diff3@Base 1.4 + svn_diff_file_diff3_2@Base 1.4 + svn_diff_file_diff4@Base 1.4 + svn_diff_file_diff4_2@Base 1.4 + svn_diff_file_diff@Base 1.4 + svn_diff_file_diff_2@Base 1.4 + svn_diff_file_options_create@Base 1.4 + svn_diff_file_options_parse@Base 1.4 + svn_diff_file_output_merge2@Base 1.6 + svn_diff_file_output_merge@Base 1.4 + svn_diff_file_output_unified2@Base 1.4 + svn_diff_file_output_unified3@Base 1.5 + svn_diff_file_output_unified@Base 1.4 + svn_diff_hunk_get_leading_context@Base 1.7 + svn_diff_hunk_get_modified_length@Base 1.7 + svn_diff_hunk_get_modified_start@Base 1.7 + svn_diff_hunk_get_original_length@Base 1.7 + svn_diff_hunk_get_original_start@Base 1.7 + svn_diff_hunk_get_trailing_context@Base 1.7 + svn_diff_hunk_readline_diff_text@Base 1.7 + svn_diff_hunk_readline_modified_text@Base 1.7 + svn_diff_hunk_readline_original_text@Base 1.7 + svn_diff_hunk_reset_diff_text@Base 1.7 + svn_diff_hunk_reset_modified_text@Base 1.7 + svn_diff_hunk_reset_original_text@Base 1.7 + svn_diff_mem_string_diff3@Base 1.5 + svn_diff_mem_string_diff4@Base 1.5 + svn_diff_mem_string_diff@Base 1.5 + svn_diff_mem_string_output_merge2@Base 1.6 + svn_diff_mem_string_output_merge@Base 1.5 + svn_diff_mem_string_output_unified2@Base 1.7 + svn_diff_mem_string_output_unified@Base 1.5 + svn_diff_open_patch_file@Base 1.7 + svn_diff_output@Base 1.4 + svn_diff_parse_next_patch@Base 1.7 + svn_diff_version@Base 1.4 +libsvn_fs-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_fs_abort_txn@Base 1.4 + svn_fs_access_add_lock_token2@Base 1.6 + svn_fs_access_add_lock_token@Base 1.4 + svn_fs_access_get_username@Base 1.4 + svn_fs_apply_text@Base 1.4 + svn_fs_apply_textdelta@Base 1.4 + svn_fs_begin_txn2@Base 1.4 + svn_fs_begin_txn@Base 1.4 + svn_fs_berkeley_logfiles@Base 1.4 + svn_fs_berkeley_path@Base 1.4 + svn_fs_berkeley_recover@Base 1.4 + svn_fs_change_node_prop@Base 1.4 + svn_fs_change_rev_prop2@Base 1.7 + svn_fs_change_rev_prop@Base 1.4 + svn_fs_change_txn_prop@Base 1.4 + svn_fs_change_txn_props@Base 1.5 + svn_fs_check_path@Base 1.4 + svn_fs_check_related@Base 1.4 + svn_fs_close_root@Base 1.4 + svn_fs_closest_copy@Base 1.4 + svn_fs_commit_txn@Base 1.4 + svn_fs_compare_ids@Base 1.4 + svn_fs_contents_changed@Base 1.4 + svn_fs_copied_from@Base 1.4 + svn_fs_copy@Base 1.4 + svn_fs_create@Base 1.4 + svn_fs_create_access@Base 1.4 + svn_fs_create_berkeley@Base 1.4 + svn_fs_delete@Base 1.4 + svn_fs_delete_berkeley@Base 1.4 + svn_fs_delete_fs@Base 1.4 + svn_fs_deltify_revision@Base 1.4 + svn_fs_dir_entries@Base 1.4 + svn_fs_file_checksum@Base 1.6 + svn_fs_file_contents@Base 1.4 + svn_fs_file_length@Base 1.4 + svn_fs_file_md5_checksum@Base 1.4 + svn_fs_generate_lock_token@Base 1.4 + svn_fs_get_access@Base 1.4 + svn_fs_get_file_delta_stream@Base 1.4 + svn_fs_get_lock@Base 1.4 + svn_fs_get_locks2@Base 1.7 + svn_fs_get_locks@Base 1.4 + svn_fs_get_mergeinfo@Base 1.5 + svn_fs_get_uuid@Base 1.4 + svn_fs_history_location@Base 1.4 + svn_fs_history_prev@Base 1.4 + svn_fs_hotcopy@Base 1.4 + svn_fs_hotcopy_berkeley@Base 1.4 + svn_fs_initialize@Base 1.4 + svn_fs_is_dir@Base 1.4 + svn_fs_is_file@Base 1.4 + svn_fs_is_revision_root@Base 1.4 + svn_fs_is_txn_root@Base 1.4 + svn_fs_list_transactions@Base 1.4 + svn_fs_lock@Base 1.4 + svn_fs_make_dir@Base 1.4 + svn_fs_make_file@Base 1.4 + svn_fs_merge@Base 1.4 + svn_fs_new@Base 1.4 + svn_fs_node_created_path@Base 1.4 + svn_fs_node_created_rev@Base 1.4 + svn_fs_node_history@Base 1.4 + svn_fs_node_id@Base 1.4 + svn_fs_node_origin_rev@Base 1.5 + svn_fs_node_prop@Base 1.4 + svn_fs_node_proplist@Base 1.4 + svn_fs_open@Base 1.4 + svn_fs_open_berkeley@Base 1.4 + svn_fs_open_txn@Base 1.4 + svn_fs_pack@Base 1.6 + svn_fs_parse_id@Base 1.4 + svn_fs_path@Base 1.4 + svn_fs_path_change2_create@Base 1.6 + svn_fs_paths_changed2@Base 1.6 + svn_fs_paths_changed@Base 1.4 + svn_fs_print_modules@Base 1.4 + svn_fs_props_changed@Base 1.4 + svn_fs_purge_txn@Base 1.4 + svn_fs_recover@Base 1.5 + svn_fs_revision_link@Base 1.4 + svn_fs_revision_prop@Base 1.4 + svn_fs_revision_proplist@Base 1.4 + svn_fs_revision_root@Base 1.4 + svn_fs_revision_root_revision@Base 1.4 + svn_fs_root_fs@Base 1.4 + svn_fs_set_access@Base 1.4 + svn_fs_set_berkeley_errcall@Base 1.4 + svn_fs_set_uuid@Base 1.4 + svn_fs_set_warning_func@Base 1.4 + svn_fs_txn_base_revision@Base 1.4 + svn_fs_txn_name@Base 1.4 + svn_fs_txn_prop@Base 1.4 + svn_fs_txn_proplist@Base 1.4 + svn_fs_txn_root@Base 1.4 + svn_fs_txn_root_base_revision@Base 1.5 + svn_fs_txn_root_name@Base 1.4 + svn_fs_type@Base 1.4 + svn_fs_unlock@Base 1.4 + svn_fs_unparse_id@Base 1.4 + svn_fs_upgrade@Base 1.5 + svn_fs_version@Base 1.4 + svn_fs_youngest_rev@Base 1.4 +libsvn_ra-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_ra_change_rev_prop2@Base 1.7 + svn_ra_change_rev_prop@Base 1.4 + svn_ra_check_path@Base 1.4 + svn_ra_create_callbacks@Base 1.4 + svn_ra_do_diff2@Base 1.4 + svn_ra_do_diff3@Base 1.5 + svn_ra_do_diff@Base 1.4 + svn_ra_do_status2@Base 1.5 + svn_ra_do_status@Base 1.4 + svn_ra_do_switch2@Base 1.5 + svn_ra_do_switch@Base 1.4 + svn_ra_do_update2@Base 1.5 + svn_ra_do_update@Base 1.4 + svn_ra_get_commit_editor2@Base 1.4 + svn_ra_get_commit_editor3@Base 1.5 + svn_ra_get_commit_editor@Base 1.4 + svn_ra_get_dated_revision@Base 1.4 + svn_ra_get_deleted_rev@Base 1.6 + svn_ra_get_dir2@Base 1.4 + svn_ra_get_dir@Base 1.4 + svn_ra_get_file@Base 1.4 + svn_ra_get_file_revs2@Base 1.5 + svn_ra_get_file_revs@Base 1.4 + svn_ra_get_latest_revnum@Base 1.4 + svn_ra_get_location_segments@Base 1.5 + svn_ra_get_locations@Base 1.4 + svn_ra_get_lock@Base 1.4 + svn_ra_get_locks2@Base 1.7 + svn_ra_get_locks@Base 1.4 + svn_ra_get_log2@Base 1.5 + svn_ra_get_log@Base 1.4 + svn_ra_get_mergeinfo@Base 1.5 + svn_ra_get_path_relative_to_root@Base 1.7 + svn_ra_get_path_relative_to_session@Base 1.7 + svn_ra_get_ra_library@Base 1.4 + svn_ra_get_repos_root2@Base 1.5 + svn_ra_get_repos_root@Base 1.4 + svn_ra_get_session_url@Base 1.5 + svn_ra_get_uuid2@Base 1.5 + svn_ra_get_uuid@Base 1.4 + svn_ra_has_capability@Base 1.5 + svn_ra_init_ra_libs@Base 1.4 + svn_ra_initialize@Base 1.4 + svn_ra_lock@Base 1.4 + svn_ra_open2@Base 1.4 + svn_ra_open3@Base 1.5 + svn_ra_open4@Base 1.7 + svn_ra_open@Base 1.4 + svn_ra_print_modules@Base 1.4 + svn_ra_print_ra_libraries@Base 1.4 + svn_ra_reparent@Base 1.4 + svn_ra_replay@Base 1.4 + svn_ra_replay_range@Base 1.5 + svn_ra_rev_prop@Base 1.4 + svn_ra_rev_proplist@Base 1.4 + svn_ra_stat@Base 1.4 + svn_ra_unlock@Base 1.4 + svn_ra_version@Base 1.4 +libsvn_ra_svn-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_ra_svn_compression_level@Base 1.7 + svn_ra_svn_conn_remote_host@Base 1.6 + svn_ra_svn_cram_server@Base 1.4 + svn_ra_svn_create_conn2@Base 1.7 + svn_ra_svn_create_conn@Base 1.4 + svn_ra_svn_drive_editor2@Base 1.4 + svn_ra_svn_drive_editor@Base 1.4 + svn_ra_svn_end_list@Base 1.4 + svn_ra_svn_flush@Base 1.4 + svn_ra_svn_get_editor@Base 1.4 + svn_ra_svn_handle_commands2@Base 1.6 + svn_ra_svn_handle_commands@Base 1.4 + svn_ra_svn_has_capability@Base 1.4 + svn_ra_svn_init@Base 1.4 + svn_ra_svn_parse_proplist@Base 1.5 + svn_ra_svn_parse_tuple@Base 1.4 + svn_ra_svn_read_cmd_response@Base 1.4 + svn_ra_svn_read_item@Base 1.4 + svn_ra_svn_read_tuple@Base 1.4 + svn_ra_svn_set_capabilities@Base 1.4 + svn_ra_svn_skip_leading_garbage@Base 1.4 + svn_ra_svn_start_list@Base 1.4 + svn_ra_svn_version@Base 1.4 + svn_ra_svn_write_cmd@Base 1.4 + svn_ra_svn_write_cmd_failure@Base 1.4 + svn_ra_svn_write_cmd_response@Base 1.4 + svn_ra_svn_write_cstring@Base 1.4 + svn_ra_svn_write_number@Base 1.4 + svn_ra_svn_write_proplist@Base 1.5 + svn_ra_svn_write_string@Base 1.4 + svn_ra_svn_write_tuple@Base 1.4 + svn_ra_svn_write_word@Base 1.4 +libsvn_repos-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_repos_abort_report@Base 1.4 + svn_repos_authz_check_access@Base 1.4 + svn_repos_authz_read@Base 1.4 + svn_repos_begin_report2@Base 1.5 + svn_repos_begin_report@Base 1.4 + svn_repos_check_revision_access@Base 1.5 + svn_repos_conf_dir@Base 1.4 + svn_repos_create@Base 1.4 + svn_repos_dated_revision@Base 1.4 + svn_repos_db_env@Base 1.4 + svn_repos_db_lockfile@Base 1.4 + svn_repos_db_logfiles@Base 1.4 + svn_repos_db_logs_lockfile@Base 1.4 + svn_repos_delete@Base 1.4 + svn_repos_delete_path@Base 1.4 + svn_repos_deleted_rev@Base 1.5 + svn_repos_dir_delta2@Base 1.5 + svn_repos_dir_delta@Base 1.4 + svn_repos_dump_fs2@Base 1.4 + svn_repos_dump_fs3@Base 1.7 + svn_repos_dump_fs@Base 1.4 + svn_repos_find_root_path@Base 1.4 + svn_repos_finish_report@Base 1.4 + svn_repos_fs@Base 1.4 + svn_repos_fs_begin_txn_for_commit2@Base 1.5 + svn_repos_fs_begin_txn_for_commit@Base 1.4 + svn_repos_fs_begin_txn_for_update@Base 1.4 + svn_repos_fs_change_node_prop@Base 1.4 + svn_repos_fs_change_rev_prop2@Base 1.4 + svn_repos_fs_change_rev_prop3@Base 1.5 + svn_repos_fs_change_rev_prop4@Base 1.7 + svn_repos_fs_change_rev_prop@Base 1.4 + svn_repos_fs_change_txn_prop@Base 1.4 + svn_repos_fs_change_txn_props@Base 1.5 + svn_repos_fs_commit_txn@Base 1.4 + svn_repos_fs_get_locks2@Base 1.7 + svn_repos_fs_get_locks@Base 1.4 + svn_repos_fs_get_mergeinfo@Base 1.5 + svn_repos_fs_lock@Base 1.4 + svn_repos_fs_pack2@Base 1.7 + svn_repos_fs_pack@Base 1.6 + svn_repos_fs_revision_prop@Base 1.4 + svn_repos_fs_revision_proplist@Base 1.4 + svn_repos_fs_unlock@Base 1.4 + svn_repos_get_commit_editor2@Base 1.4 + svn_repos_get_commit_editor3@Base 1.4 + svn_repos_get_commit_editor4@Base 1.4 + svn_repos_get_commit_editor5@Base 1.5 + svn_repos_get_commit_editor@Base 1.4 + svn_repos_get_committed_info@Base 1.4 + svn_repos_get_file_revs2@Base 1.5 + svn_repos_get_file_revs@Base 1.4 + svn_repos_get_fs_build_parser2@Base 1.4 + svn_repos_get_fs_build_parser3@Base 1.7 + svn_repos_get_fs_build_parser@Base 1.4 + svn_repos_get_logs2@Base 1.4 + svn_repos_get_logs3@Base 1.4 + svn_repos_get_logs4@Base 1.5 + svn_repos_get_logs@Base 1.4 + svn_repos_has_capability@Base 1.5 + svn_repos_history2@Base 1.4 + svn_repos_history@Base 1.4 + svn_repos_hook_dir@Base 1.4 + svn_repos_hotcopy@Base 1.4 + svn_repos_link_path2@Base 1.4 + svn_repos_link_path3@Base 1.5 + svn_repos_link_path@Base 1.4 + svn_repos_load_fs2@Base 1.4 + svn_repos_load_fs3@Base 1.7 + svn_repos_load_fs@Base 1.4 + svn_repos_lock_dir@Base 1.4 + svn_repos_node_editor@Base 1.4 + svn_repos_node_from_baton@Base 1.4 + svn_repos_node_location_segments@Base 1.5 + svn_repos_notify_create@Base 1.7 + svn_repos_open2@Base 1.7 + svn_repos_open@Base 1.4 + svn_repos_parse_dumpstream2@Base 1.4 + svn_repos_parse_dumpstream@Base 1.4 + svn_repos_path@Base 1.4 + svn_repos_post_commit_hook@Base 1.4 + svn_repos_post_lock_hook@Base 1.4 + svn_repos_post_revprop_change_hook@Base 1.4 + svn_repos_post_unlock_hook@Base 1.4 + svn_repos_pre_commit_hook@Base 1.4 + svn_repos_pre_lock_hook@Base 1.4 + svn_repos_pre_revprop_change_hook@Base 1.4 + svn_repos_pre_unlock_hook@Base 1.4 + svn_repos_recover2@Base 1.4 + svn_repos_recover3@Base 1.5 + svn_repos_recover4@Base 1.7 + svn_repos_recover@Base 1.4 + svn_repos_remember_client_capabilities@Base 1.5 + svn_repos_replay2@Base 1.4 + svn_repos_replay@Base 1.4 + svn_repos_set_path2@Base 1.4 + svn_repos_set_path3@Base 1.5 + svn_repos_set_path@Base 1.4 + svn_repos_start_commit_hook@Base 1.4 + svn_repos_stat@Base 1.4 + svn_repos_svnserve_conf@Base 1.4 + svn_repos_trace_node_locations@Base 1.4 + svn_repos_upgrade2@Base 1.7 + svn_repos_upgrade@Base 1.5 + svn_repos_verify_fs2@Base 1.7 + svn_repos_verify_fs@Base 1.5 + svn_repos_version@Base 1.4 +libsvn_subr-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_auth_first_credentials@Base 1.4 + svn_auth_get_parameter@Base 1.4 + svn_auth_get_platform_specific_client_providers@Base 1.6 + svn_auth_get_platform_specific_provider@Base 1.6 + svn_auth_get_simple_prompt_provider@Base 1.4 + svn_auth_get_simple_provider2@Base 1.6 + svn_auth_get_simple_provider@Base 1.4 + svn_auth_get_ssl_client_cert_file_provider@Base 1.4 + svn_auth_get_ssl_client_cert_prompt_provider@Base 1.4 + svn_auth_get_ssl_client_cert_pw_file_provider2@Base 1.6 + svn_auth_get_ssl_client_cert_pw_file_provider@Base 1.4 + svn_auth_get_ssl_client_cert_pw_prompt_provider@Base 1.4 + svn_auth_get_ssl_server_trust_file_provider@Base 1.4 + svn_auth_get_ssl_server_trust_prompt_provider@Base 1.4 + svn_auth_get_username_prompt_provider@Base 1.4 + svn_auth_get_username_provider@Base 1.4 + svn_auth_next_credentials@Base 1.4 + svn_auth_open@Base 1.4 + svn_auth_save_credentials@Base 1.4 + svn_auth_set_parameter@Base 1.4 + svn_auth_ssl_server_cert_info_dup@Base 1.4 + svn_base64_decode@Base 1.4 + svn_base64_decode_string@Base 1.4 + svn_base64_encode@Base 1.4 + svn_base64_encode_string2@Base 1.6 + svn_base64_encode_string@Base 1.4 + svn_base64_from_md5@Base 1.4 + svn_cache_config_get@Base 1.7 + svn_cache_config_set@Base 1.7 + svn_categorize_props@Base 1.4 + svn_checksum@Base 1.6 + svn_checksum_clear@Base 1.6 + svn_checksum_create@Base 1.6 + svn_checksum_ctx_create@Base 1.6 + svn_checksum_deserialize@Base 1.7 + svn_checksum_dup@Base 1.6 + svn_checksum_empty_checksum@Base 1.6 + svn_checksum_final@Base 1.6 + svn_checksum_match@Base 1.6 + svn_checksum_mismatch_err@Base 1.7 + svn_checksum_parse_hex@Base 1.6 + svn_checksum_serialize@Base 1.7 + svn_checksum_size@Base 1.6 + svn_checksum_to_cstring@Base 1.6 + svn_checksum_to_cstring_display@Base 1.6 + svn_checksum_update@Base 1.6 + svn_cmdline_auth_plaintext_passphrase_prompt@Base 1.6 + svn_cmdline_auth_plaintext_prompt@Base 1.6 + svn_cmdline_auth_simple_prompt@Base 1.4 + svn_cmdline_auth_ssl_client_cert_prompt@Base 1.4 + svn_cmdline_auth_ssl_client_cert_pw_prompt@Base 1.4 + svn_cmdline_auth_ssl_server_trust_prompt@Base 1.4 + svn_cmdline_auth_username_prompt@Base 1.4 + svn_cmdline_create_auth_baton@Base 1.6 + svn_cmdline_cstring_from_utf8@Base 1.4 + svn_cmdline_cstring_from_utf8_fuzzy@Base 1.4 + svn_cmdline_cstring_to_utf8@Base 1.4 + svn_cmdline_fflush@Base 1.4 + svn_cmdline_fprintf@Base 1.4 + svn_cmdline_fputs@Base 1.4 + svn_cmdline_handle_exit_error@Base 1.4 + svn_cmdline_init@Base 1.4 + svn_cmdline_output_encoding@Base 1.4 + svn_cmdline_path_local_style_from_utf8@Base 1.4 + svn_cmdline_printf@Base 1.4 + svn_cmdline_prompt_user2@Base 1.5 + svn_cmdline_prompt_user@Base 1.4 + svn_cmdline_setup_auth_baton@Base 1.4 + svn_commit_info_dup@Base 1.4 + svn_compat_log_revprops_clear@Base 1.5 + svn_compat_log_revprops_in@Base 1.5 + svn_compat_log_revprops_out@Base 1.5 + svn_compat_wrap_commit_callback@Base 1.4 + svn_compat_wrap_log_receiver@Base 1.5 + svn_config_create@Base 1.7 + svn_config_ensure@Base 1.4 + svn_config_enumerate2@Base 1.4 + svn_config_enumerate@Base 1.4 + svn_config_enumerate_sections2@Base 1.4 + svn_config_enumerate_sections@Base 1.4 + svn_config_find_group@Base 1.4 + svn_config_get@Base 1.4 + svn_config_get_bool@Base 1.4 + svn_config_get_config@Base 1.4 + svn_config_get_server_setting@Base 1.4 + svn_config_get_server_setting_bool@Base 1.6 + svn_config_get_server_setting_int@Base 1.4 + svn_config_get_user_config_path@Base 1.6 + svn_config_get_yes_no_ask@Base 1.6 + svn_config_has_section@Base 1.4 + svn_config_merge@Base 1.4 + svn_config_read2@Base 1.7 + svn_config_read@Base 1.4 + svn_config_read_auth_data@Base 1.4 + svn_config_set@Base 1.4 + svn_config_set_bool@Base 1.4 + svn_config_write_auth_data@Base 1.4 + svn_create_commit_info@Base 1.4 + svn_cstring_atoi64@Base 1.7 + svn_cstring_atoi@Base 1.7 + svn_cstring_atoui64@Base 1.7 + svn_cstring_atoui@Base 1.7 + svn_cstring_casecmp@Base 1.5 + svn_cstring_count_newlines@Base 1.4 + svn_cstring_join@Base 1.4 + svn_cstring_match_glob_list@Base 1.4 + svn_cstring_match_list@Base 1.7 + svn_cstring_split@Base 1.4 + svn_cstring_split_append@Base 1.4 + svn_cstring_strtoi64@Base 1.7 + svn_cstring_strtoui64@Base 1.7 + svn_ctype_casecmp@Base 1.5 + svn_ctype_table@Base 1.4 + svn_ctype_table_internal@Base 1.5 + svn_depth_from_word@Base 1.5 + svn_depth_to_word@Base 1.5 + svn_dirent_basename@Base 1.7 + svn_dirent_canonicalize@Base 1.6 + svn_dirent_condense_targets@Base 1.7 + svn_dirent_dirname@Base 1.6 + svn_dirent_dup@Base 1.4 + svn_dirent_get_absolute@Base 1.6 + svn_dirent_get_longest_ancestor@Base 1.6 + svn_dirent_internal_style@Base 1.6 + svn_dirent_is_absolute@Base 1.6 + svn_dirent_is_ancestor@Base 1.6 + svn_dirent_is_canonical@Base 1.6 + svn_dirent_is_child@Base 1.6 + svn_dirent_is_root@Base 1.5 + svn_dirent_is_under_root@Base 1.7 + svn_dirent_join@Base 1.6 + svn_dirent_join_many@Base 1.6 + svn_dirent_local_style@Base 1.6 + svn_dirent_skip_ancestor@Base 1.7 + svn_dirent_split@Base 1.7 + svn_dso_initialize2@Base 1.6 + svn_dso_initialize@Base 1.4 + svn_dso_load@Base 1.4 + svn_err_best_message@Base 1.4 + svn_error__locate@Base 1.0 + svn_error_abort_on_malfunction@Base 1.6 + svn_error_clear@Base 1.4 + svn_error_compose@Base 1.4 + svn_error_compose_create@Base 1.6 + svn_error_create@Base 1.4 + svn_error_createf@Base 1.4 + svn_error_dup@Base 1.4 + svn_error_find_cause@Base 1.7 + svn_error_purge_tracing@Base 1.7 + svn_error_quick_wrap@Base 1.4 + svn_error_raise_on_malfunction@Base 1.6 + svn_error_root_cause@Base 1.5 + svn_error_set_malfunction_handler@Base 1.6 + svn_error_wrap_apr@Base 1.4 + svn_handle_error2@Base 1.4 + svn_handle_error@Base 1.4 + svn_handle_warning2@Base 1.4 + svn_handle_warning@Base 1.4 + svn_hash_diff@Base 1.4 + svn_hash_from_cstring_keys@Base 1.5 + svn_hash_keys@Base 1.5 + svn_hash_read2@Base 1.4 + svn_hash_read@Base 1.4 + svn_hash_read_incremental@Base 1.4 + svn_hash_write2@Base 1.4 + svn_hash_write@Base 1.4 + svn_hash_write_incremental@Base 1.4 + svn_inheritance_from_word@Base 1.5 + svn_inheritance_to_word@Base 1.5 + svn_io_append_file@Base 1.4 + svn_io_check_path@Base 1.4 + svn_io_check_resolved_path@Base 1.4 + svn_io_check_special_path@Base 1.4 + svn_io_copy_dir_recursively@Base 1.4 + svn_io_copy_file@Base 1.4 + svn_io_copy_link@Base 1.4 + svn_io_copy_perms@Base 1.6 + svn_io_create_unique_link@Base 1.4 + svn_io_detect_mimetype2@Base 1.5 + svn_io_detect_mimetype@Base 1.4 + svn_io_dir_close@Base 1.7 + svn_io_dir_empty@Base 1.4 + svn_io_dir_file_copy@Base 1.4 + svn_io_dir_make@Base 1.4 + svn_io_dir_make_hidden@Base 1.4 + svn_io_dir_make_sgid@Base 1.4 + svn_io_dir_open@Base 1.4 + svn_io_dir_read@Base 1.4 + svn_io_dir_remove_nonrecursive@Base 1.4 + svn_io_dir_walk2@Base 1.7 + svn_io_dir_walk@Base 1.4 + svn_io_dirent2_create@Base 1.7 + svn_io_dirent2_dup@Base 1.7 + svn_io_file_affected_time@Base 1.4 + svn_io_file_checksum2@Base 1.6 + svn_io_file_checksum@Base 1.4 + svn_io_file_close@Base 1.4 + svn_io_file_create@Base 1.4 + svn_io_file_flush_to_disk@Base 1.4 + svn_io_file_getc@Base 1.4 + svn_io_file_info_get@Base 1.4 + svn_io_file_lock2@Base 1.4 + svn_io_file_lock@Base 1.4 + svn_io_file_move@Base 1.4 + svn_io_file_name_get@Base 1.7 + svn_io_file_open@Base 1.4 + svn_io_file_putc@Base 1.7 + svn_io_file_read@Base 1.4 + svn_io_file_read_full2@Base 1.7 + svn_io_file_read_full@Base 1.4 + svn_io_file_rename@Base 1.4 + svn_io_file_seek@Base 1.4 + svn_io_file_trunc@Base 1.6 + svn_io_file_write@Base 1.4 + svn_io_file_write_full@Base 1.4 + svn_io_files_contents_same_p@Base 1.4 + svn_io_filesizes_different_p@Base 1.4 + svn_io_get_dir_filenames@Base 1.4 + svn_io_get_dirents2@Base 1.4 + svn_io_get_dirents3@Base 1.7 + svn_io_get_dirents@Base 1.4 + svn_io_is_binary_data@Base 1.7 + svn_io_is_file_executable@Base 1.4 + svn_io_make_dir_recursively@Base 1.4 + svn_io_open_unique_file2@Base 1.4 + svn_io_open_unique_file3@Base 1.6 + svn_io_open_unique_file@Base 1.4 + svn_io_open_uniquely_named@Base 1.6 + svn_io_parse_mimetypes_file@Base 1.5 + svn_io_read_length_line@Base 1.4 + svn_io_read_link@Base 1.4 + svn_io_read_version_file@Base 1.4 + svn_io_remove_dir2@Base 1.5 + svn_io_remove_dir@Base 1.4 + svn_io_remove_file2@Base 1.7 + svn_io_remove_file@Base 1.4 + svn_io_run_cmd@Base 1.4 + svn_io_run_diff2@Base 1.6 + svn_io_run_diff3@Base 1.4 + svn_io_run_diff3_2@Base 1.4 + svn_io_run_diff3_3@Base 1.6 + svn_io_run_diff@Base 1.4 + svn_io_set_file_affected_time@Base 1.4 + svn_io_set_file_executable@Base 1.4 + svn_io_set_file_read_only@Base 1.4 + svn_io_set_file_read_write@Base 1.4 + svn_io_set_file_read_write_carefully@Base 1.4 + svn_io_sleep_for_timestamps@Base 1.6 + svn_io_start_cmd2@Base 1.7 + svn_io_start_cmd@Base 1.4 + svn_io_stat@Base 1.4 + svn_io_stat_dirent@Base 1.7 + svn_io_temp_dir@Base 1.4 + svn_io_wait_for_cmd@Base 1.4 + svn_io_write_unique@Base 1.6 + svn_io_write_version_file@Base 1.4 + svn_iter__break@Base 1.5 + svn_iter_apr_array@Base 1.5 + svn_iter_apr_hash@Base 1.5 + svn_location_segment_dup@Base 1.5 + svn_lock_create@Base 1.4 + svn_lock_dup@Base 1.4 + svn_log_changed_path2_create@Base 1.6 + svn_log_changed_path2_dup@Base 1.6 + svn_log_changed_path_dup@Base 1.4 + svn_log_entry_create@Base 1.5 + svn_log_entry_dup@Base 1.6 + svn_md5_digest_to_cstring@Base 1.4 + svn_md5_digest_to_cstring_display@Base 1.4 + svn_md5_digests_match@Base 1.4 + svn_md5_empty_string_digest@Base 1.4 + svn_merge_range_contains_rev@Base 1.5 + svn_merge_range_dup@Base 1.5 + svn_mergeinfo_catalog_dup@Base 1.6 + svn_mergeinfo_catalog_merge@Base 1.7 + svn_mergeinfo_diff@Base 1.5 + svn_mergeinfo_dup@Base 1.5 + svn_mergeinfo_inheritable2@Base 1.7 + svn_mergeinfo_inheritable@Base 1.5 + svn_mergeinfo_intersect2@Base 1.7 + svn_mergeinfo_intersect@Base 1.5 + svn_mergeinfo_merge@Base 1.5 + svn_mergeinfo_parse@Base 1.5 + svn_mergeinfo_remove2@Base 1.7 + svn_mergeinfo_remove@Base 1.5 + svn_mergeinfo_sort@Base 1.5 + svn_mergeinfo_to_string@Base 1.5 + svn_mime_type_is_binary@Base 1.4 + svn_mime_type_validate@Base 1.4 + svn_nls_init@Base 1.4 + svn_node_kind_from_word@Base 1.6 + svn_node_kind_to_word@Base 1.6 + svn_opt_args_to_target_array2@Base 1.4 + svn_opt_args_to_target_array3@Base 1.5 + svn_opt_args_to_target_array@Base 1.4 + svn_opt_format_option@Base 1.4 + svn_opt_get_canonical_subcommand2@Base 1.4 + svn_opt_get_canonical_subcommand@Base 1.4 + svn_opt_get_option_from_code2@Base 1.4 + svn_opt_get_option_from_code@Base 1.4 + svn_opt_parse_all_args@Base 1.4 + svn_opt_parse_num_args@Base 1.4 + svn_opt_parse_path@Base 1.4 + svn_opt_parse_revision@Base 1.4 + svn_opt_parse_revision_to_range@Base 1.5 + svn_opt_parse_revprop@Base 1.6 + svn_opt_print_generic_help2@Base 1.4 + svn_opt_print_generic_help@Base 1.4 + svn_opt_print_help2@Base 1.4 + svn_opt_print_help3@Base 1.5 + svn_opt_print_help@Base 1.4 + svn_opt_push_implicit_dot_target@Base 1.4 + svn_opt_resolve_revisions@Base 1.5 + svn_opt_subcommand_help2@Base 1.4 + svn_opt_subcommand_help3@Base 1.5 + svn_opt_subcommand_help@Base 1.4 + svn_opt_subcommand_takes_option2@Base 1.4 + svn_opt_subcommand_takes_option3@Base 1.5 + svn_opt_subcommand_takes_option@Base 1.4 + svn_parse_date@Base 1.4 + svn_path_add_component@Base 1.4 + svn_path_basename@Base 1.4 + svn_path_canonicalize@Base 1.4 + svn_path_check_valid@Base 1.4 + svn_path_compare_paths@Base 1.4 + svn_path_component_count@Base 1.4 + svn_path_compose@Base 1.5 + svn_path_condense_targets@Base 1.4 + svn_path_cstring_from_utf8@Base 1.4 + svn_path_cstring_to_utf8@Base 1.4 + svn_path_decompose@Base 1.4 + svn_path_dirname@Base 1.4 + svn_path_get_absolute@Base 1.4 + svn_path_get_longest_ancestor@Base 1.4 + svn_path_internal_style@Base 1.4 + svn_path_is_ancestor@Base 1.4 + svn_path_is_backpath_present@Base 1.4 + svn_path_is_canonical@Base 1.5 + svn_path_is_child@Base 1.4 + svn_path_is_dotpath_present@Base 1.6 + svn_path_is_empty@Base 1.4 + svn_path_is_single_path_component@Base 1.4 + svn_path_is_uri_safe@Base 1.4 + svn_path_is_url@Base 1.4 + svn_path_join@Base 1.4 + svn_path_join_many@Base 1.4 + svn_path_local_style@Base 1.4 + svn_path_remove_component@Base 1.4 + svn_path_remove_components@Base 1.4 + svn_path_remove_redundancies@Base 1.4 + svn_path_split@Base 1.4 + svn_path_split_if_file@Base 1.4 + svn_path_splitext@Base 1.5 + svn_path_uri_autoescape@Base 1.4 + svn_path_uri_decode@Base 1.4 + svn_path_uri_encode@Base 1.4 + svn_path_uri_from_iri@Base 1.4 + svn_path_url_add_component2@Base 1.6 + svn_path_url_add_component@Base 1.4 + svn_pool_create_ex@Base 1.4 + svn_pool_create_ex_debug@Base 1.4 + svn_prop_array_dup@Base 1.4 + svn_prop_array_to_hash@Base 1.7 + svn_prop_diffs@Base 1.4 + svn_prop_dup@Base 1.4 + svn_prop_get_value@Base 1.7 + svn_prop_has_svn_prop@Base 1.5 + svn_prop_hash_dup@Base 1.6 + svn_prop_hash_to_array@Base 1.5 + svn_prop_is_boolean@Base 1.5 + svn_prop_is_svn_prop@Base 1.4 + svn_prop_name_is_valid@Base 1.5 + svn_prop_needs_translation@Base 1.4 + svn_property_kind@Base 1.4 + svn_quoprint_decode@Base 1.4 + svn_quoprint_decode_string@Base 1.4 + svn_quoprint_encode@Base 1.4 + svn_quoprint_encode_string@Base 1.4 + svn_rangelist_diff@Base 1.5 + svn_rangelist_dup@Base 1.5 + svn_rangelist_inheritable2@Base 1.7 + svn_rangelist_inheritable@Base 1.5 + svn_rangelist_intersect@Base 1.5 + svn_rangelist_merge@Base 1.5 + svn_rangelist_remove@Base 1.5 + svn_rangelist_reverse@Base 1.5 + svn_rangelist_to_string@Base 1.5 + svn_relpath_basename@Base 1.7 + svn_relpath_canonicalize@Base 1.7 + svn_relpath_dirname@Base 1.7 + svn_relpath_get_longest_ancestor@Base 1.7 + svn_relpath_is_canonical@Base 1.7 + svn_relpath_join@Base 1.7 + svn_relpath_skip_ancestor@Base 1.7 + svn_relpath_split@Base 1.7 + svn_revnum_parse@Base 1.5 + svn_sleep_for_timestamps@Base 1.4 +# FIXME: rapidsvn needs svn_sort__hash, but shouldn't. #607544 + svn_sort__hash@Base 1.0 + svn_sort_compare_items_as_paths@Base 1.4 + svn_sort_compare_items_lexically@Base 1.4 + svn_sort_compare_paths@Base 1.4 + svn_sort_compare_ranges@Base 1.5 + svn_sort_compare_revisions@Base 1.4 + svn_stream_checksummed2@Base 1.6 + svn_stream_checksummed@Base 1.4 + svn_stream_close@Base 1.4 + svn_stream_compressed@Base 1.4 + svn_stream_contents_same2@Base 1.7 + svn_stream_contents_same@Base 1.4 + svn_stream_copy2@Base 1.5 + svn_stream_copy3@Base 1.6 + svn_stream_copy@Base 1.4 + svn_stream_create@Base 1.4 + svn_stream_disown@Base 1.4 + svn_stream_empty@Base 1.4 + svn_stream_for_stderr@Base 1.7 + svn_stream_for_stdin@Base 1.7 + svn_stream_for_stdout@Base 1.4 + svn_stream_from_aprfile2@Base 1.4 + svn_stream_from_aprfile@Base 1.4 + svn_stream_from_string@Base 1.6 + svn_stream_from_stringbuf@Base 1.4 + svn_stream_mark@Base 1.7 + svn_stream_open_readonly@Base 1.6 + svn_stream_open_unique@Base 1.6 + svn_stream_open_writable@Base 1.6 + svn_stream_printf@Base 1.4 + svn_stream_printf_from_utf8@Base 1.4 + svn_stream_read@Base 1.4 + svn_stream_readline@Base 1.4 + svn_stream_reset@Base 1.7 + svn_stream_seek@Base 1.7 + svn_stream_set_baton@Base 1.4 + svn_stream_set_close@Base 1.4 + svn_stream_set_mark@Base 1.7 + svn_stream_set_read@Base 1.4 + svn_stream_set_seek@Base 1.7 + svn_stream_set_skip@Base 1.7 + svn_stream_set_write@Base 1.4 + svn_stream_skip@Base 1.7 + svn_stream_supports_mark@Base 1.7 + svn_stream_tee@Base 1.7 + svn_stream_write@Base 1.4 + svn_strerror@Base 1.4 + svn_string_compare@Base 1.4 + svn_string_compare_stringbuf@Base 1.4 + svn_string_create@Base 1.4 + svn_string_create_from_buf@Base 1.4 + svn_string_createf@Base 1.4 + svn_string_createv@Base 1.4 + svn_string_dup@Base 1.4 + svn_string_find_char_backward@Base 1.4 + svn_string_first_non_whitespace@Base 1.4 + svn_string_from_stream@Base 1.6 + svn_string_isempty@Base 1.4 + svn_string_ncreate@Base 1.4 + svn_stringbuf_appendbyte@Base 1.7 + svn_stringbuf_appendbytes@Base 1.4 + svn_stringbuf_appendcstr@Base 1.4 + svn_stringbuf_appendstr@Base 1.4 + svn_stringbuf_chop@Base 1.4 + svn_stringbuf_compare@Base 1.4 + svn_stringbuf_create@Base 1.4 + svn_stringbuf_create_ensure@Base 1.6 + svn_stringbuf_create_from_string@Base 1.4 + svn_stringbuf_createf@Base 1.4 + svn_stringbuf_createv@Base 1.4 + svn_stringbuf_dup@Base 1.4 + svn_stringbuf_ensure@Base 1.4 + svn_stringbuf_fillchar@Base 1.4 + svn_stringbuf_find_char_backward@Base 1.4 + svn_stringbuf_first_non_whitespace@Base 1.4 + svn_stringbuf_from_aprfile@Base 1.4 + svn_stringbuf_from_file2@Base 1.5 + svn_stringbuf_from_file@Base 1.4 + svn_stringbuf_isempty@Base 1.4 + svn_stringbuf_ncreate@Base 1.4 + svn_stringbuf_set@Base 1.4 + svn_stringbuf_setempty@Base 1.4 + svn_stringbuf_strip_whitespace@Base 1.4 + svn_subr_version@Base 1.4 + svn_subst_build_keywords2@Base 1.4 + svn_subst_build_keywords@Base 1.4 + svn_subst_copy_and_translate2@Base 1.4 + svn_subst_copy_and_translate3@Base 1.4 + svn_subst_copy_and_translate4@Base 1.7 + svn_subst_copy_and_translate@Base 1.4 + svn_subst_create_specialfile@Base 1.6 + svn_subst_detranslate_string@Base 1.4 + svn_subst_eol_style_from_value@Base 1.4 + svn_subst_keywords_differ2@Base 1.4 + svn_subst_keywords_differ@Base 1.4 + svn_subst_read_specialfile@Base 1.6 + svn_subst_stream_detranslated@Base 1.4 + svn_subst_stream_from_specialfile@Base 1.5 + svn_subst_stream_translated@Base 1.4 + svn_subst_stream_translated_to_normal_form@Base 1.5 + svn_subst_translate_cstring2@Base 1.4 + svn_subst_translate_cstring@Base 1.4 + svn_subst_translate_stream2@Base 1.4 + svn_subst_translate_stream3@Base 1.4 + svn_subst_translate_stream@Base 1.4 + svn_subst_translate_string2@Base 1.7 + svn_subst_translate_string@Base 1.4 + svn_subst_translate_to_normal_form@Base 1.4 + svn_subst_translation_required@Base 1.4 + svn_time_from_cstring@Base 1.4 + svn_time_to_cstring@Base 1.4 + svn_time_to_human_cstring@Base 1.4 + svn_uri_basename@Base 1.7 + svn_uri_canonicalize@Base 1.6 + svn_uri_condense_targets@Base 1.7 + svn_uri_dirname@Base 1.6 + svn_uri_get_dirent_from_file_url@Base 1.7 + svn_uri_get_file_url_from_dirent@Base 1.7 + svn_uri_get_longest_ancestor@Base 1.6 + svn_uri_is_canonical@Base 1.6 + svn_uri_is_root@Base 1.6 + svn_uri_skip_ancestor@Base 1.7 + svn_uri_split@Base 1.7 + svn_user_get_homedir@Base 1.4 + svn_user_get_name@Base 1.4 + svn_utf_cstring_from_utf8@Base 1.4 + svn_utf_cstring_from_utf8_ex2@Base 1.4 + svn_utf_cstring_from_utf8_ex@Base 1.4 + svn_utf_cstring_from_utf8_fuzzy@Base 1.4 + svn_utf_cstring_from_utf8_string@Base 1.4 + svn_utf_cstring_from_utf8_stringbuf@Base 1.4 + svn_utf_cstring_to_utf8@Base 1.4 + svn_utf_cstring_to_utf8_ex2@Base 1.4 + svn_utf_cstring_to_utf8_ex@Base 1.4 + svn_utf_initialize@Base 1.4 + svn_utf_string_from_utf8@Base 1.4 + svn_utf_string_to_utf8@Base 1.4 + svn_utf_stringbuf_from_utf8@Base 1.4 + svn_utf_stringbuf_to_utf8@Base 1.4 + svn_uuid_generate@Base 1.4 + svn_ver_check_list@Base 1.4 + svn_ver_compatible@Base 1.4 + svn_ver_equal@Base 1.4 + svn_xml_ap_to_hash@Base 1.4 + svn_xml_escape_attr_cstring@Base 1.4 + svn_xml_escape_attr_string@Base 1.4 + svn_xml_escape_attr_stringbuf@Base 1.4 + svn_xml_escape_cdata_cstring@Base 1.4 + svn_xml_escape_cdata_string@Base 1.4 + svn_xml_escape_cdata_stringbuf@Base 1.4 + svn_xml_free_parser@Base 1.4 + svn_xml_fuzzy_escape@Base 1.4 + svn_xml_get_attr_value@Base 1.4 + svn_xml_hash_atts_overlaying@Base 1.4 + svn_xml_hash_atts_preserving@Base 1.4 + svn_xml_is_xml_safe@Base 1.4 + svn_xml_make_att_hash@Base 1.4 + svn_xml_make_close_tag@Base 1.4 + svn_xml_make_header2@Base 1.7 + svn_xml_make_header@Base 1.4 + svn_xml_make_open_tag@Base 1.4 + svn_xml_make_open_tag_hash@Base 1.4 + svn_xml_make_open_tag_v@Base 1.4 + svn_xml_make_parser@Base 1.4 + svn_xml_parse@Base 1.4 + svn_xml_signal_bailout@Base 1.4 +libsvn_wc-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + svn_wc_add2@Base 1.4 + svn_wc_add3@Base 1.6 + svn_wc_add4@Base 1.7 + svn_wc_add@Base 1.4 + svn_wc_add_from_disk@Base 1.7 + svn_wc_add_lock2@Base 1.7 + svn_wc_add_lock@Base 1.4 + svn_wc_add_repos_file2@Base 1.4 + svn_wc_add_repos_file3@Base 1.6 + svn_wc_add_repos_file4@Base 1.7 + svn_wc_add_repos_file@Base 1.4 + svn_wc_adm_access_path@Base 1.4 + svn_wc_adm_access_pool@Base 1.4 + svn_wc_adm_close2@Base 1.6 + svn_wc_adm_close@Base 1.4 + svn_wc_adm_locked@Base 1.4 + svn_wc_adm_open2@Base 1.4 + svn_wc_adm_open3@Base 1.4 + svn_wc_adm_open@Base 1.4 + svn_wc_adm_open_anchor@Base 1.4 + svn_wc_adm_probe_open2@Base 1.4 + svn_wc_adm_probe_open3@Base 1.4 + svn_wc_adm_probe_open@Base 1.4 + svn_wc_adm_probe_retrieve@Base 1.4 + svn_wc_adm_probe_try2@Base 1.4 + svn_wc_adm_probe_try3@Base 1.4 + svn_wc_adm_probe_try@Base 1.4 + svn_wc_adm_retrieve@Base 1.4 + svn_wc_canonicalize_svn_prop@Base 1.5 + svn_wc_check_wc2@Base 1.7 + svn_wc_check_wc@Base 1.4 + svn_wc_cleanup2@Base 1.4 + svn_wc_cleanup3@Base 1.7 + svn_wc_cleanup@Base 1.4 + svn_wc_committed_queue_create@Base 1.5 + svn_wc_conflict_description_create_prop2@Base 1.7 + svn_wc_conflict_description_create_prop@Base 1.6 + svn_wc_conflict_description_create_text2@Base 1.7 + svn_wc_conflict_description_create_text@Base 1.6 + svn_wc_conflict_description_create_tree2@Base 1.7 + svn_wc_conflict_description_create_tree@Base 1.6 + svn_wc_conflict_version_create@Base 1.6 + svn_wc_conflict_version_dup@Base 1.6 + svn_wc_conflicted_p2@Base 1.6 + svn_wc_conflicted_p3@Base 1.7 + svn_wc_conflicted_p@Base 1.4 + svn_wc_context_create@Base 1.7 + svn_wc_context_destroy@Base 1.7 + svn_wc_copy2@Base 1.4 + svn_wc_copy3@Base 1.7 + svn_wc_copy@Base 1.4 + svn_wc_crawl_revisions2@Base 1.4 + svn_wc_crawl_revisions3@Base 1.5 + svn_wc_crawl_revisions4@Base 1.6 + svn_wc_crawl_revisions5@Base 1.7 + svn_wc_crawl_revisions@Base 1.4 + svn_wc_create_conflict_result@Base 1.5 + svn_wc_create_notify@Base 1.4 + svn_wc_create_notify_url@Base 1.6 + svn_wc_create_tmp_file2@Base 1.4 + svn_wc_create_tmp_file@Base 1.4 + svn_wc_crop_tree2@Base 1.7 + svn_wc_crop_tree@Base 1.6 + svn_wc_delete2@Base 1.4 + svn_wc_delete3@Base 1.5 + svn_wc_delete4@Base 1.7 + svn_wc_delete@Base 1.4 + svn_wc_diff2@Base 1.4 + svn_wc_diff3@Base 1.4 + svn_wc_diff4@Base 1.5 + svn_wc_diff5@Base 1.6 + svn_wc_diff6@Base 1.7 + svn_wc_diff@Base 1.4 + svn_wc_dup_notify@Base 1.4 + svn_wc_dup_status2@Base 1.4 + svn_wc_dup_status3@Base 1.7 + svn_wc_dup_status@Base 1.4 + svn_wc_edited_externals@Base 1.4 + svn_wc_ensure_adm2@Base 1.4 + svn_wc_ensure_adm3@Base 1.5 + svn_wc_ensure_adm4@Base 1.7 + svn_wc_ensure_adm@Base 1.4 + svn_wc_entries_read@Base 1.4 + svn_wc_entry@Base 1.4 + svn_wc_entry_dup@Base 1.4 + svn_wc_exclude@Base 1.7 + svn_wc_external_item2_dup@Base 1.5 + svn_wc_external_item_create@Base 1.5 + svn_wc_external_item_dup@Base 1.4 + svn_wc_get_actual_target2@Base 1.7 + svn_wc_get_actual_target@Base 1.4 + svn_wc_get_adm_dir@Base 1.4 + svn_wc_get_ancestry@Base 1.4 + svn_wc_get_changelists@Base 1.7 + svn_wc_get_default_ignores@Base 1.4 + svn_wc_get_diff_editor2@Base 1.4 + svn_wc_get_diff_editor3@Base 1.4 + svn_wc_get_diff_editor4@Base 1.5 + svn_wc_get_diff_editor5@Base 1.6 + svn_wc_get_diff_editor6@Base 1.7 + svn_wc_get_diff_editor@Base 1.4 + svn_wc_get_ignores2@Base 1.7 + svn_wc_get_ignores@Base 1.4 + svn_wc_get_pristine_contents2@Base 1.7 + svn_wc_get_pristine_contents@Base 1.6 + svn_wc_get_pristine_copy_path@Base 1.4 + svn_wc_get_pristine_props@Base 1.7 + svn_wc_get_prop_diffs2@Base 1.7 + svn_wc_get_prop_diffs@Base 1.4 + svn_wc_get_status_editor2@Base 1.4 + svn_wc_get_status_editor3@Base 1.5 + svn_wc_get_status_editor4@Base 1.6 + svn_wc_get_status_editor5@Base 1.7 + svn_wc_get_status_editor@Base 1.4 + svn_wc_get_switch_editor2@Base 1.4 + svn_wc_get_switch_editor3@Base 1.5 + svn_wc_get_switch_editor4@Base 1.7 + svn_wc_get_switch_editor@Base 1.4 + svn_wc_get_update_editor2@Base 1.4 + svn_wc_get_update_editor3@Base 1.5 + svn_wc_get_update_editor4@Base 1.7 + svn_wc_get_update_editor@Base 1.4 + svn_wc_has_binary_prop@Base 1.4 + svn_wc_info_dup@Base 1.7 + svn_wc_init_traversal_info@Base 1.4 + svn_wc_is_adm_dir@Base 1.4 + svn_wc_is_entry_prop@Base 1.4 + svn_wc_is_normal_prop@Base 1.4 + svn_wc_is_wc_prop@Base 1.4 + svn_wc_is_wc_root2@Base 1.7 + svn_wc_is_wc_root@Base 1.4 + svn_wc_locked2@Base 1.7 + svn_wc_locked@Base 1.4 + svn_wc_mark_missing_deleted@Base 1.4 + svn_wc_match_ignore_list@Base 1.5 + svn_wc_maybe_set_repos_root@Base 1.4 + svn_wc_merge2@Base 1.4 + svn_wc_merge3@Base 1.5 + svn_wc_merge4@Base 1.7 + svn_wc_merge@Base 1.4 + svn_wc_merge_prop_diffs@Base 1.4 + svn_wc_merge_props2@Base 1.5 + svn_wc_merge_props3@Base 1.7 + svn_wc_merge_props@Base 1.4 + svn_wc_move@Base 1.7 + svn_wc_parse_externals_description2@Base 1.4 + svn_wc_parse_externals_description3@Base 1.5 + svn_wc_parse_externals_description@Base 1.4 + svn_wc_process_committed2@Base 1.4 + svn_wc_process_committed3@Base 1.4 + svn_wc_process_committed4@Base 1.5 + svn_wc_process_committed@Base 1.4 + svn_wc_process_committed_queue2@Base 1.7 + svn_wc_process_committed_queue@Base 1.5 + svn_wc_prop_get2@Base 1.7 + svn_wc_prop_get@Base 1.4 + svn_wc_prop_list2@Base 1.7 + svn_wc_prop_list@Base 1.4 + svn_wc_prop_set2@Base 1.4 + svn_wc_prop_set3@Base 1.6 + svn_wc_prop_set4@Base 1.7 + svn_wc_prop_set@Base 1.4 + svn_wc_props_modified_p2@Base 1.7 + svn_wc_props_modified_p@Base 1.4 + svn_wc_queue_committed2@Base 1.6 + svn_wc_queue_committed3@Base 1.7 + svn_wc_queue_committed@Base 1.5 + svn_wc_read_kind@Base 1.7 + svn_wc_relocate2@Base 1.4 + svn_wc_relocate3@Base 1.5 + svn_wc_relocate4@Base 1.7 + svn_wc_relocate@Base 1.4 + svn_wc_remove_from_revision_control2@Base 1.7 + svn_wc_remove_from_revision_control@Base 1.4 + svn_wc_remove_lock2@Base 1.7 + svn_wc_remove_lock@Base 1.4 + svn_wc_resolved_conflict2@Base 1.4 + svn_wc_resolved_conflict3@Base 1.5 + svn_wc_resolved_conflict4@Base 1.6 + svn_wc_resolved_conflict5@Base 1.7 + svn_wc_resolved_conflict@Base 1.4 + svn_wc_restore@Base 1.7 + svn_wc_revert2@Base 1.4 + svn_wc_revert3@Base 1.5 + svn_wc_revert4@Base 1.7 + svn_wc_revert@Base 1.4 + svn_wc_revision_status2@Base 1.7 + svn_wc_revision_status@Base 1.4 + svn_wc_set_adm_dir@Base 1.4 + svn_wc_set_changelist2@Base 1.7 + svn_wc_set_changelist@Base 1.5 + svn_wc_status2@Base 1.4 + svn_wc_status3@Base 1.7 + svn_wc_status@Base 1.4 + svn_wc_status_set_repos_locks@Base 1.4 + svn_wc_text_modified_p2@Base 1.7 + svn_wc_text_modified_p@Base 1.4 + svn_wc_translated_file2@Base 1.4 + svn_wc_translated_file@Base 1.4 + svn_wc_translated_stream@Base 1.5 + svn_wc_transmit_prop_deltas2@Base 1.7 + svn_wc_transmit_prop_deltas@Base 1.4 + svn_wc_transmit_text_deltas2@Base 1.4 + svn_wc_transmit_text_deltas3@Base 1.7 + svn_wc_transmit_text_deltas@Base 1.4 + svn_wc_traversed_depths@Base 1.5 + svn_wc_upgrade@Base 1.7 + svn_wc_version@Base 1.4 + svn_wc_walk_entries2@Base 1.4 + svn_wc_walk_entries3@Base 1.5 + svn_wc_walk_entries@Base 1.4 + svn_wc_walk_status@Base 1.7 --- subversion-1.7.9.orig/debian/man/svn-backup-dumps.1 +++ subversion-1.7.9/debian/man/svn-backup-dumps.1 @@ -0,0 +1,168 @@ +.\" Process this file with +.\" Copyright 2006 by Troy Heber - taken directly from svn-backup-dumps +.\" Copyright (c) 2006 CollabNet. +.\" Permission is granted to everyone to use and distribute this work, +.\" without limitation, modified or unmodified, in any way, for any purpose. +.\" groff -man -Tascii svn-backup-dumps.1 +.\" +.TH svn\-backup\-dumps 1 "2006-11-09" +.SH NAME +svn\-backup\-dumps \- Create dumpfiles to backup a subversion repository. +.SH SYNOPSIS +.B svn\-backup\-dumps +.I +.I +.SH DESCRIPTION +.B svn\-backup\-dumps +creates dumpfiles from a subversion repository. It is intended for +use in cron jobs and post-commit hooks. +.PP +The basic modes of operation are: +.IP \(bu +Create a full dump (revisions 0 to HEAD) +.IP \(bu +Create incremental dump containing at most N revisions. +.IP \(bu +Create incremental single-revision dumps (for use in post-commit). +.PP +Dumpfiles are named in the format +.IR basename . rev .svndmp +or +.IR basename . rev . rev .svndmp, +where +.I basename +is the repository directory name, and the +.I rev +arguments are the first and last revision numbers represented in the +dumpfile, zero-padded to 6 digits. +.PP +Optionally, +.B svn\-backup\-dumps +can compress dumpfiles with +.BR gzip " or " bzip2 , +and can transfer them to another host using FTP or SMB (using +.BR smbclient ). +.\" +.SH OPTIONS +.TP +.B \-\-version +Show program's version number and exit. +.TP +.BR \-h ", " \-\-help +Show this help message and exit. +.TP +.B \-b +Compress the dump using +.BR bzip2 . +.TP +.B \-\-deltas +This is passed through to +.BR "svnadmin dump" . +.TP +.BI \-c " count" +Maximum number of revisions per dumpfile. +.TP +.B \-o +Overwrite files. +.TP +.B \-O +Overwrite all files. +.TP +.B \-q +Quiet. +.TP +.BI \-r " rev" +Specify a single-revision dumpfile. +.PP +.RI "\fB\-t\fR ftp:" host : user : password : path +.PD 0 +.TP +.RI "\fB\-t\fR smb:" share : user : password : path +.PD +Transfer dumps to another machine using the FTP or SMB protocols. +.I path +is where to store the dumpfiles on the remote server; any occurrence of +.I %r +in the path is replaced by the repository name. Support for "smb:" +requires the +.B smbclient +program. +.TP +.B \-z +Compress the dump using +.BR gzip . +.\" +.SH EXAMPLES +To create a full dump of all revisions of a repository +.IR /srv/svn/foo " in the directory " /var/backup/svn : +.PP +svn\-backup\-dumps /srv/svn/foo /var/backup/svn +.PP +The dumpfile will be named +.I src.000000-NNNNNN.svndmp.gz +where +.I NNNNNN +is the head revision number. +.\" +.PP +To create incremental dumps containing at most 1000 revisions: +.PP +svn\-backup\-dumps \-\-deltas \-z \-c 1000 /srv/svn/foo /var/backup/svn +.PP +If the youngest revision is 2923, it creates the following files: +.IP +.PD 0 +foo.000000-000999.svndmp.gz +.IP +foo.001000-001999.svndmp.gz +.IP +foo.002000-002923.svndmp.gz +.PD +.PP +If run again, later, when the youngest revision is 3045, it creates +these two files: +.IP +.PD 0 +foo.002000-002999.svndmp.gz +.IP +foo.003000-003045.svndmp.gz +.PD +.PP +Note that it does not remove the redundant file +foo.002000-002923.svndmp.gz. +.\" +.PP +To create incremental single-revision dumps from a post-commit hook: +.PP +svn\-backup\-dumps \-r $rev $repos /var/backups/svn +.PP +where +.IR $rev " and " $repos +are variables previously set in the post-commit script from its command +line. The dumpfile name will be in the form +.IR foo.000352.svndmp . +.\" +.PP +To send the dumpfiles to the SMB share +.I \\\\\\\\ERNEST\\\\BACKUPS +in a directory +.I \\\\svn\\\\foo +with user +.I svnuser +and password +.IR w0rth1ng : +.IP +svn\-backup\-dumps \-t "smb://ERNEST/BACKUPS:svnuser:w0rth1ng:svn/%r +/srv/svn/foo /tmp/tmpbackup +.PP +Note that the +.I %r +in the path is replaced by the repository name +.BR foo . +Note also that a local backup directory is required, at present, even +when using the +.B \-t +option. +.\" +.SH AUTHOR +Voluntary contributions made by many individuals. Copyright \(co 2006 CollabNet. --- subversion-1.7.9.orig/debian/man/svn-bisect.1 +++ subversion-1.7.9/debian/man/svn-bisect.1 @@ -0,0 +1,121 @@ +.\" svn-bisect.1 +.\" Copyright 2009 by Peter Samuelson +.\" Permission is granted to everyone to use and distribute this work, +.\" without limitation, modified or unmodified, in any way, for any purpose. +.TH SVN-BISECT 1 "2009-10-22" +.\" +.SH NAME +svn\-bisect \- Bisect Subversion revisions to find a regression +.\" +.SH SYNOPSIS +.B svn\-bisect start +.RI [ good_rev " [" bad_rev ]] +.PP +.BR svn\-bisect " {" good | bad "} " +.RI [ rev ] +.PP +.B svn\-bisect run +.I command +.PP +.B svn\-bisect reset +.PP +.B svn\-bisect status +.\" +.SH DESCRIPTION +.B svn\-bisect +helps to automate finding a bug or behavior change in a +.B Subversion +working copy. Given an initial \(lqgood\(rq revision, with the desired +or original behavior, and a newer \(lqbad\(rq revision, with the +undesired or modified behavior, +.B svn\-bisect +will do a binary search through the revision range to find which +revision caused the change. +.PP +.B svn\-bisect +must be initialized in a working copy, with +.BR "svn\-bisect start" . +It also needs to be given at least one +.IR good +revision (the baseline) and one +.I bad +revision (known modified behavior) revision. +.PP +Sub-commands: +.TP +.B start +Initializes or reinitializes +.BR svn\-bisect ; +optionally takes +.IR good " and " bad +revision parameters. +.TP +.BI good " rev" +.TP +.BI bad " rev" +Tells +.B svn\-bisect +that a revision is +.IR good " or " bad , +defining or narrowing the search space. If not specified, +.I revision +defaults to the current revision in the working copy. +.B svn\-bisect +will then update to a revision halfway between the new +.IR good " and " bad +boundaries. If this update crosses a point where a branch was created, +it switches in or out of the branch. +.TP +.B reset +Resets the working copy to the revision and branch where +.B svn\-bisect start +was run. In the simple case this is equivalent to +.BR "rm -r .svn-bisect; svn update" , +but not if it has crossed branches, and not if you did not start at the +.B HEAD +revision. In any case, +.B svn\-bisect +never keeps track of mixed-revision working copies, so do not use +.B svn\-bisect +in a working copy that will need to be restored to mixed revisions. +.TP +.B status +Prints a brief status message. +.TP +.BI run " command" +Runs the bisection in a loop. You must have already defined initial +.IR good " and " bad +boundary conditions. Each iteration through the loop runs +.I command +as a shell command (a single argument, quoted if necessary) on the +chosen revision, then marks the revision as +.IR good " or " bad , +based on the exit status of +.IR command . +.\" +.SH EXAMPLES +Assume you are trying to find which revision between 1250 and 1400 +caused the +.B make check +command to fail. +.PP + svn\-bisect start 1250 1400 + svn\-bisect run \(aqmake check\(aq + svn\-bisect reset +.\" +.SH ENVIRONMENT +.IP SVN +The Subversion command-line program to call (default +.BR svn ). +.SH FILES +.IP \.svn\-bisect +The directory containing state information, removed after a successful +bisection. +.\" +.SH "SEE ALSO" +.BR git\-bisect (1). +.\" +.SH AUTHOR +.\" , +Written by Robert Millan and Peter Samuelson, for the Debian Project +(but may be used by others). --- subversion-1.7.9.orig/debian/man/svn-fast-backup.1 +++ subversion-1.7.9/debian/man/svn-fast-backup.1 @@ -0,0 +1,78 @@ +.\" Process this file with +.\" Copyright 2006 by Troy Heber - taken directly from svn-fast-backup +.\" Copyright (c) 2006 CollabNet. +.\" Permission is granted to everyone to use and distribute this work, +.\" without limitation, modified or unmodified, in any way, for any purpose. +.\" groff -man -Tascii svn-fast-backup.1 +.\" +.TH svn\-fast\-backup 1 "2006-11-09" +.SH NAME +svn\-fast\-backup \- very fast backup for Subversion fsfs repositories. +.SH SYNOPSIS +.B svn\-fast\-backup +.RB [ \-q ] +.RB [ \-k {\fIN\fR|\fIall\fR}] +.RB [ \-f ] +.RB [ \-t ] +.RB [ \-s ] +.I repos_path +.I backup_dir +.\" +.SH DESCRIPTION +.B svn\-fast\-backup +uses +.B rsync +snapshots for very fast backup of a Subversion +.B fsfs +repository at +.I repos_path +to +.IR backup_dir / repos-rev , +the latest revision number in the repository. Multiple +.B fsfs +backups share data via hardlinks, so old backups are almost free, since +a newer revision of a repository is almost a complete superset of an +older revision. +.PP +This is good for replacing incremental log-dump+restore-style backups +because it is just as space-conserving and even faster; there is no +inter-backup state (old backups are essentially caches); each backup +directory is self-contained. It has the same command-line interface as +.BR svn\-hot\-backup (1) +(if you use +.BR \-\-force ), +but only works for +.B fsfs +repositories. +.PP +.B svn\-fast\-backup +keeps 64 backups by default and deletes backups older than these; this +can be adjusted with the +.B \-k +option. +.\" +.SH OPTIONS +.TP +.BR \-h ", " \-\-help +Shows some brief help text. +.TP +.BR \-q ", " \-\-quiet +Quieter-than-usual operation. +.TP +.BR \-k ", " \-\-keep=\fIN\fR +Keep a specified number of backups; the default is to keep 64. +.TP +.BR \-k ", " \-\-keep=all +Do not delete any old backups at all. +.TP +.BR \-f ", " \-\-force +Make a new backup even if one with the current revision exists. +.TP +.BR \-t ", " \-\-trace +Show actions. +.TP +.BR \-s ", " \-\-simulate +Don't perform actions. +.\" +.SH AUTHOR +Voluntary contributions made by many individuals. Copyright \(co 2006 CollabNet. --- subversion-1.7.9.orig/debian/man/svn-hot-backup.1 +++ subversion-1.7.9/debian/man/svn-hot-backup.1 @@ -0,0 +1,40 @@ +.\" Process this file with +.\" Copyright 2006 by Troy Heber - taken directly from svn-hot-backup +.\" Copyright (c) 2006 CollabNet. +.\" Permission is granted to everyone to use and distribute this work, +.\" without limitation, modified or unmodified, in any way, for any purpose. +.\" groff -man -Tascii svn-hot-backup.1 +.\" +.TH svn\-hot\-backup 1 "2006-11-09" +.SH NAME +svn\-hot\-backup \- perform a "hot" backup of a Berkeley DB repository. +.SH SYNOPSIS +.B svn\-hot\-backup +.RB [ \-\-archive-type=\fItype\fR ] +.I repos_path +.I backup_dir +.PP +.\" +.SH DESCRIPTION +.B svn\-hot\-backup +performs a "hot" backup of a Subversion BDB repository, and cleans old +logfiles after the backup completes. +.\" +.SH OPTIONS +.TP +.PD 0 +.B \-\-archive\-type=gz +.TP +.BI \-\-archive\-type=bz2 +.TP +.BI \-\-archive\-type=zip +.PD +Create a compressed archive of the backup, in +.IR .tar.gz ", " .tar.bz2 ", or " .zip +format respectively. +.TP +.BR \-h ", " \-\-help +Print this help message and exit. +.\" +.SH AUTHOR +Voluntary contributions made by many individuals. Copyright \(co 2006 CollabNet. --- subversion-1.7.9.orig/debian/man/svn_load_dirs.1 +++ subversion-1.7.9/debian/man/svn_load_dirs.1 @@ -0,0 +1,127 @@ +.TH SVN_LOAD_DIRS 1 + +.SH NAME +svn_load_dirs - Load directories into a Subversion repository + +.SH SYNOPSIS +.B svn_load_dirs +[\fIoptions\fR] \fIsvn_url\fR \fIsvn_import_dir\fR [\fIdirectory\fR ...] + +.SH DESCRIPTION +This tool can be used for importing one or more directories into a +Subversion repository. The difference from "svn import" is that +svn_load_dirs can update an existing directory tree, and tag it +properly. Only changes from the previous version will be recorded in +the revision, so that you can easily apply them on another branch. +For example, this is very useful for managing the upstream source when +maintaining Debian packages in Subversion. + +.SH OPTIONS +.TP +\fIsvn_url\fR +The base Subversion URL. +.TP +\fIsvn_import_dir\fR +The path relative to \fIsvn_url\fR where the directories are to be imported. +.TP +\fIdirectory ...\fR +The directories to import. If they are not specified on the command line, +they are read from standard input. +.TP +\fB\-no_user_input\fR +Don't ask any questions. Assume that the answer is yes. +.TP +\fB\-p\fR \fIfilename\fR +Apply the properties specified in the configuration file +\fIfilename\fR to matching files. See below for a description of +the configuration file format. +.TP +\fB\-svn_username\fR \fIusername\fR +Username to use when committing to the repository. +.TP +\fB\-svn_password\fR \fIpassword\fR +Password to use when committing to the repository. +.TP +\fB\-t\fR \fItag_dir\fR +Create a tag copy in \fItag_dir\fR, relative to +\fIsvn_url\fR. \fItag_dir\fR may contain a regular expression +enclosed within '@' characters. It will be replaced by the matching part +from the imported directory names. +.TP +\fB\-v\fR +Be more verbose. Use multiple times for increased effect. +.TP +\fB\-wc\fR \fIpath\fR +Use the already checked out working copy at \fIpath\fR instead of +checking out a new working copy. + +.SH PROPERTY CONFIGURATION FILE FORMAT +The property configuration file, which is specified by the \-p option, +contains rules for applying properties to the imported files. +It consists of lines of the following format: +.PP +.I regular_expression control property_name property_value +.PP +The meaning of the fields are: +.TP +.I regular_expression +A Perl-style regular expression matching the files to apply this rule to. +.TP +.I control +Either "break" or "cont". If set to "break", processing of the current +file will stop if this rule matches. If set to "cont", processing will +continue. The latter can be used to set multiple properties for one +file. +.TP +.I property_name +(Optional) The name of the property to set. +.TP +.I property_value +(Optional) Set the property to this value. +.PP +The last two fields may be omitted, in which case the rule will not +set any properties. This is useful for excluding certain files from +subsequent rules. +.PP +You need to quote the \fIregular_expression\fR, \fIproperty_name\fR +and \fIproperty_value\fR fields with double quotes ('"') if you have +whitespace in them. Single and double quotes can be escaped with +backslash ('\\'). + +.SH EXAMPLES +For example, to import the contents of the foo\-1.3 directory into the +upstream/current directory of the foo repository: +.PP +.HP +svn_load_dirs svn+ssh://svn.example.org/svn/foo upstream/current foo\-1.3 +.PP +A tag can also be added automatically using the \-t option: +.PP +.HP +svn_load_dirs svn+ssh://svn.example.org/svn/foo \-t \'upstream/@\\d+\\.\\w+@\' +upstream/current foo\-1.3 +.PP +Here's an example of a property configuration file: +.PP +\\.doc$ break svn:mime\-type application/msword +.br +\\.ds(p|w)$ break svn:eol\-style CRLF +.br +\\.dos2unix\-eol\\.sh$ break +.br +\&.*\ \ \ break svn:eol\-style native +.PP +This example specifies that .doc files are to be treated as binary +files, that .dsp and .dsw files have their line ending characters +kept, and that all other files except dos2unix\-eol.sh have their line +endings converted to the native style. + +.SH SEE ALSO +/usr/share/doc/subversion\-tools/svn_load_dirs.README.gz +.PP +\fBsvn\fR(1) + +.SH AUTHOR +This manual page was written by Per Olofsson for the +Debian distribution (but may be used by others). Some parts were taken +from the README. --- subversion-1.7.9.orig/debian/man/svnwrap.1 +++ subversion-1.7.9/debian/man/svnwrap.1 @@ -0,0 +1,98 @@ +.\" svnwrap.1 +.\" Copyright 2006 by Peter Samuelson +.\" Permission is granted to everyone to use and distribute this work, +.\" without limitation, modified or unmodified, in any way, for any purpose. +.TH SVNWRAP 1 "2006-04-21" +.\" +.SH NAME +svnwrap \- Umask wrapper for subversion client commands +.\" +.SH SYNOPSIS +.B svnwrap +.RB { program } +.RI [ args... ] +.\" +.SH DESCRIPTION +.B svnwrap +is a simple shell script to work around permission problems when +sharing Subversion repositories between multiple local users. +.B svnwrap +can be used either by specifying a particular +.B subversion +client command on the command line, or by invoking it by the same name +as the desired client command, via a symlink. +.PP +.B svnwrap +sets the +.I umask +to 002, then launches the appropriate +.B subversion +client command. For complicated reasons, this is needed when using the +clients with +.IR BDB -format +repositories, but not for +.IR FSFS -format +ones. +.\" +.SH EXAMPLES +To create a new BDB-format shared repository (note that FSFS-format +shared repositories should also be created this way): +.PP +svnwrap\ svnadmin\ create\ \-\-fs\-type=bdb +.I /path/to/repo +.br +chgrp\ \-R +.I shared_group\ /path/to/repo +.PP +The following line in +.I /etc/inetd.conf +can be used to serve +.I svn:// +URLs: +.PP +svn\ stream\ tcp\ nowait +.I my_svn_user +/usr/bin/svnwrap\ svnserve\ svnserve\ \-i\ \-r +.I /srv/svn +.PP +The following commands enable use of +.B svnwrap +for local +.I file:/// +and remote +.I svn+ssh:// +URLs: +.PP +ln\ \-s\ /usr/bin/svnwrap\ /usr/local/bin/svn +.br +ln\ \-s\ /usr/bin/svnwrap\ /usr/local/bin/svnserve +.PP +.B svn +is used for local +.I file:/// +URLs, and +.B svnserve +is invoked by remote users of +.I svn+ssh:// +URLs. +.SH BUGS +If you symlink the +.B svn +binary to +.BR svnwrap , +as shown in one of the examples, +.I all local users' working copies will also use the new +.IR umask . +Be sure to warn your users about this, as security-related surprises +are rarely pleasant. +.\" +.SH "SEE ALSO" +.BR svnserve (8), +.BR svn (1), +.BR svnlook (1). +.\" +.SH AUTHOR +.B svnwrap +and this manual were written by Peter Samuelson +.\" +for the Debian Project (but may be used by others). --- subversion-1.7.9.orig/debian/patches/CVE-2013-1968.patch +++ subversion-1.7.9/debian/patches/CVE-2013-1968.patch @@ -0,0 +1,125 @@ +Description: Fix CVE-2013-1968 + Subversion FSFS repositories can be corrupted by newline characters in + filenames. +Origin: upstream, http://subversion.apache.org/security/CVE-2013-1968-advisory.txt +Bug-Debian: http://bugs.debian.org/711033 +Forwarded: not-needed +Author: Salvatore Bonaccorso +Last-Update: 2013-06-06 + +--- a/subversion/libsvn_fs_fs/tree.c ++++ b/subversion/libsvn_fs_fs/tree.c +@@ -44,6 +44,7 @@ + #include "svn_private_config.h" + #include "svn_pools.h" + #include "svn_error.h" ++#include "svn_ctype.h" + #include "svn_dirent_uri.h" + #include "svn_path.h" + #include "svn_mergeinfo.h" +@@ -1806,6 +1807,78 @@ + return svn_fs_fs__dag_dir_entries(table_p, node, pool, pool); + } + ++/* Return a copy of PATH, allocated from POOL, for which control ++ characters have been escaped using the form \NNN (where NNN is the ++ octal representation of the byte's ordinal value). */ ++static const char * ++illegal_path_escape(const char *path, apr_pool_t *pool) ++{ ++ svn_stringbuf_t *retstr; ++ apr_size_t i, copied = 0; ++ int c; ++ ++ /* At least one control character: ++ strlen - 1 (control) + \ + N + N + N + null . */ ++ retstr = svn_stringbuf_create_ensure(strlen(path) + 4, pool); ++ for (i = 0; path[i]; i++) ++ { ++ c = (unsigned char)path[i]; ++ if (! svn_ctype_iscntrl(c)) ++ continue; ++ ++ /* If we got here, we're looking at a character that isn't ++ supported by the (or at least, our) URI encoding scheme. We ++ need to escape this character. */ ++ ++ /* First things first, copy all the good stuff that we haven't ++ yet copied into our output buffer. */ ++ if (i - copied) ++ svn_stringbuf_appendbytes(retstr, path + copied, ++ i - copied); ++ ++ /* Make sure buffer is big enough for '\' 'N' 'N' 'N' (and NUL) */ ++ svn_stringbuf_ensure(retstr, retstr->len + 5); ++ /*### The backslash separator doesn't work too great with Windows, ++ but it's what we'll use for consistency with invalid utf8 ++ formatting (until someone has a better idea) */ ++ apr_snprintf(retstr->data + retstr->len, 5, "\\%03o", (unsigned char)c); ++ retstr->len += 4; ++ ++ /* Finally, update our copy counter. */ ++ copied = i + 1; ++ } ++ ++ /* If we didn't encode anything, we don't need to duplicate the string. */ ++ if (retstr->len == 0) ++ return path; ++ ++ /* Anything left to copy? */ ++ if (i - copied) ++ svn_stringbuf_appendbytes(retstr, path + copied, i - copied); ++ ++ /* retstr is null-terminated either by apr_snprintf or the svn_stringbuf ++ functions. */ ++ ++ return retstr->data; ++} ++ ++/* Raise an error if PATH contains a newline because FSFS cannot handle ++ * such paths. See issue #4340. */ ++static svn_error_t * ++check_newline(const char *path, apr_pool_t *pool) ++{ ++ const char *c; ++ ++ for (c = path; *c; c++) ++ { ++ if (*c == '\n') ++ return svn_error_createf(SVN_ERR_FS_PATH_SYNTAX, NULL, ++ _("Invalid control character '0x%02x' in path '%s'"), ++ (unsigned char)*c, illegal_path_escape(path, pool)); ++ } ++ ++ return SVN_NO_ERROR; ++} + + /* Create a new directory named PATH in ROOT. The new directory has + no entries, and no properties. ROOT must be the root of a +@@ -1820,6 +1893,8 @@ + dag_node_t *sub_dir; + const char *txn_id = root->txn; + ++ SVN_ERR(check_newline(path, pool)); ++ + SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional, + txn_id, pool)); + +@@ -2082,6 +2157,8 @@ + const char *to_path, + apr_pool_t *pool) + { ++ SVN_ERR(check_newline(to_path, pool)); ++ + return svn_error_trace(copy_helper(from_root, from_path, to_root, to_path, + TRUE, pool)); + } +@@ -2174,6 +2251,8 @@ + dag_node_t *child; + const char *txn_id = root->txn; + ++ SVN_ERR(check_newline(path, pool)); ++ + SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional, + txn_id, pool)); + --- subversion-1.7.9.orig/debian/patches/CVE-2013-2112.patch +++ subversion-1.7.9/debian/patches/CVE-2013-2112.patch @@ -0,0 +1,24 @@ +Description: Fix CVE-2013-2112 + Subversion's svnserve server process may exit when an incoming TCP connection + is closed early in the connection process. + . + This can lead to disruption for users of the server. +Origin: upstream, http://subversion.apache.org/security/CVE-2013-2112-advisory.txt +Bug-Debian: http://bugs.debian.org/711033 +Forwarded: not-needed +Author: Salvatore Bonaccorso +Last-Update: 2013-06-06 + +--- a/subversion/svnserve/main.c ++++ b/subversion/svnserve/main.c +@@ -928,7 +928,9 @@ + connection_pool) == APR_CHILD_DONE) + ; + } +- if (APR_STATUS_IS_EINTR(status)) ++ if (APR_STATUS_IS_EINTR(status) ++ || APR_STATUS_IS_ECONNABORTED(status) ++ || APR_STATUS_IS_ECONNRESET(status)) + { + svn_pool_destroy(connection_pool); + continue; --- subversion-1.7.9.orig/debian/patches/apache_module_dependency +++ subversion-1.7.9/debian/patches/apache_module_dependency @@ -0,0 +1,108 @@ +apache_module_dependency: Dynamically bind two mod_dav_svn functions in +mod_authz_svn, so that it works even if mod_authz_svn is loaded first. + +This is related to splitting mod_authz_svn out of dav_svn.load into its +own authz_svn.load. Since a2enmod does not reorder modules based on +dependencies, mod_authz_svn is loaded first. + +--- a/subversion/include/mod_dav_svn.h ++++ b/subversion/include/mod_dav_svn.h +@@ -30,6 +30,7 @@ + + #include + #include ++#include + + + #ifdef __cplusplus +@@ -83,6 +84,15 @@ + const char **repos_basename, + const char **relative_path, + const char **repos_path); ++APR_DECLARE_OPTIONAL_FN(dav_error *, dav_svn_split_uri, ++ (request_rec *r, ++ const char *uri, ++ const char *root_path, ++ const char **cleaned_uri, ++ int *trailing_slash, ++ const char **repos_name, ++ const char **relative_path, ++ const char **repos_path)); + + + /** +@@ -91,6 +101,10 @@ + AP_MODULE_DECLARE(dav_error *) dav_svn_get_repos_path(request_rec *r, + const char *root_path, + const char **repos_path); ++APR_DECLARE_OPTIONAL_FN(dav_error *, dav_svn_get_repos_path, ++ (request_rec *r, ++ const char *root_path, ++ const char **repos_path)); + + #ifdef __cplusplus + } +--- a/subversion/mod_authz_svn/mod_authz_svn.c ++++ b/subversion/mod_authz_svn/mod_authz_svn.c +@@ -22,7 +22,7 @@ + * ==================================================================== + */ + +- ++#define DAV_SVN_LOAD_OPTIONAL 1 + + #include + #include +@@ -64,6 +64,13 @@ + const char *force_username_case; + } authz_svn_config_rec; + ++#if DAV_SVN_LOAD_OPTIONAL ++static APR_OPTIONAL_FN_TYPE(dav_svn_get_repos_path) *get_repos_path; ++static APR_OPTIONAL_FN_TYPE(dav_svn_split_uri) *split_uri; ++#define dav_svn_get_repos_path get_repos_path ++#define dav_svn_split_uri split_uri ++#endif ++ + /* + * Configuration + */ +@@ -777,6 +784,16 @@ + return OK; + } + ++#if DAV_SVN_LOAD_OPTIONAL ++#undef dav_svn_get_repos_path ++#undef dav_svn_split_uri ++static void import_dav_svn(void) ++{ ++ get_repos_path = APR_RETRIEVE_OPTIONAL_FN(dav_svn_get_repos_path); ++ split_uri = APR_RETRIEVE_OPTIONAL_FN(dav_svn_split_uri); ++} ++#endif ++ + /* + * Module flesh + */ +@@ -798,6 +815,9 @@ + AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME, + AUTHZ_SVN__SUBREQ_BYPASS_PROV_VER, + (void*)subreq_bypass); ++#if DAV_SVN_LOAD_OPTIONAL ++ ap_hook_optional_fn_retrieve(import_dav_svn,NULL,NULL,APR_HOOK_MIDDLE); ++#endif + } + + module AP_MODULE_DECLARE_DATA authz_svn_module = +--- a/subversion/mod_dav_svn/mod_dav_svn.c ++++ b/subversion/mod_dav_svn/mod_dav_svn.c +@@ -1040,6 +1040,9 @@ + static void + register_hooks(apr_pool_t *pconf) + { ++ APR_REGISTER_OPTIONAL_FN(dav_svn_get_repos_path); ++ APR_REGISTER_OPTIONAL_FN(dav_svn_split_uri); ++ + ap_hook_pre_config(init_dso, NULL, NULL, APR_HOOK_REALLY_FIRST); + ap_hook_post_config(init, NULL, NULL, APR_HOOK_MIDDLE); + --- subversion-1.7.9.orig/debian/patches/apr-abi1 +++ subversion-1.7.9/debian/patches/apr-abi1 @@ -0,0 +1,70 @@ +Take ABI version into consideration in the module loading codepaths. +Suitable for upstream, but not sent yet. + +--- a/subversion/libsvn_fs/fs-loader.c ++++ b/subversion/libsvn_fs/fs-loader.c +@@ -100,8 +100,8 @@ + const char *funcname; + apr_status_t status; + +- libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.0", +- name, SVN_VER_MAJOR); ++ libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.%d", ++ name, SVN_VER_MAJOR, SVN_SOVERSION); + funcname = apr_psprintf(pool, "svn_fs_%s__init", name); + + /* Find/load the specified library. If we get an error, assume +--- a/subversion/libsvn_ra/ra_loader.c ++++ b/subversion/libsvn_ra/ra_loader.c +@@ -159,8 +159,8 @@ + const char *compat_funcname; + apr_status_t status; + +- libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.0", +- ra_name, SVN_VER_MAJOR); ++ libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.%d", ++ ra_name, SVN_VER_MAJOR, SVN_SOVERSION); + funcname = apr_psprintf(pool, "svn_ra_%s__init", ra_name); + compat_funcname = apr_psprintf(pool, "svn_ra_%s_init", ra_name); + +--- a/subversion/libsvn_subr/auth.c ++++ b/subversion/libsvn_subr/auth.c +@@ -399,9 +399,9 @@ + const char *library_label, *library_name; + const char *provider_function_name, *version_function_name; + library_name = apr_psprintf(pool, +- "libsvn_auth_%s-%d.so.0", ++ "libsvn_auth_%s-%d.so.%d", + provider_name, +- SVN_VER_MAJOR); ++ SVN_VER_MAJOR, SVN_SOVERSION); + library_label = apr_psprintf(pool, "svn_%s", provider_name); + provider_function_name = apr_psprintf(pool, + "svn_auth_get_%s_%s_provider", +--- a/configure.ac ++++ b/configure.ac +@@ -99,7 +99,7 @@ + if test `expr $apr_version : 2` -ne 0; then + dnl Bump the library so-version to 2 if using APR-2 + dnl (Debian uses so-version 1 for APR-1-with-largefile) +- SVN_LT_SOVERSION="-version-info 2" ++ svn_lib_ver=2 + dnl APR-2 provides APRUTIL + apu_config=$apr_config + AC_SUBST(SVN_APRUTIL_INCLUDES) +@@ -107,11 +107,14 @@ + AC_SUBST(SVN_APRUTIL_LIBS) + AC_SUBST(SVN_APRUTIL_PREFIX) + else +- SVN_LT_SOVERSION="-version-info 0" ++ svn_lib_ver=0 + APU_VER_REGEXES=["0\.9\.[7-9] 0\.9\.1[0-9] 1\."] + SVN_LIB_APRUTIL($APU_VER_REGEXES) + fi ++SVN_LT_SOVERSION="-version-info $svn_lib_ver" + AC_SUBST(SVN_LT_SOVERSION) ++AC_DEFINE_UNQUOTED(SVN_SOVERSION, $svn_lib_ver, ++ [Subversion library major verson]) + + dnl Search for pkg-config + AC_PATH_PROG(PKG_CONFIG, pkg-config) --- subversion-1.7.9.orig/debian/patches/apr-abi2 +++ subversion-1.7.9/debian/patches/apr-abi2 @@ -0,0 +1,26 @@ +Bug #266170: Use SOVERSION 1 for apr 1.x, because the apr 0.9.x -> 1.x +ABI change leaks through the libsvn ABIs (because we use apr_off_t, +which is now 64 bits on all platforms). + +Upstream refused this (http://svn.haxx.se/dev/archive-2006-03/0522.shtml +for thread), but fortunately when it came time to support apr 2.x in svn +1.7, they skipped SOVERSION 1 in consideration of Debian/Ubuntu, so we'll +be ABI-compatible again if and when we move to apr-2.x. + +--- a/configure.ac ++++ b/configure.ac +@@ -106,9 +106,13 @@ + AC_SUBST(SVN_APRUTIL_CONFIG, ["$apu_config"]) + AC_SUBST(SVN_APRUTIL_LIBS) + AC_SUBST(SVN_APRUTIL_PREFIX) ++elif test `expr $apr_version : 1` -ne 0; then ++ svn_lib_ver=1 ++ APU_VER_REGEXES=["1\."] ++ SVN_LIB_APRUTIL($APU_VER_REGEXES) + else + svn_lib_ver=0 +- APU_VER_REGEXES=["0\.9\.[7-9] 0\.9\.1[0-9] 1\."] ++ APU_VER_REGEXES=["0\.9\.[7-9] 0\.9\.1[0-9]"] + SVN_LIB_APRUTIL($APU_VER_REGEXES) + fi + SVN_LT_SOVERSION="-version-info $svn_lib_ver" --- subversion-1.7.9.orig/debian/patches/build-fixes +++ subversion-1.7.9/debian/patches/build-fixes @@ -0,0 +1,197 @@ +Fix some build problems: + +- SWIG out-of-tree stuff +- Disable auth-test.c, which tries to test things like gnome-keyring. + Unlikely to work in a build chroot. +- Add aprutil as a direct dependency for libsvn_client and libsvn_ra. + +--- a/build/generator/swig/checkout_swig_header.py ++++ b/build/generator/swig/checkout_swig_header.py +@@ -40,15 +40,14 @@ + + def write_makefile_rules(self, makefile): + """Write makefile rules to checkout files""" +- script_path = '$(top_srcdir)/build/generator/swig/checkout_swig_header.py' +- conf = '$(abs_srcdir)/build.conf' +- makefile.write('CHECKOUT_SWIG = cd $(top_builddir) && $(PYTHON)' + +- ' %s %s $(SWIG)\n\n' % (script_path, conf)) ++ script_path = 'build/generator/swig/checkout_swig_header.py' ++ makefile.write('CHECKOUT_SWIG = cd $(top_srcdir) &&' + ++ ' $(PYTHON) %s build.conf $(SWIG)\n' % script_path) + checkout_locations = [] + for path in self.swig_checkout_files: + out = self._output_file(path) + checkout_locations.append(out) +- makefile.write('%s: %s\n' % (out, script_path) + ++ makefile.write('%s: $(top_srcdir)/%s\n' % (out, script_path) + + '\t$(CHECKOUT_SWIG) %s\n\n' % path) + makefile.write('SWIG_CHECKOUT_FILES = %s\n\n\n' + % " ".join(checkout_locations)) +--- a/Makefile.in ++++ b/Makefile.in +@@ -290,14 +290,14 @@ + + # The path to generated and complementary source files for the SWIG + # bindings. +-SWIG_PL_DIR = $(abs_builddir)/subversion/bindings/swig/perl +-SWIG_PY_DIR = $(abs_builddir)/subversion/bindings/swig/python +-SWIG_RB_DIR = $(abs_builddir)/subversion/bindings/swig/ruby ++SWIG_PL_DIR = $(top_builddir)/subversion/bindings/swig/perl ++SWIG_PY_DIR = $(top_builddir)/subversion/bindings/swig/python ++SWIG_RB_DIR = $(top_builddir)/subversion/bindings/swig/ruby + + # The path to the source files for the SWIG bindings + SWIG_PL_SRC_DIR = $(abs_srcdir)/subversion/bindings/swig/perl +-SWIG_PY_SRC_DIR = $(abs_srcdir)/subversion/bindings/swig/python +-SWIG_RB_SRC_DIR = $(abs_srcdir)/subversion/bindings/swig/ruby ++SWIG_PY_SRC_DIR = $(top_srcdir)/subversion/bindings/swig/python ++SWIG_RB_SRC_DIR = $(top_srcdir)/subversion/bindings/swig/ruby + + ### Automate JAR creation using Makefile generator's javahl-java.jar + ### property. Enhance generator to support JAR installation. +@@ -770,8 +770,7 @@ + fi + for d in $(SWIG_PL_DIR)/libsvn_swig_perl; \ + do \ +- cd $$d; \ +- rm -rf *.lo *.la *.o .libs; \ ++ (cd $$d && rm -rf *.lo *.la *.o .libs); \ + done + if [ -f "$(SWIG_PL_DIR)/native/Makefile" ]; then \ + cd $(SWIG_PL_DIR)/native; $(MAKE) clean; \ +@@ -804,7 +803,7 @@ + fi + for d in $(SWIG_PY_DIR) $(SWIG_PY_DIR)/libsvn_swig_py; \ + do \ +- cd $$d && rm -rf *.lo *.la *.o *.pyc .libs; \ ++ (cd $$d && rm -rf *.lo *.la *.o *.pyc .libs); \ + done + find $(SWIG_PY_SRC_DIR) $(SWIG_PY_DIR) -name "*.pyc" -exec rm {} ';' + +@@ -828,8 +827,7 @@ + fi + for d in $(SWIG_RB_DIR) $(SWIG_RB_DIR)/libsvn_swig_ruby; \ + do \ +- cd $$d; \ +- rm -rf *.lo *.la *.o .libs; \ ++ (cd $$d && rm -rf *.lo *.la *.o .libs); \ + done + + extraclean-swig-rb: clean-swig-rb +--- a/build/generator/gen_base.py ++++ b/build/generator/gen_base.py +@@ -333,7 +333,8 @@ + + class SWIGSource(SourceFile): + def __init__(self, filename): +- SourceFile.__init__(self, filename, build_path_dirname(filename)) ++ SourceFile.__init__(self, filename, ++ build_path_dirname('$(top_srcdir)/' + filename)) + + + lang_abbrev = { +--- a/build/generator/swig/header_wrappers.py ++++ b/build/generator/swig/header_wrappers.py +@@ -52,7 +52,7 @@ + """Write makefile rules for generating SWIG wrappers for Subversion + header files.""" + wrapper_fnames = [] +- python_script = '$(abs_srcdir)/build/generator/swig/header_wrappers.py' ++ python_script = 'build/generator/swig/header_wrappers.py' + makefile.write('GEN_SWIG_WRAPPER = cd $(top_srcdir) && $(PYTHON)' + + ' %s build.conf $(SWIG)\n\n' % python_script) + for fname in self.includes: +--- a/configure.ac ++++ b/configure.ac +@@ -668,6 +668,7 @@ + fi + + AH_BOTTOM( ++#undef /* */ _ + #define N_(x) x + #define U_(x) x + #ifdef ENABLE_NLS +@@ -1355,6 +1356,11 @@ + rm -f .swig_checked + + AC_OUTPUT ++if test "$abs_srcdir" != "$abs_builddir" ++then ++ AC_MSG_NOTICE([Creating build directories]) ++ (cd "$abs_srcdir"; find subversion tools contrib -type d) | xargs $MKDIR ++fi + + # ==== Print final messages to user ========================================== + +--- a/build.conf ++++ b/build.conf +@@ -196,7 +196,7 @@ + description = Subversion Client Library + type = lib + path = subversion/libsvn_client +-libs = libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr apriconv apr ++libs = libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr aprutil apriconv apr + install = lib + msvc-export = svn_client.h private/svn_client_private.h + +@@ -259,7 +259,7 @@ + description = Subversion Repository Access Library + type = lib + path = subversion/libsvn_ra +-libs = libsvn_delta libsvn_subr ra-libs apriconv apr ++libs = libsvn_delta libsvn_subr ra-libs aprutil apriconv apr + # conditionally add more dependencies + add-deps = $(SVN_RA_LIB_DEPS) + add-install-deps = $(SVN_RA_LIB_INSTALL_DEPS) +@@ -703,13 +703,14 @@ + # ---------------------------------------------------------------------------- + # Tests for libsvn_subr + +-[auth-test] +-description = Test platform-specific auth provider access +-type = exe +-path = subversion/tests/libsvn_subr +-sources = auth-test.c +-install = test +-libs = libsvn_test libsvn_subr ++# Fails because it assumes gnome-keyring facilities are available at test time ++#[auth-test] ++#description = Test platform-specific auth provider access ++#type = exe ++#path = subversion/tests/libsvn_subr ++#sources = auth-test.c ++#install = test ++#libs = libsvn_test libsvn_subr + + [cache-test] + description = Test in-memory cache +--- a/subversion/libsvn_ra_serf/update.c ++++ b/subversion/libsvn_ra_serf/update.c +@@ -2536,12 +2536,6 @@ + then go process the pending content. */ + if (!parser_ctx->paused && parser_ctx->pending != NULL) + SVN_ERR(svn_ra_serf__process_pending(parser_ctx, iterpool_inner)); +- +- /* Debugging purposes only! */ +- for (i = 0; i < sess->num_conns; i++) +- { +- serf_debug__closed_conn(sess->conns[i]->bkt_alloc); +- } + } + + /* Ensure that we opened and closed our root dir and that we closed +--- a/subversion/libsvn_ra_serf/util.c ++++ b/subversion/libsvn_ra_serf/util.c +@@ -716,12 +716,6 @@ + + return svn_error_wrap_apr(status, _("Error running context")); + } +- +- /* Debugging purposes only! */ +- for (i = 0; i < sess->num_conns; i++) +- { +- serf_debug__closed_conn(sess->conns[i]->bkt_alloc); +- } + } + svn_pool_destroy(iterpool); + --- subversion-1.7.9.orig/debian/patches/chunksize-integer.patch +++ subversion-1.7.9/debian/patches/chunksize-integer.patch @@ -0,0 +1,13 @@ +Author: W. Martin Borgert +Bug-Debian: 683188 +--- subversion-1.7.9.orig/subversion/bindings/swig/python/svn/core.py ++++ subversion-1.7.9/subversion/bindings/swig/python/svn/core.py +@@ -171,7 +171,7 @@ + # read the rest of the stream + chunks = [ ] + while True: +- data = svn_stream_read(self._stream, SVN_STREAM_CHUNK_SIZE) ++ data = svn_stream_read(self._stream, int(SVN_STREAM_CHUNK_SIZE)) + if not data: + break + chunks.append(data) --- subversion-1.7.9.orig/debian/patches/examples-compile-instructions +++ subversion-1.7.9/debian/patches/examples-compile-instructions @@ -0,0 +1,95 @@ +Fix build instructions for libsvn-doc/examples/*.c. + + +--- a/tools/examples/getlocks_test.c ++++ b/tools/examples/getlocks_test.c +@@ -20,13 +20,11 @@ + * under the License. + * ==================================================================== + * +- * To compile on unix against Subversion and APR libraries, try +- * something like: ++ * To compile on Debian: + * + * cc getlocks_test.c -o getlocks_test \ +- * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \ +- * -L/usr/local/apache2/lib -L/usr/local/lib \ +- * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lapr-0 -laprutil-0 ++ * -I/usr/include/subversion-1 $(pkg-config --cflags apr-1) \ ++ * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 + * + */ + +--- a/tools/examples/headrev.c ++++ b/tools/examples/headrev.c +@@ -20,13 +20,11 @@ + * under the License. + * ==================================================================== + * +- * To compile on unix against Subversion and APR libraries, try +- * something like: ++ * To compile on Debian: + * + * cc headrev.c -o headrev \ +- * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \ +- * -L/usr/local/apache2/lib -L/usr/local/lib \ +- * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lapr-0 -laprutil-0 ++ * -I/usr/include/subversion-1 $(pkg-config --cflags apr-1) \ ++ * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 + * + */ + +--- a/tools/examples/minimal_client.c ++++ b/tools/examples/minimal_client.c +@@ -30,12 +30,10 @@ + * For a much more complex example, the svn cmdline client might be + * considered the 'reference implementation'. + * +- * From a Linux system, a typical commandline compile might look like: ++ * To compile on Debian: + * + * cc minimal_client.c -o minimal_client \ +- * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \ +- * -L/usr/local/apache2/lib -L/usr/local/lib \ +- * -lsvn_client-1 -lapr-0 -laprutil-0 ++ * -I/usr/include/subversion-1 $(pkg-config --cflags apr-1) -lsvn_client-1 + * + */ + +--- a/tools/examples/svnput.c ++++ b/tools/examples/svnput.c +@@ -33,13 +33,10 @@ + * under the License. + * ==================================================================== + * +- * To compile on unix against Subversion and APR libraries, try +- * something like: ++ * To compile on Debian: + * + * cc svnput.c -o svnput \ +- * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \ +- * -L/usr/local/apache2/lib -L/usr/local/lib \ +- * -lsvn_client-1 -lapr-0 -laprutil-0 ++ * -I/usr/include/subversion-1 $(pkg-config --cflags apr-1) -lsvn_client-1 + * + */ + +--- a/tools/examples/testwrite.c ++++ b/tools/examples/testwrite.c +@@ -20,13 +20,11 @@ + * under the License. + * ==================================================================== + * +- * To compile on unix against Subversion and APR libraries, try +- * something like: ++ * To compile on Debian: + * + * cc testwrite.c -o testwrite \ +- * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \ +- * -L/usr/local/apache2/lib -L/usr/local/lib \ +- * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lsvn-fs-1 -lapr-0 -laprutil-0 ++ * -I/usr/include/subversion-1 $(pkg-config --cflags apr-1) \ ++ * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lsvn_fs-1 + * + */ + --- subversion-1.7.9.orig/debian/patches/fix-bdb-version-detection +++ subversion-1.7.9/debian/patches/fix-bdb-version-detection @@ -0,0 +1,21 @@ +berkeley-db.m4: Avoid bdb version detection; just link to libaprutil instead + +In Debian, apu-config --libs does not print dependent libraries (see +#378105). svn relies on this to detect the BDB version. Work around +this by linking to -laprutil1 instead, which will indirectly link to +libdb. + +I don't think this can be sent upstream, as it won't work when +compiling aprutil in-tree. But I'm not certain. + +--- a/build/ac-macros/berkeley-db.m4 ++++ b/build/ac-macros/berkeley-db.m4 +@@ -183,7 +183,7 @@ + SVN_DB_LIBS=["${SVN_DB_LIBS-`$apu_config --libs | $SED -e 's/.*\(-ldb[^[:space:]]*\).*/\1/' | $EGREP -- '-ldb[^[:space:]]*'`}"] + + CPPFLAGS="$SVN_DB_INCLUDES $SVN_APRUTIL_INCLUDES $CPPFLAGS" +- LIBS="`$apu_config --ldflags` $SVN_DB_LIBS $LIBS" ++ LIBS="`$apu_config --ldflags --link-ld` $SVN_DB_LIBS $LIBS" + + if test -n "$svn_berkeley_db_header"; then + SVN_DB_HEADER="#include <$svn_berkeley_db_header>" --- subversion-1.7.9.orig/debian/patches/java-build +++ subversion-1.7.9/debian/patches/java-build @@ -0,0 +1,16 @@ +A hack to get around differences between Sun javah and gcj javah - in Sun +javah, symbols in a nested class use _ as a separator instead of _00024. +Patch is originally from Nobuhiro Iwamatsu, bug #561516. + +--- a/build/generator/templates/makefile.ezt ++++ b/build/generator/templates/makefile.ezt +@@ -99,7 +99,8 @@ + [if-any target.headers][target.varname]_CLASS_FILENAMES =[for target.header_class_filenames] [target.header_class_filenames][end] + [target.varname]_CLASSES =[for target.header_classes] [target.header_classes][end] + $([target.varname]_HEADERS): $([target.varname]_CLASS_FILENAMES) +- [target.link_cmd] -d [target.output_dir] -classpath [target.classes]:$([target.varname]_CLASSPATH) $([target.varname]_CLASSES) ++ [target.link_cmd] -d [target.output_dir] -classpath [target.classes]:$([target.varname]_CLASSPATH) -all [target.classes] ++ cd [target.output_dir]; sed -i s/_00024/_/ *.h + [end][if-any target.sources][target.varname]_SRC =[for target.sources] [target.sources][end] + $([target.varname]_OBJECTS): $([target.varname]_SRC) + [target.link_cmd] -d [target.output_dir] -classpath [target.classes]:$([target.varname]_CLASSPATH) $([target.varname]_SRC) --- subversion-1.7.9.orig/debian/patches/java-osgi-metadata +++ subversion-1.7.9/debian/patches/java-osgi-metadata @@ -0,0 +1,32 @@ +Bug #644438: Ship a OSGi metadata file with the Java bindings. +Patch by Jakub Adam, via upstream r1234864. + + +--- a/Makefile.in ++++ b/Makefile.in +@@ -302,8 +302,11 @@ + + ### Automate JAR creation using Makefile generator's javahl-java.jar + ### property. Enhance generator to support JAR installation. ++JAVAHL_MANIFEST_IN = $(abs_srcdir)/subversion/bindings/javahl/Manifest.in ++JAVAHL_MANIFEST = subversion/bindings/javahl/Manifest + INSTALL_EXTRA_JAVAHL_JAVA=\ +- $(JAR) cf $(JAVAHL_JAR) -C subversion/bindings/javahl/classes org; \ ++ sed s/%bundleVersion/$(PACKAGE_VERSION)/ $(JAVAHL_MANIFEST_IN) > $(JAVAHL_MANIFEST); \ ++ $(JAR) cfm $(JAVAHL_JAR) $(JAVAHL_MANIFEST) -C subversion/bindings/javahl/classes org; \ + $(INSTALL_DATA) $(JAVAHL_JAR) $(DESTDIR)$(javahl_javadir); + + INSTALL_EXTRA_JAVAHL_LIB=@INSTALL_EXTRA_JAVAHL_LIB@ +--- /dev/null ++++ b/subversion/bindings/javahl/Manifest.in +@@ -0,0 +1,10 @@ ++Manifest-Version: 1.0 ++Bundle-ManifestVersion: 2 ++Bundle-Name: Apache Subversion JavaHL API ++Bundle-Vendor: Apache Subversion ++Bundle-SymbolicName: org.apache.subversion.javahl ++Bundle-Version: %bundleVersion ++Export-Package: org.apache.subversion.javahl, ++ org.apache.subversion.javahl.callback, ++ org.apache.subversion.javahl.types, ++ org.tigris.subversion.javahl --- subversion-1.7.9.orig/debian/patches/last-changed-date-charset +++ subversion-1.7.9/debian/patches/last-changed-date-charset @@ -0,0 +1,22 @@ +Bug #290774: Convert $LastChangedDate$ keyword to the local character +set, since it is already rendered in the local language. + +Not accepted upstream: http://svn.haxx.se/dev/archive-2006-04/0730.shtml + +--- a/subversion/libsvn_subr/subst.c ++++ b/subversion/libsvn_subr/subst.c +@@ -200,8 +200,12 @@ + break; + case 'D': /* long format of date of this revision */ + if (date) +- svn_stringbuf_appendcstr(value, +- svn_time_to_human_cstring(date, pool)); ++ { ++ char *date_keyword; ++ char *date_utf8 = svn_time_to_human_cstring (date, pool); ++ svn_utf_cstring_from_utf8(&date_keyword, date_utf8, pool); ++ svn_stringbuf_appendcstr(value, date_keyword); ++ } + break; + case 'r': /* number of this revision */ + if (rev) --- subversion-1.7.9.orig/debian/patches/loosen-sqlite-version-check +++ subversion-1.7.9/debian/patches/loosen-sqlite-version-check @@ -0,0 +1,18 @@ +Bug 608925: The actual ABI compatibility of sqlite3 doesn't seem to +depend on the patchlevel (the x in 3.7.x), so omit that in our sanity +check here. + +This matters in Debian because the sqlite3 library package exports a +slightly more liberal shlibs file than the library version itself. + +--- a/subversion/libsvn_subr/sqlite.c ++++ b/subversion/libsvn_subr/sqlite.c +@@ -740,7 +740,7 @@ + static svn_error_t * + init_sqlite(void *baton, apr_pool_t *pool) + { +- if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER) ++ if (sqlite3_libversion_number()/1000 < SQLITE_VERSION_NUMBER/1000) + { + return svn_error_createf( + SVN_ERR_SQLITE_ERROR, NULL, --- subversion-1.7.9.orig/debian/patches/no-extra-libs +++ subversion-1.7.9/debian/patches/no-extra-libs @@ -0,0 +1,33 @@ +Bug #338302: Use pkg-config instead of '{apr,aprutil,neon}-config --libs' +to improve link stuff. At the time this patch was originally deployed, +it eliminated redundant dependencies on: libssl0.9.8, libldap2, +libexpat2, libxml2, zlib1g. + +--- a/build/ac-macros/apr.m4 ++++ b/build/ac-macros/apr.m4 +@@ -99,9 +99,9 @@ + AC_MSG_ERROR([apr-config --link-ld --libs failed]) + fi + else +- SVN_APR_LIBS="`$apr_config --link-ld`" ++ SVN_APR_LIBS="`pkg-config --libs apr-1`" + if test $? -ne 0; then +- AC_MSG_ERROR([apr-config --link-ld failed]) ++ AC_MSG_ERROR([pkg-config --libs apr-1 failed]) + fi + fi + SVN_APR_LIBS="`SVN_REMOVE_STANDARD_LIB_DIRS($SVN_APR_LIBS)`" +--- a/build/ac-macros/aprutil.m4 ++++ b/build/ac-macros/aprutil.m4 +@@ -103,9 +103,9 @@ + AC_MSG_ERROR([apu-config --link-ld --libs failed]) + fi + else +- SVN_APRUTIL_LIBS="`$apu_config --link-ld`" ++ SVN_APRUTIL_LIBS="`pkg-config --libs apr-util-1`" + if test $? -ne 0; then +- AC_MSG_ERROR([apu-config --link-ld failed]) ++ AC_MSG_ERROR([pkg-config --libs apr-util-1 failed]) + fi + fi + SVN_APRUTIL_LIBS="`SVN_REMOVE_STANDARD_LIB_DIRS($SVN_APRUTIL_LIBS)`" --- subversion-1.7.9.orig/debian/patches/no-extra-libs-2 +++ subversion-1.7.9/debian/patches/no-extra-libs-2 @@ -0,0 +1,95 @@ +More link pruning, which eliminates one package dependency: subversion +-> libneon; nobody but libsvn_ra_neon should link neon directly. Also +hack the apriconv library declaration not to pull in aprutil. (It +might be correct on Windows, I don't know, but we don't need apriconv +_at all_, so we don't want it to pull in aprutil for us.) + +--- a/build.conf ++++ b/build.conf +@@ -109,7 +109,7 @@ + type = exe + path = subversion/svn + libs = libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr +- apriconv apr neon ++ apriconv apr + manpages = subversion/svn/svn.1 + install = bin + +@@ -154,7 +154,7 @@ + description = Subversion repository replicator + type = exe + path = subversion/svnsync +-libs = libsvn_ra libsvn_delta libsvn_subr apr neon ++libs = libsvn_ra libsvn_delta libsvn_subr apr + install = bin + manpages = subversion/svnsync/svnsync.1 + +@@ -606,7 +606,7 @@ + type = lib + path = subversion/bindings/javahl/native + libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff +- libsvn_subr libsvn_fs aprutil apriconv apr neon ++ libsvn_subr libsvn_fs apriconv apr + sources = *.cpp *.c + add-deps = $(javahl_javah_DEPS) $(javahl_java_DEPS) $(javahl_callback_javah_DEPS) $(javahl_types_javah_DEPS) + install = javahl-lib +@@ -1040,7 +1040,7 @@ + + [apriconv] + type = lib +-external-lib = $(SVN_APRUTIL_LIBS) ++external-lib = $(SVN_APR_LIBS) + + [bdb] + type = lib +@@ -1188,7 +1188,7 @@ + path = tools/client-side/svnmucc + sources = svnmucc.c + install = tools +-libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta apriconv apr neon ++libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta apriconv apr + + [diff] + type = exe +--- a/subversion/bindings/swig/perl/native/Makefile.PL.in ++++ b/subversion/bindings/swig/perl/native/Makefile.PL.in +@@ -43,6 +43,12 @@ + ra_serf fs_base fs_util fs_fs/); + + my @ldmodules = map {"-lsvn_$_-1"} (@modules, qw/diff subr/); ++sub libs_line { ++ return join(' ', $apr_ldflags, ++ (map {"-L$_"} @ldpaths), ++ (map {"-lsvn_$_-1"} @_), ++ '-lsvn_swig_perl-1', qx($swig -perl -ldflags)); ++} + + my $apr_shlib_path_var = '@SVN_APR_SHLIB_PATH_VAR@'; + my $cppflags = '@CPPFLAGS@'; +@@ -67,10 +73,6 @@ + " -I$svnlib_builddir", + " -I$swig_srcdir -g"), + OBJECT => q/$(O_FILES)/, +- LIBS => [join(' ', $apr_ldflags, +- (map {"-L$_"} @ldpaths), +- @ldmodules, '-lsvn_swig_perl-1', +- `$swig -perl -ldflags`)], + test => { TESTS => "$swig_srcdir/perl/native/t/*.t" } + ); + +@@ -80,6 +82,7 @@ + $_; + } + ++$config{LIBS} = [libs_line('diff', 'subr')]; + WriteMakefile(%config, NAME => 'SVN::_Core', C => ['core.c'], + PM => {map { ("$swig_srcdir/perl/native/$_.pm" => + "\$(INST_LIBDIR)/$_.pm") } +@@ -94,6 +97,7 @@ + ); + + for (@modules) { ++ $config{LIBS} = [libs_line($_, 'subr')]; + WriteMakefile(%config, + MAKEFILE=> "Makefile.$_", + NAME => "SVN::_".perlish($_), --- subversion-1.7.9.orig/debian/patches/python-builds +++ subversion-1.7.9/debian/patches/python-builds @@ -0,0 +1,117 @@ +Build for multiple python versions. Patch from Matthias Klose + via Ubuntu. Mostly, rename libsvn_swig_py to +libsvn_swig_py2.x. + +Submitted upstream: http://svn.haxx.se/dev/archive-2008-05/0361.shtml + +--- a/Makefile.in ++++ b/Makefile.in +@@ -132,6 +132,7 @@ + APACHE_LDFLAGS = @APACHE_LDFLAGS@ + + SWIG = @SWIG@ ++PYTHON_INCLUDES = @PYTHON_INCLUDES@ + SWIG_PY_INCLUDES = @SWIG_PY_INCLUDES@ -I$(SWIG_SRC_DIR)/python/libsvn_swig_py + SWIG_PY_COMPILE = @SWIG_PY_COMPILE@ + SWIG_PY_LINK = @SWIG_PY_LINK@ +--- a/build/ac-macros/swig.m4 ++++ b/build/ac-macros/swig.m4 +@@ -109,7 +109,8 @@ + AC_CACHE_CHECK([for Python includes], [ac_cv_python_includes],[ + ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" + ]) +- SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" ++ PYTHON_INCLUDES="$ac_cv_python_includes" ++ SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) \$(PYTHON_INCLUDES)" + + if test "$ac_cv_python_includes" = "none"; then + AC_MSG_WARN([python bindings cannot be built without distutils module]) +@@ -282,6 +283,7 @@ + AC_MSG_RESULT([$SWIG_RB_TEST_VERBOSE]) + fi + AC_SUBST(SWIG) ++ AC_SUBST(PYTHON_INCLUDES) + AC_SUBST(SWIG_PY_INCLUDES) + AC_SUBST(SWIG_PY_COMPILE) + AC_SUBST(SWIG_PY_LINK) +--- a/build.conf ++++ b/build.conf +@@ -413,7 +413,7 @@ + type = swig + path = subversion/bindings/swig + sources = core.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_diff libsvn_subr apr + description = Subversion core library bindings + include-runtime = yes +@@ -422,7 +422,7 @@ + type = swig + path = subversion/bindings/swig + sources = svn_client.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_client libsvn_subr apr + nonlibs = swig_core + description = Subversion client library bindings +@@ -431,7 +431,7 @@ + type = swig + path = subversion/bindings/swig + sources = svn_delta.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_delta libsvn_subr apr + nonlibs = swig_core + description = Subversion delta library bindings +@@ -440,7 +440,7 @@ + type = swig + path = subversion/bindings/swig + sources = svn_diff.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_diff libsvn_subr apr + nonlibs = swig_core + description = Subversion diff library bindings +@@ -449,7 +449,7 @@ + type = swig + path = subversion/bindings/swig + sources = svn_fs.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_fs libsvn_subr apr + nonlibs = swig_core + description = Subversion FS library bindings +@@ -458,7 +458,7 @@ + type = swig + path = subversion/bindings/swig + sources = svn_ra.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_ra libsvn_subr apr + nonlibs = swig_core + description = Subversion RA library bindings +@@ -467,7 +467,7 @@ + type = swig + path = subversion/bindings/swig + sources = svn_repos.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_repos libsvn_subr apr + nonlibs = swig_core + description = Subversion repository library bindings +@@ -476,13 +476,13 @@ + type = swig + path = subversion/bindings/swig + sources = svn_wc.i +-libs = libsvn_swig_py libsvn_swig_perl libsvn_swig_ruby ++libs = libsvn_swig_py$(PYVER) libsvn_swig_perl libsvn_swig_ruby + libsvn_wc libsvn_subr apr + nonlibs = swig_core + description = Subversion WC library bindings + + # SWIG utility library for Python modules +-[libsvn_swig_py] ++[libsvn_swig_py$(PYVER)] + type = swig_lib + lang = python + path = subversion/bindings/swig/python/libsvn_swig_py --- subversion-1.7.9.orig/debian/patches/repos-templates +++ subversion-1.7.9/debian/patches/repos-templates @@ -0,0 +1,86 @@ +Bug #210901: Add fully qualified paths to commands in example hook +scripts that get installed as .tmpl files in new repositories. Use +$REPOS/hooks/ as the path, to encourage repository admins to copy the +hooks, not just use them in place. + +--- a/subversion/libsvn_repos/repos.c ++++ b/subversion/libsvn_repos/repos.c +@@ -275,7 +275,7 @@ + + #define PREWRITTEN_HOOKS_TEXT \ + "# For more examples and pre-written hooks, see those in" NL \ +- "# the Subversion repository at" NL \ ++ "# /usr/share/subversion/hook-scripts, and in the repository at" NL \ + "# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and" NL \ + "# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/" NL + +@@ -354,8 +354,11 @@ + "REPOS=\"$1\"" NL + "USER=\"$2\"" NL + "" NL +-"commit-allower.pl --repository \"$REPOS\" --user \"$USER\" || exit 1" NL +-"special-auth-check.py --user \"$USER\" --auth-level 3 || exit 1" NL ++"# Exit on all errors." NL ++"set -e" NL ++"" NL ++"\"$REPOS\"/hooks/commit-allower.pl --repository \"$REPOS\" --user \"$USER\"" NL ++"\"$REPOS\"/hooks/special-auth-check.py --user \"$USER\" --auth-level 3" NL + "" NL + "# All checks passed, so allow the commit." NL + "exit 0" NL; +@@ -442,10 +445,13 @@ + "$SVNLOOK log -t \"$TXN\" \"$REPOS\" | \\" NL + " grep \"[a-zA-Z0-9]\" > /dev/null || exit 1" NL + "" NL ++"# Exit on all errors." NL ++"set -e" NL ++"" NL + "# Check that the author of this commit has the rights to perform" NL + "# the commit on the files and directories being modified." NL +-"commit-access-control.pl \"$REPOS\" \"$TXN\" commit-access-control.cfg || exit 1" +- NL ++"\"$REPOS\"/hooks/commit-access-control.pl \"$REPOS\" $TXN \\" NL ++" \"$REPOS\"/hooks/commit-access-control.cfg" NL + "" NL + "# All checks passed, so allow the commit." NL + "exit 0" NL; +@@ -756,7 +762,7 @@ + "REPOS=\"$1\"" NL + "REV=\"$2\"" NL + NL +-"mailer.py commit \"$REPOS\" \"$REV\" /path/to/mailer.conf" NL; ++"\"$REPOS\"/hooks/mailer.py commit \"$REPOS\" $REV \"$REPOS\"/mailer.conf" NL; + + #undef SCRIPT_NAME + +@@ -817,7 +823,8 @@ + "USER=\"$2\"" NL + "" NL + "# Send email to interested parties, let them know a lock was created:" NL +-"mailer.py lock \"$REPOS\" \"$USER\" /path/to/mailer.conf" NL; ++"\"$REPOS\"/hooks/mailer.py lock \\" NL ++" \"$REPOS\" \"$USER\" \"$REPOS\"/hooks/mailer.conf" NL; + + #undef SCRIPT_NAME + +@@ -876,7 +883,8 @@ + "USER=\"$2\"" NL + "" NL + "# Send email to interested parties, let them know a lock was removed:" NL +-"mailer.py unlock \"$REPOS\" \"$USER\" /path/to/mailer.conf" NL; ++"\"$REPOS\"/hooks/mailer.py unlock \\" NL ++" \"$REPOS\" \"$USER\" \"$REPOS\"/hooks/mailer.conf" NL; + + #undef SCRIPT_NAME + +@@ -941,8 +949,8 @@ + "PROPNAME=\"$4\"" NL + "ACTION=\"$5\"" NL + "" NL +-"mailer.py propchange2 \"$REPOS\" \"$REV\" \"$USER\" \"$PROPNAME\" " +-"\"$ACTION\" /path/to/mailer.conf" NL; ++"\"$REPOS\"/hooks/mailer.py propchange2 \"$REPOS\" $REV \\" NL ++" \"$USER\" \"$PROPNAME\" \"$ACTION\" \"$REPOS\"/hooks/mailer.conf" NL; + + #undef SCRIPT_NAME + --- subversion-1.7.9.orig/debian/patches/rpath +++ subversion-1.7.9/debian/patches/rpath @@ -0,0 +1,86 @@ +Prevent the linker from adding an rpath to shared libraries. Original +patch by David Kimdon . The basic theory is: + +- Split the $(LINK) makefile macro into $(LINK) and $(LINK_LIB). +- Comment out LD_RUN_PATH in the Perl makefiles. +- Use libtool instead of apxs to install the apache modules. + libtool relinks without rpath in this case, apxs obviously doesn't. + +--- a/Makefile.in ++++ b/Makefile.in +@@ -203,10 +203,10 @@ + COMPILE_JAVAHL_JAVAC = $(JAVAC) $(JAVAC_FLAGS) + COMPILE_JAVAHL_JAVAH = $(JAVAH) + +-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 = $(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) + + # 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) +@@ -736,7 +736,9 @@ + ./config.status subversion/bindings/swig/perl/native/Makefile.PL + + $(SWIG_PL_DIR)/native/Makefile: $(SWIG_PL_DIR)/native/Makefile.PL +- cd $(SWIG_PL_DIR)/native; $(PERL) Makefile.PL ++ cd $(SWIG_PL_DIR)/native; \ ++ $(PERL) Makefile.PL INSTALLDIRS=vendor; \ ++ sed -i -e '/^LD_RUN_PATH/s/^/#/' Makefile Makefile.[a-z]* + + # There is a "readlink -f" command on some systems for the same purpose, + # but it's not as portable (e.g. Mac OS X doesn't have it). These should +--- a/build.conf ++++ b/build.conf +@@ -487,7 +487,7 @@ + lang = python + path = subversion/bindings/swig/python/libsvn_swig_py + libs = libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_subr apriconv apr +-link-cmd = $(LINK) ++link-cmd = $(LINK_LIB) $(SWIG_PY_LIBS) + install = swig-py-lib + # need special build rule to include -DSWIGPYTHON + compile-cmd = $(COMPILE_SWIG_PY) +@@ -510,7 +510,7 @@ + lang = ruby + path = subversion/bindings/swig/ruby/libsvn_swig_ruby + libs = libsvn_client libsvn_wc libsvn_delta libsvn_subr apriconv apr +-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) +--- a/build/generator/gen_base.py ++++ b/build/generator/gen_base.py +@@ -407,7 +407,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') +@@ -459,6 +459,7 @@ + extmap = self.gen_obj._extension_map + self.objext = extmap['exe', 'object'] + self.filename = build_path_join(self.path, name + extmap['exe', 'target']) ++ self.link_cmd = '$(LINK)' + + self.manpages = options.get('manpages', '') + self.testing = options.get('testing') +--- a/build/generator/templates/makefile.ezt ++++ b/build/generator/templates/makefile.ezt +@@ -126,7 +126,7 @@ + ######################################## + [for areas] + [is areas.type "apache-mod"]install-mods-shared:[for areas.files] [areas.files.fullname][end][for areas.files] +- cd [areas.files.dirname] ; $(MKDIR) "$(APACHE_LIBEXECDIR)" ; $(INSTALL_MOD_SHARED) -n [areas.files.name] [areas.files.filename][end] ++ cd [areas.files.dirname] ; $(MKDIR) "$(APACHE_LIBEXECDIR)" ; $(INSTALL_LIB) [areas.files.filename] $(APACHE_LIBEXECDIR)[end] + [else]install-[areas.type]: [for areas.files][if-index areas.files first][else] [end][areas.files.fullname][end] [for areas.apache_files] [areas.apache_files.fullname][end] + $(MKDIR) $(DESTDIR)$([areas.varname]dir)[for areas.files][is areas.type "locale"] + $(MKDIR) [areas.files.installdir] --- subversion-1.7.9.orig/debian/patches/ruby-no-strict-aliasing +++ subversion-1.7.9/debian/patches/ruby-no-strict-aliasing @@ -0,0 +1,15 @@ +It seems swig is generating _really_ bad code here, or something. +Whatever it is, this line suppresses 1323 warnings, any of which might +be real bugs with real consequences. + +--- a/Makefile.in ++++ b/Makefile.in +@@ -138,7 +138,7 @@ + SWIG_PY_LIBS = @SWIG_PY_LIBS@ + SWIG_PL_INCLUDES = @SWIG_PL_INCLUDES@ + SWIG_RB_INCLUDES = @SWIG_RB_INCLUDES@ -I$(SWIG_SRC_DIR)/ruby/libsvn_swig_ruby +-SWIG_RB_COMPILE = @SWIG_RB_COMPILE@ ++SWIG_RB_COMPILE = @SWIG_RB_COMPILE@ -fno-strict-aliasing + SWIG_RB_LINK = @SWIG_RB_LINK@ + SWIG_RB_LIBS = @SWIG_RB_LIBS@ + SWIG_RB_SITE_LIB_DIR = @SWIG_RB_SITE_LIB_DIR@ --- subversion-1.7.9.orig/debian/patches/ruby-test-info +++ subversion-1.7.9/debian/patches/ruby-test-info @@ -0,0 +1,29 @@ +--- a/subversion/bindings/swig/ruby/test/test_info.rb ++++ b/subversion/bindings/swig/ruby/test/test_info.rb +@@ -26,9 +26,12 @@ + + info = make_info(commit_info.revision) + assert_equal(@author, info.author) +- assert_equal(commit_info.date, info.date) +- assert_equal(commit_info.revision, info.revision) +- assert_equal(log, info.log) ++ # FIXME: Strange debian buildd error #1 ++ # https://buildd.debian.org/fetch.cgi?pkg=subversion;ver=1.6.5dfsg-1;arch=powerpc;stamp=1250968748 ++ # https://buildd.debian.org/fetch.cgi?pkg=subversion;ver=1.6.11dfsg-1;arch=powerpc;stamp=1271760487 ++ # assert_equal(commit_info.date, info.date) ++ # assert_equal(commit_info.revision, info.revision) ++ # assert_equal(log, info.log) + end + + def test_dirs_changed +@@ -47,7 +50,9 @@ + + info = make_info(commit_info.revision) + assert_equal(["/", "#{dir}/"], info.changed_dirs) +- assert_equal(commit_info.revision, info.revision) ++ # FIXME: Strange Debian buildd error #2 ++ # https://buildd.debian.org/fetch.cgi?pkg=subversion;ver=1.6.5dfsg-1;arch=powerpc;stamp=1250968748 ++ # assert_equal(commit_info.revision, info.revision) + assert_equal(log, info.log) + end + --- subversion-1.7.9.orig/debian/patches/ruby-test-svnserve-race +++ subversion-1.7.9/debian/patches/ruby-test-svnserve-race @@ -0,0 +1,56 @@ +Bug #378837: Ruby testsuite: wait for svnserve to start before +connecting to it. This mainly affects very slow machines - observed +on various arm and m68k builds. + +Thanks to Roman Zippel, Kobayashi Noritada, Wouter Verhelst and Martin +Michlmayr. + +--- a/subversion/bindings/swig/ruby/test/util.rb ++++ b/subversion/bindings/swig/ruby/test/util.rb +@@ -19,6 +19,7 @@ + + require "fileutils" + require "pathname" ++require "socket" + require "svn/util" + require "tmpdir" + +@@ -250,11 +251,7 @@ + "-d", "--foreground") + } + pid, status = Process.waitpid2(@svnserve_pid, Process::WNOHANG) +- if status and status.exited? +- if $DEBUG +- STDERR.puts "port #{port} couldn't be used for svnserve" +- end +- else ++ if wait_until_svnserve_gets_available_at(port) + # svnserve started successfully. Note port number and cease + # startup attempts. + @svnserve_port = port +@@ -320,4 +317,25 @@ + include Svnserve + extend SetupEnvironment + end ++ ++ # Waits until svnserve gets available at port +port+, avoiding the race ++ # condition between starting up a svnserve process and trying to connect ++ # to it (Bug#378837 in Debian's BTS). ++ def wait_until_svnserve_gets_available_at(port) ++ 1000.times do |n| ++ begin ++ pid, status = Process.waitpid2(@svnserve_pid, Process::WNOHANG) ++ if status and status.exited? ++ STDERR.puts "port #{port} couldn't be used for svnserve" ++ return false ++ end ++ TCPSocket.new(@svnserve_host, port).close ++ rescue Errno::ECONNREFUSED ++ sleep(n < 10 ? 0.2 : 0.5) ++ else ++ return true ++ end ++ end ++ raise "svnserve couldn't get available at port #{port}" ++ end + end --- subversion-1.7.9.orig/debian/patches/ruby-test-wc +++ subversion-1.7.9/debian/patches/ruby-test-wc @@ -0,0 +1,26 @@ +Recent APR 1.4 includes some hash order randomization for security +purposes. This broke the Subversion testsuites in various ways. Most +of them were fixed in 1.7 already but this one hasn't been. It is from +upstream trunk, r1327373. + + +--- a/subversion/bindings/swig/ruby/test/test_wc.rb ++++ b/subversion/bindings/swig/ruby/test/test_wc.rb +@@ -326,12 +326,16 @@ + ignored_errors = [] + callbacks.ignored_errors = ignored_errors + access.walk_entries(@wc_path, callbacks) ++ sorted_ignored_errors = ignored_errors.sort_by {|path, err| path} ++ sorted_ignored_errors = sorted_ignored_errors.collect! do |path, err| ++ [path, err.class] ++ end + assert_equal([ + [@wc_path, Svn::Error::Cancelled], + [path1, Svn::Error::Cancelled], + [path2, Svn::Error::Cancelled], + ], +- ignored_errors.collect {|path, err| [path, err.class]}) ++ sorted_ignored_errors) + end + end + end --- subversion-1.7.9.orig/debian/patches/ruby-typemap-digest +++ subversion-1.7.9/debian/patches/ruby-typemap-digest @@ -0,0 +1,28 @@ +From: Roman Zippel +Date: Mon, 18 Sep 2006 01:05:02 +0200 +Subject: Change the ruby 'digest' typemaps to tolerate NULL pointers. + +Bug #387996: I looked at the failing self tests [on m68k]. The first +one is a bug in the created wrapper. The basic problem is that in +svn_delta.c:_wrap_svn_txdelta_apply_wrapper() the value of temp3 is not +modified by svn_txdelta_apply_wrapper(), so the return is basically +random. In this case the stack is clear and svn_md5_digest_to_cstring() +returns a NULL, which rb_str_new2() doesn't like. + +The easiest fix is to change the typemap in svn_types.swg so it can deal +with the NULL pointer. (BTW I tried returning Qnil here, but that +doesn't work well output_helper.) + +Sent upstream: http://svn.haxx.se/dev/archive-2006-09/0536.shtml + +--- a/subversion/bindings/swig/include/svn_types.swg ++++ b/subversion/bindings/swig/include/svn_types.swg +@@ -1066,7 +1066,7 @@ + #ifdef SWIGRUBY + %typemap(argout) unsigned char digest[ANY] { + char *digest_string = (char *)svn_md5_digest_to_cstring($1, _global_pool); +- %append_output(rb_str_new2(digest_string)); ++ %append_output(rb_str_new2(digest_string ? digest_string : "")); + } + #endif + --- subversion-1.7.9.orig/debian/patches/series +++ subversion-1.7.9/debian/patches/series @@ -0,0 +1,25 @@ +build-fixes +java-build +last-changed-date-charset +no-extra-libs +no-extra-libs-2 +repos-templates +rpath +ruby-no-strict-aliasing +ruby-test-svnserve-race +ruby-typemap-digest +ssh-no-controlmaster +svnshell +apr-abi1 +apr-abi2 +fix-bdb-version-detection +python-builds +examples-compile-instructions +loosen-sqlite-version-check +apache_module_dependency +workaround_EINVAL_on_kfreebsd +java-osgi-metadata +chunksize-integer.patch +CVE-2013-1968.patch +CVE-2013-2112.patch +ruby-test-wc --- subversion-1.7.9.orig/debian/patches/ssh-no-controlmaster +++ subversion-1.7.9/debian/patches/ssh-no-controlmaster @@ -0,0 +1,38 @@ +Bug #413102: Avoid accidentally becoming an ssh ControlMaster. + +If you set ControlMaster via your ssh config: +.ssh/config: +Host * + ControlMaster auto + Controlpath ~/.ssh/master-%r@%h:%p + +you can get 'svn: Can't write to connection: Broken pipe' with certain +ssh commands, because svn can open multiple ssh sessions and kill them +at unpredictable times. + +I don't really think the problem is either svn's or openssh's fault, +but this is the obvious way to avoid it. We will still use ssh +connection sharing, but only if a ControlMaster is already present. + +--- a/subversion/libsvn_subr/config_file.c ++++ b/subversion/libsvn_subr/config_file.c +@@ -1027,7 +1027,7 @@ + "### passed to the tunnel agent as @.) If the" NL + "### built-in ssh scheme were not predefined, it could be defined" NL + "### as:" NL +- "# ssh = $SVN_SSH ssh -q" NL ++ "# ssh = $SVN_SSH ssh -q -o ControlMaster=no" NL + "### If you wanted to define a new 'rsh' scheme, to be used with" NL + "### 'svn+rsh:' URLs, you could do so as follows:" NL + "# rsh = rsh" NL +--- a/subversion/libsvn_ra_svn/client.c ++++ b/subversion/libsvn_ra_svn/client.c +@@ -391,7 +391,7 @@ + * versions have it too. If the user is using some other ssh + * implementation that doesn't accept it, they can override it + * in the [tunnels] section of the config. */ +- val = "$SVN_SSH ssh -q"; ++ val = "$SVN_SSH ssh -q -o ControlMaster=no"; + } + + if (!val || !*val) --- subversion-1.7.9.orig/debian/patches/svnshell +++ subversion-1.7.9/debian/patches/svnshell @@ -0,0 +1,24 @@ +Bug #234462: The error messages that svnshell spits out for unknown +commands are confusing. They should be replaced by a "Unknown command." +error message. Upstream says we have no sense of humor. (: + +Patch from Roland Illig . + +--- a/tools/examples/svnshell.py ++++ b/tools/examples/svnshell.py +@@ -56,14 +56,8 @@ + def postcmd(self, stop, line): + self._setup_prompt() + +- _errors = ["Huh?", +- "Whatchoo talkin' 'bout, Willis?", +- "Say what?", +- "Nope. Not gonna do it.", +- "Ehh...I don't think so, chief."] +- + def default(self, line): +- print(self._errors[randint(0, len(self._errors) - 1)]) ++ print "Unknown command." + + def do_cat(self, arg): + """dump the contents of a file""" --- subversion-1.7.9.orig/debian/patches/workaround_EINVAL_on_kfreebsd +++ subversion-1.7.9/debian/patches/workaround_EINVAL_on_kfreebsd @@ -0,0 +1,11 @@ +--- a/subversion/bindings/swig/ruby/test/util.rb ++++ b/subversion/bindings/swig/ruby/test/util.rb +@@ -332,6 +332,8 @@ + TCPSocket.new(@svnserve_host, port).close + rescue Errno::ECONNREFUSED + sleep(n < 10 ? 0.2 : 0.5) ++ rescue Errno::EINVAL ++ sleep(n < 10 ? 0.2 : 0.5) + else + return true + end --- subversion-1.7.9.orig/debian/python-subversion.README.Debian +++ subversion-1.7.9/debian/python-subversion.README.Debian @@ -0,0 +1 @@ +See /usr/bin/svnshell for an example that uses the python bindings. --- subversion-1.7.9.orig/debian/python-subversion.dirs +++ subversion-1.7.9/debian/python-subversion.dirs @@ -0,0 +1 @@ +usr/bin --- subversion-1.7.9.orig/debian/python-subversion.examples +++ subversion-1.7.9/debian/python-subversion.examples @@ -0,0 +1 @@ +tools/examples/*.py --- subversion-1.7.9.orig/debian/python-subversion.install +++ subversion-1.7.9/debian/python-subversion.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/*/libsvn_swig_py*.so.* +debian/tmp/usr/lib/python* --- subversion-1.7.9.orig/debian/python-subversion.lintian-overrides +++ subversion-1.7.9/debian/python-subversion.lintian-overrides @@ -0,0 +1,2 @@ +# nobody but us will ever link to this, so we don't ship a shlibs file +no-shlibs-control-file usr/lib/*/libsvn_swig_py2.*-1.so.* --- subversion-1.7.9.orig/debian/ruby-svn.install +++ subversion-1.7.9/debian/ruby-svn.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/*/libsvn_swig_ruby*.so.* +debian/tmp/usr/lib/ruby --- subversion-1.7.9.orig/debian/ruby-svn.lintian-overrides +++ subversion-1.7.9/debian/ruby-svn.lintian-overrides @@ -0,0 +1,2 @@ +# nobody but us will ever link to this, so we don't ship a shlibs file +no-shlibs-control-file usr/lib/*/libsvn_swig_ruby-1.so.* --- subversion-1.7.9.orig/debian/rules +++ subversion-1.7.9/debian/rules @@ -0,0 +1,421 @@ +#!/usr/bin/make -f + +# DEB_BUILD_OPTIONS supported: +# noopt Compile with gcc -O0 rather than -O2 +# nostrip Do not strip binaries and libraries +# debug Enable additional debug support +# nocheck Skip test suites (synonym 'notest') +# with-javahl, no-javahl | +# with-apache, no-apache | enable/disable certain packages +# with-ruby, no-ruby | + +export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +export DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) +export DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + +# Fully functional Java support is still a bit spotty on some Debian +# architectures. DISABLE_JAVAHL_ARCHS overrides ENABLE_JAVAHL=yes. +# Note: the Build-Depends line in debian/control must be kept in sync +# with DISABLE_JAVAHL_ARCHS. + +ENABLE_JAVAHL := yes +DISABLE_JAVAHL_ARCHS := alpha arm hppa m68k mips mipsel hurd-i386 +ifneq (,$(filter $(DEB_HOST_ARCH), $(DISABLE_JAVAHL_ARCHS))) + ENABLE_JAVAHL := +endif + +# We may need to disable libapache2-svn and/or libsvn-ruby*. +ENABLE_APACHE := no +ENABLE_RUBY := yes + +DEB_BUILDDIR := BUILD +MAKE_B := $(MAKE) -C $(DEB_BUILDDIR) + +export LANG := C +export HOME := $(DEB_BUILDDIR)/dummy_home + +include /usr/share/quilt/quilt.make + +# ENABLE_FOO -> DEB_OPT_WITH_FOO=1 +# DEB_BUILD_OPTIONS='foo bar' -> DEB_OPT_FOO=1, DEB_OPT_BAR=1 +# DEB_BUILD_OPTIONS='no-foo' -> DEB_OPT_WITH_FOO="" +$(foreach o, JAVAHL APACHE RUBY, $(if $(filter y yes 1,$(ENABLE_$o)), \ + $(eval DEB_OPT_WITH_$o := 1),$(eval DEB_OPT_WITH_$o :=))) +d_b_o:=$(shell echo "$$DEB_BUILD_OPTIONS" | tr 'a-z-,' 'A-Z_ ') +$(foreach o, $(d_b_o), \ + $(if $(findstring =,$o), $(eval DEB_OPT_$o), $(eval DEB_OPT_$o := 1))) +$(foreach o, $(filter NO_%,$(d_b_o)), $(eval DEB_OPT_$(subst NO_,WITH_,$o) :=)) +$(if $(DEB_OPT_PARALLEL),$(eval MAKEFLAGS += -j$(DEB_OPT_PARALLEL))) + +# How to fix "#!/usr/bin/env " lines: $(call fix_shebangs_in, /your/dir) +fix_shebangs_in = \ + find $1 -type f | xargs -r egrep -m1 -c '^\#! ?/' | sed -n 's/:1//p' |\ + xargs -r sed -i -e 's:^\#! */usr/bin/env perl.*:\#!/usr/bin/perl -w:' \ + -e 's:^\#! */usr/bin/env pyth.*:\#!/usr/bin/python:' \ + -e 's:^\#! */usr/bin/env ruby.*:\#!/usr/bin/$(RUBY):' + +PERL_DIR := $(DEB_BUILDDIR)/subversion/bindings/swig/perl/native +PY_DIR := $(DEB_BUILDDIR)/subversion/bindings/swig/python +PYVERSIONS := $(shell pyversions -vi) + +allpy = \ + set -e; for v in $(PYVERSIONS); do \ + $(RM) $(PY_DIR); \ + ln -fs python$$v $(PY_DIR); \ + pylib=$$(python$$v -c 'from distutils import sysconfig; print sysconfig.get_python_lib()'); \ + $1; \ + done + +libdir := /usr/lib/$(DEB_HOST_MULTIARCH) +confflags := \ + --prefix=/usr \ + --libdir=$(libdir) \ + --mandir=\$${prefix}/share/man \ + --with-custom-libtool=libtool \ + --with-apr=/usr \ + --with-apr-util=/usr \ + --with-neon=/usr \ + --disable-neon-version-check \ + --with-serf=/usr \ + --with-berkeley-db=:::db \ + --with-sasl=/usr \ + --with-editor=/usr/bin/editor \ + --with-ruby-sitedir=/usr/lib/ruby \ + --with-swig=/usr \ + --with-kwallet \ + --with-gnome-keyring + +ifdef DEB_OPT_DEBUG + confflags+= --enable-debug +endif +export EXTRA_CFLAGS := -O2 +ifdef DEB_OPT_NOOPT + EXTRA_CFLAGS := -O0 +endif + +export DH_OPTIONS +ifdef DEB_OPT_WITH_JAVAHL + # jikes 1.22 cannot compile javahl. + confflags += --enable-javahl --without-jikes \ + --with-jdk=/usr/lib/jvm/java-gcj \ + --with-junit=/usr/share/java/junit.jar +else + DH_OPTIONS += -Nlibsvn-java + confflags += --disable-javahl +endif + +ifdef DEB_OPT_WITH_APACHE + confflags += --with-apxs=/usr/bin/apxs2 --disable-mod-activation +else + confflags += --without-apxs + DH_OPTIONS += -Nlibapache2-svn +endif + +ifdef DEB_OPT_WITH_RUBY + RUBY := ruby1.8 + rb_defs := SWIG_RB_SITE_LIB_DIR=$(shell $(RUBY) -rrbconfig -e "print RbConfig::CONFIG['vendordir']") + rb_defs += SWIG_RB_SITE_ARCH_DIR=$(shell $(RUBY) -rrbconfig -e "print RbConfig::CONFIG['vendorarchdir']") +else + DH_OPTIONS += -Nruby-svn -Nlibsvn-ruby -Nlibsvn-ruby1.8 + RUBY := fooby +endif + + +# Set autoconf cross-compile mode correctly. +# Also disable testsuite if cross-compiling. +ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE)) + confflags += --build $(DEB_HOST_GNU_TYPE) +else + confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) + DEB_OPT_NOCHECK := 1 +endif + + +# I'm not trying to be difficult: this check exists because building as +# root really _does_ fail. The failure mode as of 1.4.0 is test 17 +# from switch_tests.py. Upstream response is "so don't build as root". +# (fakeroot does not fail, as it does not wrap the access(2) syscall.) +# +# We run this code from build-arch, since that's what actually fails as +# root, but also from autogen, since that will halt the build earlier. +define DONT_BE_ROOT + @if [ $$(id -u) = 0 ] && [ -z "$(FAKEROOTKEY)" ]; then \ + echo >&2 "***"; \ + echo >&2 "*** Building as root is not supported ***"; \ + false; \ + fi +endef + +debian/stamp-autogen: $(QUILT_STAMPFN) + $(DONT_BE_ROOT) + ./autogen.sh + touch $@ + +debian/stamp-configure: $(QUILT_STAMPFN) debian/stamp-autogen + dh_testdir + + test -e patches || ln -s debian/patches patches + mkdir -p $(DEB_BUILDDIR) $(HOME) + cd $(DEB_BUILDDIR) && \ + PYTHON=/usr/bin/python RUBY=/usr/bin/$(RUBY) \ + $(CURDIR)/configure $(confflags) + + # Subversion upstream ships with Swig 1.3.25 pregenerated + # files, which may interact badly with the build if Debian swig + # is not version 1.3.25 - particularly with swig 1.3.24. + # Thus we unconditionally delete the pregenerated files. + +$(MAKE_B) extraclean-swig + for v in $(PYVERSIONS); do \ + cp -la $(PY_DIR) $(PY_DIR)$$v; \ + done + $(RM) -r $(PY_DIR) + + touch $@ + +build: debian/stamp-build-arch debian/stamp-build-indep + +check_defs := CLEANUP=1 LC_ALL=C +check_swig := check-swig-py check-swig-pl $(if $(DEB_OPT_WITH_RUBY),check-swig-rb) +check_all := $(check_swig) $(if $(DEB_OPT_WITH_JAVAHL),check-javahl) check +check-help: + @echo "$(MAKE) $(check_all)" + +check check-swig-rb check-javahl: debian/stamp-build-arch + +$(MAKE_B) $@ $(check_defs) + +check-swig-pl: debian/stamp-build-arch + +$(MAKE_B) $@ $(check_defs) + $(MAKE) -C $(PERL_DIR) test LC_ALL=C + +check-swig-py: debian/stamp-build-arch + $(call allpy, \ + $(MAKE_B) $@ PYTHON=python$$v PYVER=$$v $(check_defs)) + +build-arch: debian/stamp-build-arch +debian/stamp-build-arch: debian/stamp-configure + dh_testdir + $(DONT_BE_ROOT) + + # note: autogen-swig does not support -jN + $(call allpy, $(MAKE_B) -j1 autogen-swig) + +$(MAKE_B) all tools + # Run svn once, to make sure it populates $(HOME)/.subversion/* + $(DEB_BUILDDIR)/subversion/svn/svn --version > /dev/null + $(call allpy, \ + $(MAKE_B) swig-py PYTHON=python$$v PYVER=$$v \ + PYTHON_INCLUDES=-I/usr/include/python$$v \ + swig_pydir=$$pylib/libsvn swig_pydir_extra=$$pylib/svn) + # note: swig-pl seems to have trouble with -jN + +$(MAKE_B) -j1 swig-pl + $(MAKE) -C $(PERL_DIR) all \ + OPTIMIZE="-g -Wall $(EXTRA_CFLAGS)" +ifdef DEB_OPT_WITH_RUBY + +$(MAKE_B) swig-rb $(rb_defs) +endif +ifdef DEB_OPT_WITH_JAVAHL + +$(MAKE_B) -j1 javahl +endif + touch $@ + +ifndef DEB_OPT_NOCHECK + @echo "###################################################" + @echo "Running testsuite - may take a while. To disable," + @echo "use DEB_BUILD_OPTIONS=nocheck or edit debian/rules." + @echo + $(MAKE) -f debian/rules $(check_swig) + + ifdef DEB_OPT_WITH_JAVAHL + # This fails on current free JVMs, according to Blair Zajac. + # Thus the "-" prefix, to ignore failure, for now. + -$(MAKE) -f debian/rules check-javahl + endif + + # Run 'check' last, as it takes longest. 'cat tests.log' is for + # obtaining diagnostics from buildd logs. + @if ! $(MAKE) -f debian/rules check; then \ + echo "###################################################"; \ + echo "Testsuite failed, 'tests.log' follows:"; echo; \ + cat $(DEB_BUILDDIR)/tests.log; \ + exit 1; \ + fi +endif + touch $@ + +build-indep: debian/stamp-build-indep +debian/stamp-build-indep: debian/stamp-configure + +$(MAKE_B) doc-api + touch $@ + +clean: unpatch + dh_testdir + dh_clean + $(RM) patches + ! [ -f $(DEB_BUILDDIR)/Makefile ] || $(MAKE_B) extraclean-swig distclean + $(RM) -r $(DEB_BUILDDIR) + $(RM) -r subversion/bindings/swig/ruby/test/.test-result + $(RM) build-outputs.mk gen-make.opts subversion/svn_private_config.h.in + $(RM) build/transform_libtool_scripts.sh + find -name \*.pyc -exec $(RM) {} + + # these are (re)generated by autogen.sh + $(RM) subversion/bindings/swig/proxy/*.swg + $(RM) configure build/ltmain.sh build/libtool.m4 build/lt*.m4 + $(RM) build/config.sub build/config.guess + $(RM) debian/stamp-* + +debian/stamp-install-indep: debian/stamp-build-indep + dh_prep -i + dh_installdirs -i + +ifdef DEB_OPT_WITH_JAVAHL + $(MAKE_B) install-javahl-java \ + DESTDIR=$(CURDIR)/debian/tmp \ + javahl_javadir=/usr/share/java \ + javahl_javahdir=/usr/include/svn-javahl +endif + + dh_install -i + + mkdir -p debian/libsvn-doc/usr/share/doc/libsvn1 + mkdir -p debian/libsvn-doc/usr/share/doc/libsvn-doc + cp -a $(DEB_BUILDDIR)/doc/doxygen/html \ + debian/libsvn-doc/usr/share/doc/libsvn1/ + $(RM) debian/libsvn-doc/usr/share/doc/libsvn1/html/jquery.js + ln -s ../libsvn1/html debian/libsvn-doc/usr/share/doc/libsvn-doc/ + mkdir debian/libsvn-doc/usr/share/doc/libsvn1/examples + ln -s ../libsvn1/examples debian/libsvn-doc/usr/share/doc/libsvn-doc/ + + # Install files for 'subversion-tools' package. + install $(DEB_BUILDDIR)/tools/backup/hot-backup.py \ + debian/subversion-tools/usr/bin/svn-hot-backup + + rm debian/subversion-tools/usr/share/subversion/hook-scripts/*.in + rm -r debian/subversion-tools/usr/share/subversion/hook-scripts/mailer/tests +ifndef DEB_OPT_WITH_RUBY + rm debian/subversion-tools/usr/share/subversion/hook-scripts/*.rb +endif + + # Fix some scripts not to use #!/usr/bin/env. + $(call fix_shebangs_in, debian/*/usr/bin \ + debian/subversion-tools/usr/share/subversion/hook-scripts) + cd debian/subversion-tools/usr/share/subversion/hook-scripts; \ + chmod 0755 commit-email.pl commit-access-control.pl \ + mailer/mailer.py verify-po.py svnperms.py; + + # Remove suffixes from binaries in /usr/bin + prename 's/\.(sh|pl|rb|py)$$//' debian/*/usr/bin/* + + pod2man -c 'User Commands' -r "" debian/contrib/svn-clean \ + $(DEB_BUILDDIR)/svn-clean.1 + + touch $@ + +debian/stamp-install-arch: debian/stamp-build-arch + dh_prep -s + dh_installdirs -s + + $(MAKE_B) local-install install-tools \ + DESTDIR=$(CURDIR)/debian/tmp toolsdir=/usr/bin + sed -i 's:/usr/lib/\([^/]*/\)?lib\([^ ]*\).la:-l\1:g' debian/tmp/usr/lib/*/*.la + + $(call allpy, \ + $(MAKE_B) install-swig-py DESTDIR=$(CURDIR)/debian/tmp \ + PYTHON=python$$v PYVER=$$v \ + swig_pydir=$$pylib/libsvn swig_pydir_extra=$$pylib/svn) + $(RM) debian/tmp/usr/lib/python*/*-packages/libsvn/*.la + $(RM) debian/tmp/usr/lib/python*/*-packages/libsvn/*.a + +ifdef DEB_OPT_WITH_JAVAHL + $(MAKE_B) install-javahl \ + DESTDIR=$(CURDIR)/debian/tmp \ + javahl_javadir=/usr/share/java \ + javahl_javahdir=/usr/include/svn-javahl +endif + + $(MAKE_B) install-swig-pl-lib \ + DESTDIR=$(CURDIR)/debian/tmp + $(MAKE) -C $(PERL_DIR) install \ + MAN3EXT=3perl DESTDIR=$(CURDIR)/debian/tmp + +ifdef DEB_OPT_WITH_RUBY + $(MAKE_B) install-swig-rb $(rb_defs) \ + DESTDIR=$(CURDIR)/debian/tmp + find debian/tmp/usr/lib/ruby \( -name \*.a -o -name \*.la \) -exec $(RM) {} + +endif + + cd debian/tmp/$(libdir); for lib in ra fs auth swig; do \ + $(RM) libsvn_$${lib}_*.so libsvn_$${lib}_*.la; \ + done + cd debian/tmp/$(libdir); $(RM) libsvn_swig*.a libsvnjavahl.a libsvnjavahl.la + # Intermediate hack, until we can remove the rest of the .la files. + sed -i "/dependency_libs/s/=.*/=''/" debian/tmp/$(libdir)/*.la + dh_install -s +ifdef DEB_OPT_WITH_JAVAHL + mkdir -p debian/libsvn-java/$(libdir) + mv debian/libsvn-java/usr/lib/jni debian/libsvn-java/$(libdir)/ +endif + ln -s libsvn_ra_neon-1.so.1 debian/libsvn1/$(libdir)/libsvn_ra_dav-1.so.1 + + install -m644 tools/client-side/bash_completion \ + debian/subversion/etc/bash_completion.d/subversion + +ifdef DEB_OPT_WITH_APACHE + install subversion/mod_authz_svn/INSTALL \ + debian/libapache2-svn/usr/share/doc/libapache2-svn/INSTALL.authz +endif + + cp tools/examples/svnshell.py debian/python-subversion/usr/bin/svnshell + $(call fix_shebangs_in, debian/python-subversion/usr/bin/svnshell) + + touch $@ + +binary-indep: debian/stamp-install-indep + dh_testdir + dh_testroot + dh_link -i + dh_installdocs -i + dh_installexamples -i + $(call fix_shebangs_in, debian/*/usr/share/doc/*/examples) + dh_installman -i + dh_installchangelogs -i CHANGES + dh_lintian -i + dh_compress -i + dh_fixperms -i + dh_perl -i + dh_installdeb -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i + +binary-arch: debian/stamp-install-arch + dh_testdir + dh_testroot + dh_link -s + dh_installdocs -s + dh_installexamples -s + $(call fix_shebangs_in, debian/*/usr/share/doc/*/examples) + dh_installchangelogs -s CHANGES + dh_lintian -s + dh_fixperms -s + dh_strip -s + dh_compress -s + + # dh_makeshlibs (1) creates shlibs/symbols files and (2) generates + # calls to 'ldconfig' in postinst/postrm. We want (1) only for + # libsvn1, but (2) for the swig packages too. + dh_makeshlibs -s -Xjava -X_auth_ -X_ra_neon -X_ra_serf -X_ra_local -X_fs_ + $(RM) debian/libsvn-*/DEBIAN/shlibs debian/python-subversion/DEBIAN/shlibs + $(RM) debian/libsvn-*/DEBIAN/symbols debian/python-subversion/DEBIAN/symbols + dh_perl -s + dh_python2 -s + dh_installdeb -s + dh_shlibdeps -s -X_auth_ + sed -i 's:libsvn-private\(, *\)\?::' debian/*.substvars + dh_gencontrol -s + dh_md5sums -s + dh_builddeb -s + +binary: binary-indep binary-arch + +.PHONY: build build-arch build-indep binary binary-arch binary-indep +.PHONY: clean check-help $(check_all) --- subversion-1.7.9.orig/debian/source/format +++ subversion-1.7.9/debian/source/format @@ -0,0 +1 @@ +1.0 --- subversion-1.7.9.orig/debian/source/lintian-overrides +++ subversion-1.7.9/debian/source/lintian-overrides @@ -0,0 +1,3 @@ +# We don't want a random binNMU to change the bdb version to one that +# nobody has tested with svn. So we have to hardcode it. +build-depends-on-versioned-berkeley-db --- subversion-1.7.9.orig/debian/subversion-tools.NEWS +++ subversion-1.7.9/debian/subversion-tools.NEWS @@ -0,0 +1,16 @@ +subversion-tools (1.2.3dfsg1-1) unstable; urgency=low + + /usr/lib/subversion has moved to /usr/share/subversion; a symlink has + been left behind. This only affects installations where repositories + have been configured to use hook scripts shipped in /usr/lib/subversion, + without making local copies of the scripts. After the release of Debian + Etch, the compatibility symlink will disappear. Please update your + repository configurations accordingly. + + The other script affected is /usr/lib/subversion/hot-backup.py, which + has now moved into /usr/share/doc/subversion/examples. It was never a + supported executable (or it would live in /usr/bin). It is also no + longer needed, because "svnadmin hotcopy" now includes the same + functionality. Please use "svnadmin hotcopy" instead. + + -- Peter Samuelson Sat, 15 Oct 2005 20:09:52 -0500 --- subversion-1.7.9.orig/debian/subversion-tools.dirs +++ subversion-1.7.9/debian/subversion-tools.dirs @@ -0,0 +1 @@ +usr/share/doc/subversion/examples --- subversion-1.7.9.orig/debian/subversion-tools.docs +++ subversion-1.7.9/debian/subversion-tools.docs @@ -0,0 +1,2 @@ +debian/contrib/svn_load_dirs/svn_load_dirs.README +debian/contrib/svn_load_dirs/svn_load_dirs_property_table.example --- subversion-1.7.9.orig/debian/subversion-tools.install +++ subversion-1.7.9/debian/subversion-tools.install @@ -0,0 +1,14 @@ +tools/hook-scripts/* usr/share/subversion/hook-scripts +BUILD/tools/hook-scripts/* usr/share/subversion/hook-scripts +debian/contrib/commit-email.pl usr/share/subversion/hook-scripts +debian/contrib/emacs/psvn.el usr/share/emacs/site-lisp +debian/contrib/emacs/dsvn.el usr/share/emacs/site-lisp +debian/contrib/emacs/50psvn.el etc/emacs/site-start.d + +tools/server-side/svn-backup-dumps.py usr/bin +debian/contrib/svn_load_dirs/svn_load_dirs.pl usr/bin +debian/contrib/svn-fast-backup usr/bin +debian/contrib/svn-clean usr/bin +debian/contrib/svn_apply_autoprops.py usr/bin +debian/bin/svn-bisect usr/bin +debian/bin/svnwrap usr/bin --- subversion-1.7.9.orig/debian/subversion-tools.lintian-overrides +++ subversion-1.7.9/debian/subversion-tools.lintian-overrides @@ -0,0 +1,4 @@ +# the ruby script isn't really needed, it's more of an example file +ruby-script-but-no-ruby-dep usr/share/subversion/hook-scripts/commit-email.rb +# Python dependency is implied by python-subversion dependency +python-script-but-no-python-dep --- subversion-1.7.9.orig/debian/subversion-tools.manpages +++ subversion-1.7.9/debian/subversion-tools.manpages @@ -0,0 +1,7 @@ +debian/man/svnwrap.1 +debian/man/svn-hot-backup.1 +debian/man/svn-fast-backup.1 +debian/man/svn-backup-dumps.1 +debian/man/svn_load_dirs.1 +debian/man/svn-bisect.1 +BUILD/svn-clean.1 --- subversion-1.7.9.orig/debian/subversion-tools.postrm +++ subversion-1.7.9/debian/subversion-tools.postrm @@ -0,0 +1,7 @@ +#!/bin/sh -e + +#DEBHELPER# + +if [ -L /usr/lib/subversion ]; then + rm /usr/lib/subversion +fi --- subversion-1.7.9.orig/debian/subversion.NEWS +++ subversion-1.7.9/debian/subversion.NEWS @@ -0,0 +1,38 @@ +subversion (1.5.0dfsg1-1) experimental; urgency=low + + * As did Subversion 1.4.0, Subversion 1.5.0 will SILENTLY UPGRADE the + format of any working copy it touches. Thereafter, you won't be able + to use earlier Subversion releases with the same working copy. + * In order to use certain features of 1.5.0, you will need to upgrade + your repositories. Unlike with working copies, this is not done + automatically; use the 'svnadmin upgrade' command. + * A lot has changed in 1.5.0; you are encouraged to read + /usr/share/doc/subversion/svn_1.5_releasenotes.html . + + -- Peter Samuelson Thu, 24 Jul 2008 00:03:29 -0500 + +subversion (1.4.6dfsg1-2) unstable; urgency=low + + If you are using BDB repositories, you will get "DB_VERSION_MISMATCH" + errors when you try to use them with recent Subversion, due to the move + to db4.6. To fix this, just run 'svnadmin recover /path/to/repo' for + each affected repository. We apologise for the inconvenience. + + -- Peter Samuelson Tue, 12 Feb 2008 06:49:14 -0600 + +subversion (1.4.0~rc4-1) experimental; urgency=low + + Subversion 1.4.0 will SILENTLY UPGRADE the format of any working copy + it touches. Thereafter, you won't be able to use earlier Subversion + releases with the same working copy. The good news is that this new + format is much more efficient than the old; you should notice a + respectable speed increase for operations such as 'svn status', + especially with large checkouts. + + 1.4.0 also brings an incompatible enhancement (known as 'svndiff1') to + the repository storage format, reducing disk usage by something like + 30%. However, this ONLY affects new repositories, created with svnadmin + 1.4. Existing repositories will continue to use the old format. If you + want to take advantage of svndiff1, dump and reload your repositories. + + -- Peter Samuelson Sun, 23 Jul 2006 15:49:56 -0500 --- subversion-1.7.9.orig/debian/subversion.README.Debian +++ subversion-1.7.9/debian/subversion.README.Debian @@ -0,0 +1,43 @@ +Subversion for Debian +===================== + +Subversion is maintained by a team at: + + http://pkg-subversion.alioth.debian.org/ + + +NFS and Repositories +-------------------- +You should never host a BDB-format repository on an NFS volume: it can +lead to data corruption and data loss. We recommend the svn:// +(svnserve) or svn+ssh:// (ssh tunnel) access methods instead. + +A FSFS repository can be hosted on NFS, but make sure you have the +'lockd' daemon (from the 'nfs-common' package) running on both client +and server. See also this Subversion FAQ entry: + + http://subversion.apache.org/faq.html#nfs + + +The umask issue +--------------- +If you are sharing BDB repositories between multiple users, you may +wish to use the 'svnwrap' script after setting proper permissions. +This sets 'umask 002' before running the real subversion binary. See +'man svnwrap' for details. + + +Emacs and Subversion +-------------------- +There are two packages that provide support for Subversion in Emacs: + +* psvn.el: + + A PCL-CVS-style interface for Subversion. + +* vc-svn.el: + + A Subversion backend for the Emacs VC system. This is now shipped by + Emacs and Xemacs. + + -- Peter Samuelson , Thu, 14 Jun 2012 00:46:56 -0500 --- subversion-1.7.9.orig/debian/subversion.dirs +++ subversion-1.7.9/debian/subversion.dirs @@ -0,0 +1 @@ +etc/bash_completion.d --- subversion-1.7.9.orig/debian/subversion.docs +++ subversion-1.7.9/debian/subversion.docs @@ -0,0 +1,3 @@ +README +debian/svn_1.6_releasenotes.html +debian/svn_1.7_releasenotes.html --- subversion-1.7.9.orig/debian/subversion.examples +++ subversion-1.7.9/debian/subversion.examples @@ -0,0 +1 @@ +tools/dev/gnuify-changelog.pl --- subversion-1.7.9.orig/debian/subversion.install +++ subversion-1.7.9/debian/subversion.install @@ -0,0 +1,8 @@ +debian/tmp/usr/bin/svn* usr/bin +debian/tmp/usr/share/locale usr/share +debian/tmp/usr/share/man/man1 usr/share/man +debian/tmp/usr/share/man/man5 usr/share/man +debian/tmp/usr/share/man/man8 usr/share/man + +BUILD/dummy_home/.subversion/config etc/subversion +BUILD/dummy_home/.subversion/servers etc/subversion --- subversion-1.7.9.orig/debian/svn_1.6_releasenotes.html +++ subversion-1.7.9/debian/svn_1.6_releasenotes.html @@ -0,0 +1,889 @@ + + +Apache Subversion 1.6 Release Notes + + + + + + + + + +
+
+ + + +
+ + + +

Apache Subversion 1.6 Release Notes

+ +
+

What's New in Apache Subversion 1.6 + +

+ + + +

Apache Subversion 1.6 is a superset of all previous Subversion +releases, and is as of the time of its release considered the current +"best" release. Any feature or bugfix in 1.0.x through 1.5.x is also +in 1.6, but 1.6 contains features and bugfixes not present in any +earlier release. The new features will eventually be documented in a +1.6 version of the free Subversion book +(svnbook.red-bean.com).

+ +

This page describes only major changes. For a complete list of +changes, see the 1.6 section of the CHANGES +file.

+ +
+ +
+

Compatibility Concerns + +

+ +

Older clients and servers interoperate transparently with 1.6 +servers and clients. However, some of the new 1.6 features may not be +available unless both client and server are the latest version. There are +also cases where a new feature will work but will run less efficiently if +the client is new and the server old.

+ +

There is no need to dump and reload your +repositories. Subversion 1.6 can read repositories created by earlier +versions. To upgrade an existing installation, just install the +newest libraries and binaries on top of the older ones.

+ +

Subversion 1.6 maintains API/ABI compatibility with earlier +releases, by only adding new functions, never removing old ones. A +program written to the 1.0, 1.1, 1.2, 1.3, 1.4 or 1.5 API can both compile +and run using 1.6 libraries. However, a program written for 1.6 +cannot necessarily compile or run against older libraries.

+ +
+

New Feature Compatibility Table + +

+ + + + + + + + + + + + + + + + + + + + + +
New FeatureMinimum Client1Minimum ServerMinimum RepositoryNotes
FSFS Packingany1.61.6
Tree Conflicts1.61.6anyUsing servers older than 1.6 is possible, but some kinds + of conflicts will not be detected.
1Reminder: when using the file:// + repository access method, the Subversion program is both the client + and the server.
+ +
+ +
+

Working Copy and Repository Filesystem Format Changes + +

+ +

The working copy format has been upgraded. This means that 1.5 and +older Subversion clients will not be able to work with +working copies produced by Subversion 1.6. Working copies are upgraded automatically.

+ +

Similarly, the repository filesystem formats have changed, meaning +that 1.5 and older versions of Subversion tools that normally access +a repository directly (e.g. svnserve, mod_dav_svn, +svnadmin) won't be able to read a repository created by +Subversion 1.6. But, repositories are not upgraded automatically.

+ +
+

Working Copy Upgrades + +

+ +

WARNING: if a Subversion 1.6 client encounters a +pre-1.6 working copy, it will automatically upgrade the +working copy format as soon as it touches it, making it unreadable by +older Subversion clients. If you are using several versions of +Subversion on your machine, be careful about which version you use in +which working copy, to avoid accidentally upgrading a working copy. +(But note that this "auto upgrade" behavior does not occur +with the repositories, only working +copies.)

+ +

If you accidentally upgrade a 1.5 working copy to 1.6, and wish to +downgrade back to 1.5, use the change-svn-wc-format.py script. See this FAQ entry for details, and run the script with the +--help option for usage instructions.

+ +
+ +
+

Repository Upgrades + +

+ +

The Subversion 1.6 server works with 1.5 and older repositories, +and it will not upgrade such repositories to 1.6 unless +specifically requested to via the +svnadmin upgrade command. This means +that some of the new 1.6 features will not become available simply by +upgrading your server: you will also have to upgrade your +repositories. (We decided not to auto-upgrade repositories because we +didn't want 1.6 to silently make repositories unusable by +1.5 — that step should be a conscious decision on the +part of the repository admin.)

+ +
+ +
+ +
+

Command Line Output Changes + +

+ +

Although we try hard to keep output from the command line programs +compatible between releases, new information sometimes has to be +added. This can break scripts that rely on the exact format of the +output.

+ +
+

Improved output of svn proplist --verbose + +

+ +

The output of svn proplist --verbose has been +improved, and svn propget now accepts the --verbose +option. The following example illustrates these changes.

+ +
   $ svn proplist --verbose build.conf
+   Properties on 'build.conf':
+     svn:eol-style
+       native
+     svn:mergeinfo
+       /trunk/build.conf:1-4800
+       /branches/a/build.conf:3000-3400
+       /branches/b/build.conf:3200-3600
+   $ 
+
+ +
+ +
+

Changed output of svn status + +

+ +

The output of svn status contains the additional seventh +column which informs whether the item is the victim of a tree conflict. +An additional line with more detailed description of a tree conflict is +displayed after each item remaining in tree conflict.

+ +
   $ svn status
+   M       Makefile.in
+   A     C src/error.c
+         >   local add, incoming add upon update
+   M       src/log.c
+   M     C src/path.c
+         >   local edit, incoming delete upon update
+   D     C src/properties.c
+         >   local delete, incoming edit upon merge
+   M     C src/time.c
+   $ 
+
+ +
+ +
+

Conflict summary printed by svn update and + svn merge + +

+ +svn update and svn merge now print +a summary of conflicts upon completion. + +
$ svn update --accept=postpone
+   C alpha
+ C   beta
+C    gamma
+Updated to revision 3.
+Summary of conflicts:
+  Text conflicts: 1
+  Property conflicts: 1
+  Tree conflicts: 1
+
+ +Minor problems with the conflict summary are described in +issue 3342. + +
+ +
+ +
+

Hook Changes + +

+ +
+

Changed handling of output of pre-lock hook + +

+ +

The output of pre-lock hook was previously discarded, but now +it is used to specify the names of lock tokens.

+ +
+ +
+ +
+ +
+

New Features + +

+ + + +
+

Repository root relative URLs (client) + +

+ +

This section is currently incomplete, please +help write it! See the +design notes for more information.

+ +
   $ svn SUBCOMMAND ^/
+   $ svn SUBCOMMAND ^/PATH
+
+ +
+ +
+

Improvements to svn:externals + +

+ +

Subversion 1.6 adds a couple of new features for users of +svn:externals. The include:

+ + + +
+

Support for files in svn:externals + (client) + +

+ +

+ If the URL in a svn:externals description refers to a file, + it will be added into the working copy as a versioned item. +

+ +

+ There are a few differences between directory and file + externals. +

+ +
    +
  • + The path to the file external must be in a working copy that is + already checked out. While directory externals can place the + external directory at any depth and it will create any + intermediate directories, file externals must be placed into a + working copy that is already checked out. +
  • +
  • + The file external's URL must be in the same repository as the URL + that the file external will be inserted into; inter-repository + file externals are not supported. +
  • +
  • + While commits do not descend into a directory external, a commit + in a directory containing a file external will commit any + modifications to the file external. +
  • +
+ +

The differences between a normal versioned file and a file +external.

+ +
    +
  • + File externals cannot be moved or deleted; the + svn:externals property must be modified instead; however, + file externals can be copied. +
  • +
+ +

Other facts.

+ +
    +
  • + A file external shows up as a X in the switched status + column. +
  • +
+ +
+ +
+

Support usual shell quoting rules in externals definitions + (issue 2461, client) + +

+ +

Need to document possible incompatibilities (see +this +thread)

+ +
+ +
+

Further reading + +

+ +

See The svn:externals section of the Subversion Book.

+ +
+ +
+ +
+

Detection of tree conflicts (client) + +

+ +

Subversion 1.6 recognizes a new kind of conflict, known as a +"tree conflict". Such conflicts manifest at the level +of directory structure, rather than file content.

+ +

Situations now flagged as conflicts include deletions of locally +modified files, and incoming edits to locally deleted files. Files +and directories which are victims of a tree conflict cannot be +committed before the conflict is marked resolved.

+ +

Note that Subversion is still treating renames as a "copy+delete" +operation, so file renames causing tree conflicts can only be detected +in terms of file additions and deletions. Because of this, false positives +during tree conflict detection are possible.

+ +

To facilitate tree conflict detection, attempting to commit the +deletion of a file which has already been deleted in the HEAD revision +now causes an error. In Subversion 1.5, this was treated as a no-op, +potentially resulting in "empty" revisions which contained +no changes.

+ + +
+

Further reading + +

+ +

See the tree conflicts section of the Subversion Book.

+ +
+ +
+ +
+

Filesystem Storage Improvements + +

+ +

Subversion 1.6 contains several improvements to both the Berkeley DB and FSFS +backends. These are designed to improve storage space, and can result in +drastically smaller repositories. These changes include:

+ + +
+

Sharing multiple common representations + (issue 2286, + server) + +

+

When using many branches and merging between them often, it is common to +have files with similar lines of history which contain the exact same content. +In the past, Subversion has stored these files as deltas against previous +versions of the file. Subversion 1.6 will now use existing representations in +the filesystem for duplicate storage. Depending on the size of the repository, +and the degree of branching and merging, this can cause an up to 20% space +reduction for Berkeley DB repositories and a 15% reduction for FSFS +repositories.

+ +
+ +
+

FSFS repositories: Packing completed shards (server) + +

+ +

Subversion 1.5 introduced the ability for FSFS repositories to be +sharded into +multiple directories for revision and revprop files. Subversion 1.6 takes +the sharding concept further, and allows full shard directories to be +packed into a single file. By reducing internal fragmentation in +the filesystem, packed FSFS repositories have significant space savings +over their unpacked counterparts, especially repositories which contain +many small commits. Using a one-file-per-shard approach also allows +Subversion to reduce disk I/O and better exploit operating system caches. +

+ +

To pack a repository, run svnadmin pack on the repository. +Once a repository has been packed, there is no migration path back to an +unpacked state, and it can only be read by Subversion 1.6 or greater +servers.

+ +
+ +
+

FSFS repositories: Support for Memcached (server) + +

+ +

Memcached can +cache data of FSFS repositories.

+ +

Additional build-time dependencies: APR-Util ≥1.3 || ( APR-Util < +1.3 && APR_Memcache )

+ +
+ +
+

BDB repositories: Forward deltas (server) + +

+ +

Newly created BDB repositories now use forward deltas instead of reverse +deltas. svnadmin upgrade can be used to make older repositories +use forward deltas for new revisions. If you want to achieve the most +optimized state of an older repository, you still need to perform dump and +load of the repository.

+ +
+ +
+ +
+

Ctypes Python Bindings + +

+ +

Subversion 1.6 introduces a new python binding for the Subversion API. The +new binding makes use of the ctypes library to present the standard API along +with a selection of Python classes to give an object-oriented interface to +standard Subversion constructs. These bindings have several advantages over +the traditional SWIG-based bindings:

+
    +
  • Generated automatically
  • +
  • Straightforward, and don't have any special "transformation" rules
  • +
  • Pure python and cross-platform
  • +
  • Both forward and backward compatible as long as the functions used in the programs + have compatible definitions
  • +
  • High level classes make it easy to access common subversion + functionality in a pythonic way
  • +
+ +

Building the ctypes bindings produces two ways to access Subversion from +python. The first interface is a direct python port of the standard API. +Ctypes provides some basic type conversions and allows the calling of +Subversion functions just like in C code. The new bindings also introduce a +set of python classes to enable higher-level access to Subversion features. +These classes take full advantage of python features and hide as much of the +C implementation as possible to make Subversion easier to use for python +programmers not familiar with the C API.

+ +
+ +
+ +
+

Enhancements and Bugfixes + +

+ +
+

Improved interactive conflict resolution (client) + +

+ +

Interactive conflict resolution supports new display-conflict, +mine-conflict and theirs-conflict options.

+ +

Here's an example using the command-line client:

+ +
   $ svn up
+   U    Makefile.in
+   Conflict discovered in 'configure.ac'.
+   Select: (p) postpone, (df) diff-full, (e) edit,
+           (mc) mine-conflict, (tc) theirs-conflict,
+           (s) show all options: s
+
+     (e)  edit             - change merged file in an editor
+     (df) diff-full        - show all changes made to merged file
+     (r)  resolved         - accept merged version of file
+
+     (dc) display-conflict - show all conflicts (ignoring merged version)
+     (mc) mine-conflict    - accept my version for all conflicts (same)
+     (tc) theirs-conflict  - accept their version for all conflicts (same)
+
+     (mf) mine-full        - accept my version of entire file (even non-conflicts)
+     (tf) theirs-full      - accept their version of entire file (same)
+
+     (p)  postpone         - mark the conflict to be resolved later
+     (l)  launch           - launch external tool to resolve conflict
+     (s)  show all         - show this list
+
+   Select: (p) postpone, (df) diff-full, (e) edit,
+           (mc) mine-conflict, (tc) theirs-conflict,
+           (s) show all options: mc
+   G    configure.ac
+   Updated to revision 36666.
+   $ 
+
+ +
+ +
+

Sparse directory exclusion + +

+ +

In Subversion 1.6, the --set-depth parameter to svn +update has grown a new value—exclude. This value tells +Subversion to exclude the target from the working copy, immediately and until +further notice. Prior to Subversion 1.6, if a directory could not easily be +removed from a working copy. If it was deleted without the help of Subversion, +it would return on the next svn update. If it was deleted with +svn delete, the directory remained as a local modification +forever. (Unless, of course, it was accidentally committed.) The new exclusion +mechanism in Subversion 1.6 fixes both these problems.

+ +

Note that if you exclude a versioned directory that has some unversioned +files in it, or some files with local modifications, Subversion handles this +situation gracefully. All the files that aren't safe to delete, Subversion +leaves around, and of course leaves any intermediate directories required to +reach those files, too.

+ +
+

Further reading + +

+ +

See this blog post for more examples and information.

+ +
+ +
+ +
+

Logging support for svnserve (server) + +

+ +

svnserve now accepts the --log-file option which +allows to specify the file used for logging.

+ +
+ + +
+

New public 'historical' HTTP URI syntax for mod_dav_svn (server) + +

+ +

mod_dav_svn now supports a new public URI syntax for +examining older versions of files or directories. The intent here is +to allow users to examine history without the use of an svn client, +and to make it easier for 3rd-party tools (e.g. code-review services) +to work directly against repositories without using svn libraries.

+ +
http://host/repos/path?[p=PEG][&r=REV]
+ +

The new syntax works similarly to the way URIs work with the svn + commandline client. Simply requesting http://host/repos/path + fetches "path" in the HEAD revision. Adding a "p" query argument + specifies a different peg revision instead, so that:

+ +
http://host/repos/path?p=38
+ +

...is similar to specifying "path@38" on the commandline. Adding a + "r" query argument is like specifying "-r" on the commandline, + causing the repository to follow history backwards from the peg + revision to the older operative revision:

+ +
http://host/repos/path?p=38&r=20
+ +

As with the commandline, the peg revision defaults to HEAD if + unspecified, and the operative revision defaults to the peg + revision. The online Subversion Book has + a section + explaining peg and operative revisions in great detail.

+ +
+ + +
+

Command-line client improvements (client) + +

+ +

There are far too many enhancements and new options to the +command-line client to list them all here. Aside from all the ones +mentioned already in these release notes, below are a few more that we +consider important, but please see the 1.6.0 section in the CHANGES file +for a complete list.

+ +
+

log can take multiple revisions + +

+ +

The svn log command can now take multiple revision arguments +in one invocation. Both the -c and -r arguments are supported.

+ +
   $ svn log -r36169 -r36171 http://svn.collab.net/repos/svn/
+   ------------------------------------------------------------------------
+   r36169 | sussman | 2009-02-26 14:46:44 -0800 (Thu, 26 Feb 2009) | 1 line
+
+   ...log message omitted...
+   ------------------------------------------------------------------------
+   r36171 | joeswatosh | 2009-02-26 22:05:28 -0800 (Thu, 26 Feb 2009) | 20 lines
+
+   ...log message omitted...
+   $ svn log -c36169,36171 http://svn.collab.net/repos/svn/
+   ------------------------------------------------------------------------
+   r36169 | sussman | 2009-02-26 14:46:44 -0800 (Thu, 26 Feb 2009) | 1 line
+
+   ...log message omitted...
+   ------------------------------------------------------------------------
+   r36171 | joeswatosh | 2009-02-26 22:05:28 -0800 (Thu, 26 Feb 2009) | 20 lines
+
+   ...log message omitted...
+
+ +
+ +
+

--trust-server-cert option + +

+ +

Option added to svn and svnsync, so that +non-interactive operations can work with self-signed certificates not +backed by a known trust authority.

+ +with this option: +
   $ svn log -r36364 https://svn.collab.net/repos/svn/trunk --trust-server-cert --non-interactive
+   ------------------------------------------------------------------------
+   r36364 | stylesen | 2009-03-06 13:11:20 +0530 (Fri, 06 Mar 2009) | 3 lines
+   
+   ...log message omitted...
+   ------------------------------------------------------------------------
+
+ +without this option: +
   $ svn log -r36364 https://svn.collab.net/repos/svn/trunk 
+   Error validating server certificate for 'https://svn.collab.net':
+    - The certificate is not issued by a trusted authority. Use the
+      fingerprint to validate the certificate manually!
+   Certificate information:
+    - Hostname: svn.collab.net
+    - Valid: from Sep 24 22:01:07 2007 GMT until Sep 23 22:01:07 2011 GMT
+    - Issuer: sv, CollabNet, Brisbane, California, US
+   (hostname@collab.net)
+    - Fingerprint:
+   AA:5B:74:B1:E2:7F:38:B3:2B:C2:B1:60:6E:01:BB:F5:7C:37:98:46
+   (R)eject, accept (t)emporarily or accept (p)ermanently? t
+   ------------------------------------------------------------------------
+   r36364 | stylesen | 2009-03-06 13:11:20 +0530 (Fri, 06 Mar 2009) | 3 lines
+
+   ...log message omitted...
+   ------------------------------------------------------------------------
+
+ +
+ +
+ +
+

API changes, improvements and language bindings + (client and server) + +

+ +

The pre-lock hook can now specify the lock-token string +via the hook's stdout; see r32778 for details. Note that when the hook uses this feature, +it must take responsibility for ensuring that lock tokens are unique +across the repository.

+ +

There are too many new and revised APIs in Subversion 1.6.0 to list +them all here. See the Subversion API +Documentation page for general API information. If you develop a +3rd-party client application that uses Subversion APIs, you should +probably look at the header files for the interfaces you use and see +what's changed.

+ +

One general change is that most APIs that formerly took a +recurse parameter have been upgraded to accept a +depth parameter instead, to enable the new sparse checkouts feature.

+ +

Language bindings have mostly been updated for the new APIs, though +some may lag more than others.

+ +
+ +
+

Bug fixes (client and server) + +

+ +

A great many bugs have been fixed. See the 1.6.0 section in the CHANGES file +for details.

+ +
+ +
+ +
+

Subversion 1.4.x series no longer supported + +

+ +

The Subversion 1.4.x line is no longer supported. This doesn't +mean that your 1.4 installation is doomed; if it works well and is all +you need, that's fine. "No longer supported" just means we've stopped +accepting bug reports against 1.4.x versions, and will not make any +more 1.4.x bugfix releases.

+ +
+ +
+

New Dependency: SQLite + +

+ +

We now require SQLite to build both +the server and client. We recommend 3.6.13 or greater, but work with +anything better than 3.4.0. Subversion will attempt to use an SQLite +amalgamation if it is +present in the root of the distribution tarball, otherwise, Subversion will +search for SQLite in the usual places on the system. You may also pass +--with-sqlite to configure to specify the location +of the SQLite library or amalgamation you wish to use.

+ +
+ + +
+ + + --- subversion-1.7.9.orig/debian/svn_1.7_releasenotes.html +++ subversion-1.7.9/debian/svn_1.7_releasenotes.html @@ -0,0 +1,1402 @@ + + +Apache Subversion 1.7 Release Notes + + + + + + + + + +
+
+ + + +
+ + + +

Apache Subversion 1.7 Release Notes

+ +
+

What's New in Apache Subversion 1.7 + +

+ + + +

Apache Subversion 1.7 is a superset of all previous Subversion +releases, and is as of the time of its release considered the current +"best" release. Any feature or bugfix in 1.0.x through 1.6.x is also +in 1.7, but 1.7 contains features and bugfixes not present in any +earlier release. The new features will eventually be documented in a +1.7 version of the free Subversion book +(svnbook.red-bean.com).

+ +

This page describes only major changes. For a complete list of +changes, see the 1.7 section of the CHANGES +file.

+ +
+ +
+

Compatibility Concerns + +

+ +

Older clients and servers interoperate transparently with 1.7 +servers and clients. However, some of the new 1.7 features may not be +available unless both client and server are the latest version. There are +also cases where a new feature will work but will run less efficiently if +the client is new and the server old.

+ +

There is no need to dump and reload your +repositories. Subversion 1.7 servers can read and write to repositories created by +earlier versions. To upgrade an existing server installation, just install the +newest libraries and binaries on top of the older ones.

+ +

Subversion 1.7 servers use the same repository format as Subversion 1.6. +Therefore, it is possible to seamlessly upgrade and downgrade between 1.6.x and 1.7.x +servers without changing the format of the on-disk repositories. +(This is not correct in general for any pair of 1.x and 1.y servers, +but happens to hold for 1.6 and 1.7.) +If new 1.7 features were enabled on the server (in the hooks or server +configuration files), they will, of course, have to be disabled prior +to reverting back to a 1.6 server.

+ +

Subversion 1.7 clients use a new working copy format. +Subversion 1.7 clients cannot use Subversion 1.6 (and earlier) working copies. +Existing working copies created with Subversion 1.6 and earlier need to be +upgraded before they can be used with a Subversion 1.7 +client (see below for details).

+ +

Subversion 1.7 maintains API/ABI compatibility with earlier +releases, by only adding new functions, never removing old ones. A +program written to any previous 1.x API can both compile +and run using 1.7 libraries. However, a program written for 1.7 +cannot necessarily compile or run against older libraries.

+ +

There may be limited cases where the behavior of old APIs has been +slightly modified from previous releases. These are cases where edge cases +of the functionality has been deemed buggy, and therefore improved or removed. +Please consult the +API errata for more detailed information on what these APIs are +and what impact these changes may have. For Subversion 1.7, these +errata are mostly limited to libsvn_wc, with one notable +exception: libsvn_ra_serf's approach to driving +the svn_delta_editor_t interfaces (provided to it indirectly +via calls to the svn_ra.h interfaces).

+ +
+

New Feature Compatibility Table + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New FeatureMinimum Client1Minimum ServerMinimum RepositoryNotes
HTTPv21.71.7anyPermutations of older client/server combinations will continue to + function at the pre-1.7 feature level. Server-side configuration + changes might be required for optimal performance with clients that + use serf.
WC-NG1.7anyany1.6 working copies cannot be used with 1.7 and will + not be upgraded to the new 1.7 format + automatically.
svnrdump1.71.4 (dump)
1.7 (load)
anySee the full entry, below for discussion + of known issues.
svn patch1.7anyany
atomic revprop changes1.71.7anyFixes a race condition in svnsync (issue #3546).
reduced subtree mergeinfo + recording1.7anyanyIf both pre-1.7 clients and 1.7 clients are used to perform merges + to the same branch, the pre-1.7 clients may experience slower merge + performance.
server performance tuningany1.7anyPurely server-side configuration. file:// access in 1.7 clients will + use the default settings.
1Reminder: when using the file:// + repository access method, the Subversion program is both the client + and the server.
+ +
+ +
+

Command Line Output Changes + +

+ +

Although we try hard to keep output from the command line programs +compatible between releases, new information sometimes has to be +added. This can break scripts that rely on the exact format of the +output. For this reason, we encourage programs which consume the output +of the commandline client to consider using the --xml option, +or accessing Subversion through the various bindings interfaces.

+ + + +
+

Improved output of svn update for multiple working copies + +

+ +

Improvements have been made to the output of svn update +when updating multiple working copies at once (see +issue #3693). Below is an example of the new output:

+ +
  $ svn up subversion svncorp UNVERSIONED
+  Updating 'subversion':
+  At revision 1037740.
+  Updating 'svncorp':
+  At revision 288.
+  Skipped 'UNVERSIONED'
+  Summary of updates:
+   Updated 'subversion' to r1037740.
+   Updated 'svncorp' to r288.
+  Summary of conflicts:
+   Skipped paths: 1
+
+ +
+ +
+

svn diff now shows property changes as unidiff + +

+ +

svn diff now shows textual property changes in unidiff format, +except for svn:mergeinfo properties. +Below is an example of the new output:

+ +
  $ svn diff
+  Index: gamma
+  ===================================================================
+  --- gamma       (revision 23)
+  +++ gamma       (working copy)
+
+  Property changes on: gamma
+  ___________________________________________________________________
+  Modified: svn:externals
+  ## -1,3 +1,3 ##
+   ^/branches/gamma gamma-external
+  -^/trunk/alpha alpha-external
+  +^/trunk/beta beta-external
+   ^/trunk/epsilon epsilon-external
+  Index: beta
+  ===================================================================
+  --- beta        (revision 23)
+  +++ beta        (working copy)
+
+  Property changes on: beta
+  ___________________________________________________________________
+  Added: svn:eol-style
+  ## -0,0 +1 ##
+  +native
+
+ +
+ +
+

Error and warning numbers now reported + +

+ +

The output of svn now contains an error number or warning +number with every error. The following example illustrates these changes.

+ +
   % svn info
+   svn: E155007: '/home/CIA-91' is not a working copy
+
+ +

These error values are useful as search keywords. Under the hood, these error +codes correspond to the API error codes used by Subversion and APR. For programming to our API's, +it's possible to convert a numeric error code to a symbolic one via the which-error.py script (first included in Subversion 1.3.0):

+ +
   % ./tools/dev/which-error.py 155007
+   00155007  SVN_ERR_WC_NOT_DIRECTORY
+
+ +
+
+ +
+

Miscellaneous Compatibility Notes + +

+ +

There are some additional specific areas where changes made in this +release might necessitate further adjustment by administrators or +users. We'll cover those in this section.

+ +
+

Case sensitivity of authz access rules + +

+ +

Prior to this release, the section headers in Subversion's authz +access files—which contain repository names and repository +filesystem paths—were parsed in a case-insensitive fashion. +That's been fixed in this release. The practical fallout, though, is +that your existing authz files might be depending (perhaps +unintentionally) on the old behavior and the new behavior could result +in access to items in your repositories being unexpectedly +denied—or granted—as a result of upgrading to Subversion +1.7. Please review all authz access files for case correctness. (For +details, +see issue #3781).

+ +
+ +
+

Incompatible FSFS changes since 1.7.0-alpha3 for packed repositories + +

+ +

Subversion 1.6 introduced support for packing + FSFS revision files, and Subversion 1.7.x alpha releases (up to +1.7.0-alpha3) supported packing of revprops into an SQLite database. This +support is not present in the final release (see issue #3952 for the reason). Any +FSFS-backed repositories that were svnadmin created or +svnadmin upgraded by svnadmin from a nightly build or +from an alpha release of the 1.7.x line are not supported by +the final 1.7.0 release. It is required to dump these repositories +using an svnadmin built from the 1.7.0-alpha3 release (or to +svnsync them using a source server running 1.7.0-alpha3) in order to +upgrade them for the 1.7.0 release.

+ +

Subversion 1.7 will complain when it encounters such repositories, with +the following error:

+ +
subversion/libsvn_fs_fs/fs_fs.c:1083: (apr_err=160043)
+svnadmin: E160043: Found format '5', only created by unreleased dev builds;
+   see http://subversion.apache.org/docs/release-notes/1.7#revprop-packing
+
+ +

We reiterate that this lack of upgrade path is within the latitude of +our policy for pre-releases. We may +provide in the future a script to downgrade a repository in-place to the +format supported by both 1.6 and 1.7. (We will welcome contributions of such a script.)

+ +

We plan to reintroduce revprop packing in a future release; see issue #3944 for details.

+ +
+ +
+

'svn remove' now removes directories from disk immediately + +

+ +

The svn remove command now removes directories from disk +immmediately. In Subversion 1.6, directories were scheduled for deletion +but kept on disk to retain meta-data stored in the .svn subdirectory. +With the new working copy format introduced in Subversion 1.7 it is no +longer necessary to keep the removed directory on disk. This also +facilitates better handling of directory replacements in the working +copy (see issue #3468 for details).

+ +

If the --keep-local option is used, svn remove will +keep the removed directory on disk.

+ +

+ +
+ +
+ +
+

New Features + +

+ +
+

Working Copy Metadata Storage Improvements (client) + +

+ +

Subversion 1.7 features a complete re-write of the working copy +metadata management system of Subversion, code named WC-NG. The old system +was one of the first parts of Subversion written, and over time had grown +difficult to maintain and extend. WC-NG is intended to provide an +immediate performance improvement, while also enabling many future feature +enhancements.

+ +

Although Subversion 1.7 does not introduce these new features, the +improvements in the working copy storage make them much more likely to +appear in future releases.

+ +

A number of known (and unknown) bugs have been fixed by the new working +copy metadata system (see +issue +#3357).

+ +
+

Centralized Metadata Storage + +

+ +

A key feature of the changes introduced in Subversion 1.7 is the +centralization of working copy metadata storage into a single location. +Instead of a .svn directory in every directory in the working +copy, Subversion 1.7 working copies have just one .svn +directory—in the root of the working copy. This directory includes +(among other things) an SQLite-backed database which contains all of the +metadata Subversion needs for that working copy.

+ +

Even though the data is stored in a structured format, the relationships +between the data are complex. We highly discourage external tools from +modifying the data held in this database, as such modification is likely to +result in working copy corruption.

+ +

+ +
WARNING: It is not + safe to copy an SQLite file while it's being accessed via the SQLite + libraries. Consequently, duplicating a working copy (using tar, + cp, or rsync) that is being accessed by a Subversion + process is not supported for Subversion 1.7 working copies, and may + cause the duplicate (new) working copy to be created corrupted. (See issue #3596 for details.)
+ + +
+ +
+

Pristine Contents + +

+ +

Subversion keeps a record of the unmodified contents of all files in the +working copy. Historically, these have been called text-bases, but +in Subversion 1.7, they have received a new name, and a new home. With the +centralization of metadata, the text-bases have been renamed +pristines, and are now located in the same .svn +directory as the working copy metadata.

+ +

The pristines are stored by checksum in a sharded format. Any files +in the working copy which have the same pristine content will now share +references to the pristine store, making such working copies slightly +smaller. Running svn cleanup will remove any pristines which +are no longer needed by the current state of the working copy.

+ +

Note: In 1.7, we recommend to run svn cleanup +periodically in order to claim +back the disk space of unreferenced pristines. We expect a future Subversion +release to purge unreferenced (and thus unused) pristines automatically; see +issue #4071 +for details.

+ +
+ +
+

Upgrading the Working Copy + +

+ +

Subversion 1.7 introduces substantial changes to the working copy format. +In previous releases of Subversion, Subversion would automatically update +the working copy to the new format when a write operation was performed. +Subversion 1.7, however, will make this a manual step. Before using +Subversion 1.7 with their working copies, users will be required +to run a new command, svn upgrade to update the metadata to the +new format. This command may take a while, and for some users, it may be more +practical to simply checkout a new working copy.

+ +

Note: Subversion 1.7 cannot upgrade working copies that +a 1.6 client would have refused to operate upon before an svn cleanup +was run (with a 1.6 client). In other words, before upgrading to 1.7, a 1.6 +client must be used to run svn cleanup on all working copies that +require cleanup. Likewise, Subversion 1.7 cannot upgrade corrupt 1.6 working +copies. Unfixable problems can arise from missing or corrupt meta-data inside +.svn directories. Such damage to the 1.6 working copy is permanent, +and cannot be fixed even if svn cleanup is run prior to the upgrade.

+

We regret these limitations, but we had to introduce them in order for +1.7 to ship timely and without overcomplicating the internals. +If your working copy does not upgrade cleanly, please check out a new one.

+ + + +
+ +
+ +
+

Improved HTTP protocol usage (client and server) + +

+ +

Over the years, many people have complained about the performance issues +with Subversion's use of HTTP as a repository access mechanism. This largely +stems from the developers' original intent to implement as much of the WebDAV +DeltaV specification as +possible. Alas, this specification was not widely implemented, so +none of the supposed benefits of the DeltaV overhead ever +materialized.

+ +

Subversion 1.7 offers a simpler HTTP protocol variant that can be used when +connecting to supported servers. This simpler protocol (sometimes referred to +as HTTPv2) requires fewer client-server round trips to establish a +connection, making Subversion much more performant on high-latency network +connections. Subversion's Serf-based repository access library (which will +become the default library for HTTP in Subversion 1.8) has received +all of the protocol changes scheduled for 1.7, affecting both commit and read +operations; the older Neon-based library has received the most important and +high-impact of these changes, too.

+ +

As mentioned in the compatibility +table, Subversion 1.7 will only use HTTPv2 when connecting with a 1.7 (or +greater) server, but will continue to use existing protocols when communicating +with earlier versions of Subversion. Likewise, older clients will only use the +old protocol when connecting to a Subversion server, regardless of version.

+ +
+ +
+

New remote dumpfile tool: svnrdump (client) + +

+ +

Subversion 1.7 adds a new tool to the client's toolbox: +svnrdump. svnrdump replicates the functionality of +svnadmin dump and svnadmin load, but works on +remote repositories, instead of needing administrator (local filesystem) access +to the source or target repository.

+ +
+

svnrdump load race condition + +

+ +

Note that svnrdump load can suffer from a race condition +in its locking algorithm when run against a 1.6 or earlier server. +The race condition is only applicable if multiple svnrdump load +processes may attempt to write concurrently to a single repository. +This is the same problem that the new atomic revprop changes feature fixes for +svnsync (see issue #3546), and the same server-side +workaround is available.

+ +

Server administrators who would like to block their users +from committing via svnrdump load may do so by installing the +following pre-revprop-change script:

+ +
#!/bin/sh
+PROPNAME="$4"
+if [ "$PROPNAME" = "svn:rdump-lock" ]; then
+  echo "'svnrdump load' disabled by the server administrator" >&2
+  exit 1
+fi
+exit 0
+
+ +

This hook script suffices to protect repositories from accidental use +of svnrdump load. It does not (and cannot) protect the server from +users who intentionally recompile svnrdump in order to bypass this +restriction.

+ +
+ +
+

svnrdump dump and libsvn_ra_serf editor driving don't mix + +

+ +

The svnrdump dump command is more strict in its expectations +from the network access library than +the API permits it to be. This problem manifests itself in particular +with the ra_serf HTTP access library, as documented +in issue #4116. A workaround is to +use the ra_neon HTTP access library (which is the default).

+ +

The problem does not affect other executables (such as svn and +svnadmin). It also does not affect svnrdump when the default +HTTP access library, ra_neon, is used. Third-party API consumers should not +expect to be able to use all the orderings permitted by the +delta editor API +when the editor receiver is svnrdump dump.

+ +

This problem is related to, but not the same as, +ra_serf's dishonouring of the delta editor ordering rules.

+ +
+ +
+ +
+

New feature: svn patch (client) + +

+ +

Subversion 1.7 features a new subcommand called svn patch +which can apply patch files in unidiff format (as produced by +svn diff and other diff tools) to a working copy.

+ +

svn patch will apply unidiff changes to existing files just +like third party patch tools. +It will also add newly created files to version control, and delete files +and directories which are left empty after patching. +Keywords and newlines are also handled automatically if the +svn:keywords and svn:eol-style properties are +set on patched files.

+ +

svn diff will now produce unidiff output for Subversion +property changes, and svn patch is able to apply these changes +to properties (except for svn:mergeinfo, see +issue #3747).

+ +

When a patch does not apply cleanly some or all changes listed in the +patch might be rejected. But svn patch currently does not +mark files with rejected changes as conflicted (see +issue #3565). Files which weren't patched successfully can be +committed without being touched by svn resolve first. +This problem will be addressed in a future release of Subversion.

+ +

A new API for parsing unidiff patch files has been added to +libsvn_diff. A new API for applying unidiff patches to a +working copy has been added to libsvn_client.

+ +
+ + +
+ +
+

Enhancements and Bugfixes + +

+ + + +
+

Command-line client improvements (client) + +

+ +

There are far too many enhancements and new options to the +command-line client to list them all here. Aside from all the ones +mentioned already in these release notes, below are a few more that we +consider important, but please see the 1.7.0 section in the CHANGES file +for a complete list.

+ + + +
+

svn log can now print diffs + +

+

svn log accepts the new --diff +option which causes it to show changes committed in a revision as +a unified diff. Below is example output:

+
  $ svn log --diff -r1033146 http://svn.apache.org/repos/asf/subversion/trunk
+  ------------------------------------------------------------------------
+  r1033146 | hwright | 2010-11-09 19:40:46 +0100 (Tue, 09 Nov 2010) | 3 lines
+
+  * subversion/libsvn_wc/wc_db.c
+    (svn_wc__db_op_copy): Remove unused variable.
+
+
+  Index: subversion/libsvn_wc/wc_db.c
+  ===================================================================
+  --- subversion/libsvn_wc/wc_db.c	(revision 1033145)
+  +++ subversion/libsvn_wc/wc_db.c	(revision 1033146)
+  @@ -3061,7 +3061,7 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
+                      apr_pool_t *scratch_pool)
+   {
+     svn_wc__db_pdh_t *src_pdh, *dst_pdh;
+  -  const char *src_relpath, *dst_relpath, *dst_op_root_relpath;
+  +  const char *src_relpath, *dst_relpath;
+     apr_int64_t dst_op_depth;
+   
+     SVN_ERR_ASSERT(svn_dirent_is_absolute(src_abspath));
+
+  ------------------------------------------------------------------------
+
+ +
+ +
+

svn update now accepts the --parents option + +

+

svn update now accepts the --parents +option. This option removes the need to manually create missing parent +directories when adding additional items to a sparse working copy.

+ +

For example, adding 3 files from different directories to a sparse +working copy required creating each file's parent directories first:

+
   $ svn co --depth=empty ${PROJECT_ROOT_URL} wc
+   $ svn up --depth=empty wc/A wc/A/D wc/A/D/G wc/A/D/H wc/A/B wc/A/B/E
+   $ svn up wc/A/D/G/pi wc/A/D/H/omega wc/A/B/E/alpha
+
+

This becomes much easier with the new --parents option:

+
   $ svn co --depth=empty ${PROJECT_ROOT_URL} wc
+   $ svn up --parents wc/A/D/G/pi wc/A/D/H/omega wc/A/B/E/alpha
+
+
+ +
+

New subcommand: svn relocate + +

+

A new svn relocate subcommand has been added. +It points a working copy to a different repository root URL, serving +the same purpose as the old svn switch --relocate syntax +which has now been deprecated. +

+ +
+

svn switch now checks ancestry + +

+

svn switch now checks that the working copy item being +switched shares common version control history with the URL to which +it is being switched.

+ +

This change was made to protect users from the unpleasant side +effects of oft-mistyped switch commands, such as accidentally +running svn switch ^/branches when you instead meant to +run svn switch ^/branches/SOME-BRANCH. As of +version 1.7, Subversion will check to see if the source URL and the +target working copy item are ancestrally related and, if they do not, +the switch operation will fail with an error.

+ +
   $ svn switch ^/branches
+   svn: E195012: Path '.' does not share common version control ancestry
+   with the requested switch location.  Use --ignore-ancestry to disable
+   this check.
+   $
+
+ +

What is meant by "ancestrally related"? In short, it means that if +you were to compare all the paths and revisions that each of these two +version controlled items has occupied over time — its current +repository location plus all previous ones, back through all the +copies and moves in its history — those two sets would +overlap.

+ +

As noted in the previous example's error message, this ancestry +check — which does come at some performance cost — may be +disabled by passing the --ignore-ancestry +option to the svn switch command.

+
+ +
+

svn diff can show copied files as if they were newly added + +

+

When svn diff shows a copied file, it usually shows how the +copied file differs from the file it was copied from. +Sometimes this isn't the desired form of output. There are situations where +a copied file needs to appear in its entirety, for instance when producing +a patch file to be applied elsewhere with a patch tool (such as +svn patch).

+ +

In Subversion 1.7, svn diff takes a new +--show-copies-as-adds option which causes copied +files to be shown in their entirety, just like newly added files are shown.

+ +
+ +
+

svn diff can show git-style diff annotations + +

+

svn diff takes a new +--git option which causes it to produce extra +annotations denoting added, deleted, and copied files. +This extended diff format was inspired by +git-diff.

+ +

svn diff --git is intended to produce patches which are +compatible to +git-apply, but there are limitations due to differences between +Subversion and git: +

    +
  • svn diff currently cannot display rename information. + Renames are always shown as a copy and a delete.
  • +
  • All paths in patches are shown relative to the repository root to + avoid ambiguity. It is possible that the numbers of leading path + components on the left and right side of the patch differ, + for instance if a diff between /trunk and + /branches/mybranch is shown. + This may prevent git-apply from applying such patches without + modification.
  • +
+

+ +

In a future release of Subversion, +svn patch will receive support for the +extra annotations produced by svn diff --git, so that additions, +copies, renames, and deletions can be handled explicitly rather than +implicitly.

+ +

The same diff format extensions are also supported by +Mercurial.

+ +
+ +
+

svn merge help text has been enhanced + +

+

The help text for the svn merge command has been enhanced. +It now explains common use cases and includes small examples, making it +more useful for quick reference. +

+ +
+

New subcommand: svnlook filesize + +

+

A new svnlook filesize subcommand has been added. +It returns the size of a given path in the repository, for +a given revision or transaction. This is a constant-time operation +regardless of the size of the file. In pre-commit hooks wanting to +block commits with too large files, svnlook filesize can now +be used instead of the much more costly workaround via +svnlook cat.

+
+ + +
+ +
+

API changes, improvements and language bindings + (client and server) + +

+ +

There are too many new and revised APIs in Subversion 1.7.0 to list +them all here. See the Subversion API +Documentation page for general API information. If you develop a +3rd-party client application that uses Subversion APIs, you should +probably look at the header files for the interfaces you use and see +what's changed.

+ +

As noted above, a small number of APIs in +libsvn_wc have slightly changed functionality from their +historical roots. Each of these cases has been documented as an +errata, +detailing the impact of these changes. All of the errata were the result of +behavior which was deemed buggy, and the API changes are an attempt to fix +these bugs. The circumstances under which each is triggered are relatively +rare, and we anticipate the actual impact to end users will be minimal.

+ +

Language bindings have mostly been updated for the new APIs, though +some may lag more than others.

+ +
+

JavaHL Updates + +

+ +

Due to the move to the Apache Software Foundation, the JavaHL bindings +have been similarly moved to a new package: org.apache.subversion. +The old package still exists, and will continue to ship for backward +compatibility reasons, but we recommend comsumers switch to the new package, +as only it will continue to be updated.

+ +

Also, JavaHL now requires Java 1.5 to compile. In addition, many of the APIs +in the new package have been switch to use generics, and other Java 1.5 +language features.

+ +
+ +
+ +
+

Bug fixes (client and server) + +

+ +

A great many bugs have been fixed. See the 1.7.0 section in the CHANGES file +for details.

+ +
+ +
+

Serf HTTP library improved and stabilized (client) + +

+ +

The libsvn_ra_serf repository access library has received +a lot of improvements and stabilization. +The design of serf facilitates +future performance improvements that are impossible to achieve with +neon. There were plans to make +serf the default HTTP access library for the 1.7 release. +But because of some remaining issues (for instance +issue #3979, +issue #3980, and +issue #3981), +Subversion 1.7 still uses neon by default. +Remaining problems are mostly due to insufficient infrastructure deployed +in the wild wild web, such as HTTP proxies that do not support HTTP/1.1. +Workarounds for these problems will be implemented for the next release. +serf will become the default HTTP access library in Subversion 1.8. +

+

+In the meantime, we encourage all users to try serf with Subversion 1.7 and +report any problems. Successful test reports are appreciated as well. +Tests in networks that use HTTP proxies or enterprise authentication are +particularly helpful. +You can configure which library the client should use on a default or +host-by-host basis by setting the http-library variable in the +client-side servers configuration file +(~/.subversion/servers).

+ +
+

Note that +server-side configuration changes might be required to avoid +performance regressions for serf clients in some setups.

+

The MaxKeepAliveRequests option in httpd.conf +needs to be increased from 100 (the default) to at least 1000 +(there is no reason why it could not be 10000). +This will improve performance by allowing serf clients to use fewer +TCP connections to the server. +Clients using neon will also work fine with this configuration.

+
+ +

Because serf clients issue a larger number of HTTP GET requests +than neon clients it is possible that serf clients cause quicker +growth of httpd server logs than neon clients do. As of 1.7.3, +the httpd error logs may also grow more rapidly with serf clients +than with neon clients; see +r1239697.

+ +

Known issues with svnrdump that manifest when the latter uses +the ra_serf library for HTTP access are documented under the 'svnrdump' section of this document.

+ +
+ +
+

Improved handling of HTTP redirects (client) + +

+ +

In the past, when the Subversion client encountered an HTTP redirect +response from the server, it displayed an obtuse, and rarely-useful error +message. Subversion 1.7 improves the situation by following permanent +redirects (301 Moved Permanently) for svn update and svn +info, and providing a more useful error message on temporary +redirects (302 Found and 307 Temporary Redirect).

+ +
+ +
+

Atomic revprop changes (client and server) + +

+ +

Revprop changes are now handled atomically. +This fixes a known race condition in the locking algorithm used by +svnsync (see issue #3546). It is possible to fix the svnsync race condition +even for pre-1.7 svnsync clients by installing the pre-revprop-change hook +script given in +comment 12 of issue #3546. (The hook script requires a 1.7 or newer +server for correctness.)

+ +
+ +
+

Merge-Tracking Enhancements + +

+ +

While there are scores of bug fixes, performance improvements, and other +changes to merge-tracking, the following are the major changes. See the +1.7.0 section in the CHANGES +file for a complete list.

+ +
+

Reduced subtree mergeinfo changes + +

+ +

Merges no longer record mergeinfo (describing the merge) on subtrees (that +have their own explicit mergeinfo), if the subtree was unaffected by the merge. +This should greatly reduce the number of spurious svn:mergeinfo +property changes for users who have large numbers of subtrees with explicit +mergeinfo.

+ +

If a change being merged contains svn:mergeinfo modifications these +will still be applied, just like any other property modifications. +So if the change being merged was itself the result of another merge +performed with a 1.5 or 1.6 client, excessive subtree mergeinfo changes +are still possible. Best results will be achieved for new branches +created and maintained exclusively with 1.7 clients.

+ +
+ +
+

Reintegrate merges are less restrictive + +

+ +

Reintegrate merges now succeed in the case where all the prior 'sync' +merges were done as subtree merges, but effectively all the changes were +merged from the target to the source. Reintegrate also works with shallow +targets, as long as none of the excluded subtrees are affected by the +merge.

+ +
+ +
+

Improved notification about mergeinfo changes + +

+ +

Merge-tracking aware merges now produce special notifications and headers +when a merge records mergeinfo describing a merge or elides mergeinfo. This +clearly differentiates between changes that are made due to application of a +diff from the merge source and those that are simply merge-tracking +'housekeeping' changes.

+ +

Below is an example of the new output, showing notifications about +application of a diff to the file lib/src/psi.c and mergeinfo +changes resulting from this merge.

+ +
   $ svn merge ^/trunk -c3 --depth infinity
+   --- Merging r3 into 'lib':
+   U    lib/src/psi.c
+   --- Recording mergeinfo for merge of r3 into '.':
+    U   .
+   --- Recording mergeinfo for merge of r3 into 'lib':
+    G   lib
+   --- Eliding mergeinfo from 'lib':
+    U   lib 
+
+ +
+ +
+

Merges into mixed-revision working copies now disallowed by default + +

+ +

To prevent unnecessary conflicts, svn merge will now fail +with an error if the merge target is a +mixed-revision working copy.

+ +

A mixed-revision working copy will need to be updated with +svn update before a merge can be performed into it. +This restriction has always existed during merges using the +--reintegrate option and it is now the default +behaviour for every type of merge.

+ +

For backwards-compatibility, there is a new option called +--allow-mixed-revisions which disables the +check for a mixed-revision working copy, except for reintegrate merges. +Using this option is not recommended. +Please use svn update instead.

+ +
+ +
+

The mergeinfo subcommand accounts for subtree and partial merges + +

+ +

The svn mergeinfo subcommand now flags revisions wich are +partially merged to a target with the '*' decorator. A revision +may be partially merged due to non-inheritable mergeinfo on the target or +because of explicit mergeinfo on some subtree of the target. The latter case +is ignored by default, but may be considered by using the new --depth + and -R options for svn mergeinfo.

+ +
+ +
+

Transitive record only merges + +

+ +

Merges performed with the --record-only option now apply +svn:mergeinfo diffs from the merge source.

+ +
+ +
+

Merges into sparse directories no longer cause tree conflicts + +

+ +

Merges into shallow working copies used to cause tree conflicts on nodes +which were affected by the merge but not present in the working copy. +In 1.7, no tree conflict is flagged. Instead, non-inheritable subtree mergeinfo +is created on the parents of missing nodes, so that later merges into working +copies that are not sparse will pick up any missing changes for those nodes.

+ +
+ +
+ +
+

Server-side performance tuning + +

+ +

Previous releases of Subversion already supported various caching +mechanism like memcached. In version 1.7, the servers will aggressively +cache data in-process to maximize performance. To mitigate the network +throughput as the next potential bottleneck in the chain, the data +compression rate can be configured as well.

+ +
+

Data caching + +

+ +

Per default, Subversion server processes will use a 16 MB memory +block to cache file and folder content. This amount is being allocated +by every server process, i.e., the maximum size of cache memory available +per process can roughly be estimated as

+ +
cache limit = 0.8 * (RAM size / max. server process count) - 4 MB
+
+ +

A reasonable upper limit to that in-process cache size is the size +of the active data set. This is usually the size of user files in /trunk +plus the size of all differing files on active branches. So, two or +three times the sum of all /trunk sizes or all active projects on that +server is a reasonable indication for a performance-optimal cache size. +

+ +

svnserve introduces a new optional --memory-cache-size +/ -M command line parameter to override the default cache +size. Using --cache-fulltexts and --cache-txdeltas +you may instruct the server what kind of data should be cached. The first +should always be enabled unless data is only read once as during a +svnrdump run. Text delta caching should be enabled unless +your server memory is low.

+ +

For mod_dav_svn, a 10 GB cache configuration with maximum +data coverage looks like this in httpd.conf + +

<IfModule dav_svn_module>
+    SVNInMemoryCacheSize 10485760
+    SVNCacheFullTexts on
+    SVNCacheTextDeltas on
+</IfModule>
+
+ +

As a side-effect, the memory consumption becomes more predictable +in many usage scenarios since there is less need to gather and pre-process +data. Please note that a cache size of 0 will deactivate the +new caching facilities and cause the server to fall back to 1.6 caching +mechanisms.

+ +
+ +
+

Network data compression level + +

+ +

Subversion servers are often disk or network I/O limited. With the +introduction of data caching, however, disk +I/O can be widely eliminated and the CPU load created by data +compression will become a bottleneck on fast network connections.

+ +

The default setting will allow for 10 to 15 MB/s net data throughput +(5 MB to 10 MB compressed data) per client and per CPU core. On a +multi-core server with a 1 Gb network connection or if clients are mainly +connected with very limited bandwidth, you may want to select a higher +compression rate to squeeze a little more data through the network at +the expense of significantly higher server CPU loads. If the server's NIC +is not a bottleneck, you may consider lowering the compression level to +1 or 2 for 100 Mb clients and to 0 +(compression off) for a network with predominately 1 Gb clients.

+ +

To that end, svnserve accepts the new optional +--compression or -c command line parameter. +mod_dav_svn supports the feature as well but its impact is +limited since over HTTP, network data compression is used only in certain +cases to begin with. The optional module parameter +SVNCompressionLevel controls it:

+ +
<IfModule dav_svn_module>
+    SVNCompressionLevel 9
+</IfModule>
+
+ +
+ +
+ +
+

Optimizations of diff, merge and blame + +

+ +

The svn diff algorithm, which is at the core of diff, +merge and blame, has undergone several optimizations. +For large files which have a lot of identical lines at the beginning +and/or the end, or files which have many lines which are unique to +one side of the comparison, the speedup can be very significant.

+ +
+ +
+

Detecting MIME types with libmagic + +

+ +

Subversion 1.7 can optionally be compiled with support for +libmagic to detect +MIME types of binary files which are added to version control. +This feature is used only for binary files for which no MIME type +is found via auto-props or the mime-types-file configuration option.

+ +
+ +
+

Changing case of file and directory names on Windows + +

+ +

Subversion on Windows now fully supports changing the case of +file and directory names. No more special +workarounds, a simple +'svn mv file.java File.java' just does the right thing.

+ +
+ +
+ +
+

Known issues in the release + +

+ +

There are some known issues in the Subversion 1.7.0 release. These +may be fixed in later 1.7.x releases.

+ +
+

64-bit RHEL2 + +

+ +

Building Subversion 1.7.0 and APR 1.4.5 from source on 64-bit RHEL2 +with the standard compiler will produce executables that SEGV on +startup. This problem is likely to affect all 64-bit x86 platforms +that use gcc 4.0.x or older and is due to APR bug +51851. +Workarounds include using a more recent gcc or configuring APR +with --disable-nonportable-atomics.

+ +
+ +
+

OS X 10.7 + +

+ +

The SQLite shipped with OS X 10.7 will produce executables that fail at +runtime with the error:

+
svn: E200030: Could not initialize SQLite shared cache
+

A fix for this problem will be included in the 1.7.1 release.

+ +
+ +
+

JavaHL SEGV during GC + +

+ +

The JavaHL bindings have moved to the org.apache.subversion package +with org.tigris.subversion provided as a compatibility layer. Using +the compatibility package will cause the JVM to SEGV when SVNAdmin or +SVNClient objects are finalized. A fix for this problem will be included +in the 1.7.1 release.

+ +
+ +
+

APR 1.4.6 + +

+ +

When Subversion is built with APR 1.4.6 some of the Subversion +regression tests will FAIL at random due to a change in the APR hash +table implementation. The APR change causes some Subversion output to +appear in a different order and the testsuite will FAIL when it +expects the old order; the regression tests for the Subversion +bindings may also FAIL. This is a bug in the testsuite and does not +indicate a failure in Subversion. A fix for the main regression tests +will be included in the 1.7.4 release.

+ +
+ +
+ +
+

Dependency, license and distribution changes + +

+ +

Subversion 1.7 marks the first official feature release as part of the +Apache Software Foundation. A few bits of minutiae have changed as a +result.

+ +
+

Subversion Dependency Distribution + +

+ +

Previous releases of Subversion shipped with companion artifacts which +included a number of Subversion dependencies. In the past, these dependencies +were hard to find and build, and not often installed on the target platform. +Today, this is no longer a problem, so we have discontinued shipping the +companion dependency tarballs. If you still want to get some of the required +Subversion dependencies before building, you can run the +get-deps.sh script in the root of the unpacked archive.

+ +
+ +
+

License changed to Apache License, version 2 + +

+ +

Since its inception, Subversion has a used a "modified Apache license". +The migration of the project to the Apache Software Foundation provided +an opprotunity to also change the license to the standard +Apache License, +version 2. Additionally, the copyright to the collective work is now +owned by the ASF. While this has very little practical effect, it does mean +consumers have one less license to worry about when deploying Subversion.

+ +
+ +
+

Download location changes + +

+ +

The download location for Subversion source tarballs +and other release artifacts +are now hosted by the Apache Software Foundation. This includes the official +distribution location, as well as +archives of all +previous Subversion releases. Of course, other locations are welcome to +continue to host Subversion distribution artifacts, but the Apache download +sites are now the canonical source for Subversion releases.

+ +
+ +
+

No longer shipping contrib/ + +

+ +

Since the early days of Subversion development, the Subversion repository +has hosted a section for various other tools and scripts related to +Subversion. As Subversion has become more popular, the need to host these +tools in the main repository has decreased to the point where we encourage +tool authors to host their contributions at one of a number of external +hosting platforms. For this reason, and the potentially uncertain nature of +some of the licenses on these scripts, we have stopped shipping the +contrib/ directory in the release tarballs. For the time being, +these scripts remain available via the +main +repository.

+ +
+ +
+ +
+

Subversion 1.5.x series no longer supported + +

+ +

The Subversion 1.5.x line is no longer supported. This doesn't +mean that your 1.5 installation is doomed; if it works well and is all +you need, that's fine. "No longer supported" just means we've stopped +accepting bug reports against 1.5.x versions, and will not make any +more 1.5.x bugfix releases.

+ +
+ + +
+ + + --- subversion-1.7.9.orig/debian/test.sh +++ subversion-1.7.9/debian/test.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# This is the meager start to a script that will test the package. + +SVN=/usr/bin/svn +SVNADMIN=/usr/bin/svnadmin + +# create test repository +rm -rf /var/lib/svn/* + +$SVNADMIN create --fs-type fsfs /var/lib/svn +$SVN mkdir -m '' file:///var/lib/svn/repos + +# uncomment repos stuff + +/etc/init.d/apache2 restart + --- subversion-1.7.9.orig/debian/watch +++ subversion-1.7.9/debian/watch @@ -0,0 +1,3 @@ +# 'man uscan' for the format and usage of this file +version=3 +http://www.apache.org/dist/subversion/subversion-(\d+.\d+.\d+).tar.gz