--- subversion-1.8.8.orig/debian/README.source +++ subversion-1.8.8/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.8.8.orig/debian/authz_svn.load +++ subversion-1.8.8/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.8.8.orig/debian/bin/svn-bisect +++ subversion-1.8.8/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.8.8.orig/debian/bin/svnwrap +++ subversion-1.8.8/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.8.8.orig/debian/changelog +++ subversion-1.8.8/debian/changelog @@ -0,0 +1,3315 @@ +subversion (1.8.8-1ubuntu3.3) trusty-security; urgency=medium + + * SECURITY UPDATE: Arbitrary code execution on clients through + malicious svn+ssh URLs + - debian/patches/CVE-2017-9800-1.8.18.patch: ensure that host + arguments to ssh cannot be treated as ssh options. + - CVE-2017-9800 + * SECURITY UPDATE: svnserve/sasl may authenticate users using the + wrong realm. + - debian/patches/CVE-2016-2167.patch: Reject invalid usernames when + SASL is being used. + - CVE-2016-2167 + * SECURITY UPDATE: remotely triggerable crash in the mod_authz_svn + module. + - debian/patches/CVE-2016-2167.patch: Reject requests with invalid + Destination headers. + - CVE-2016-2168 + * SECURITY UPDATE: denial-of-service caused by exponential XML + entity expansion ("billion laughs attack"). + - debian/patches/CVE-2016-8734-1,8.patch: properly error out the + parser on invalid data. + - CVE-2016-8734 + * SECURITY UPDATE: mod_dav_svn: integer overflow when parsing + skel-encoded request bodies. + - debian/patches/CVE-2015-5343.patch: Defer memory allocation + when reading skel-encoded requests. + - CVE-2015-5343 + + -- Steve Beattie Thu, 10 Aug 2017 00:00:57 -0700 + +subversion (1.8.8-1ubuntu3.2) trusty-security; urgency=medium + + * SECURITY UPDATE: denial of service via non-existing REPORT request + - debian/patches/CVE-2014-3580.patch: make sure repo patchs are + specified in subversion/mod_dav_svn/reports/deleted-rev.c, + subversion/mod_dav_svn/reports/file-revs.c, + subversion/mod_dav_svn/reports/get-location-segments.c, + subversion/mod_dav_svn/reports/get-locations.c, + subversion/mod_dav_svn/reports/inherited-props.c, + subversion/mod_dav_svn/reports/log.c, + subversion/mod_dav_svn/reports/mergeinfo.c. + - CVE-2014-3580 + * SECURITY UPDATE: denial of service via non-existing virtual transaction + name + - debian/patches/CVE-2014-8108.patch: check transaction names and + activity ids in subversion/mod_dav_svn/repos.c. + - CVE-2014-8108 + * SECURITY UPDATE: denial of service via large number of REPORT requests + - debian/patches/CVE-2015-0202.patch: refactor locking in + subversion/libsvn_fs_fs/tree.c. + - CVE-2015-0202 + * SECURITY UPDATE: denial of service via crafted parameter combinations + - debian/patches/CVE-2015-0248.patch: properly handle missing revision + numbers in subversion/mod_dav_svn/reports/get-location-segments.c, + subversion/svnserve/serve.c. + - CVE-2015-0248 + * SECURITY UPDATE: svn:author property spoofing issue + - debian/patches/CVE-2015-0251.patch: restrict svn:author modifications + in subversion/mod_dav_svn/deadprops.c. + - CVE-2015-0251 + * SECURITY UPDATE: incorrect anonymous access restriction + - debian/patches/CVE-2015-3184.patch: use force_authn() in Makefile.in, + build/ac-macros/apache.m4, build/run_tests.py, + subversion/mod_authz_svn/mod_authz_svn.c, + subversion/tests/cmdline/README, + subversion/tests/cmdline/davautocheck.sh, + subversion/tests/cmdline/mod_authz_svn_tests.py, + subversion/tests/cmdline/svntest/main.py, win-tests.py. + - CVE-2015-3184 + * SECURITY UPDATE: sensitive path information disclosure + - debian/patches/CVE-2015-3187.patch: fix order in + subversion/libsvn_repos/rev_hunt.c, added tests to + subversion/tests/cmdline/authz_tests.py, + subversion/tests/libsvn_repos/repos-test.c. + - CVE-2015-3187 + * debian/control: Depend on specific version of apache2-dev and + apache2-bin to make sure fix for CVE-2015-3185 is included. + + -- Marc Deslauriers Wed, 19 Aug 2015 14:32:44 -0400 + +subversion (1.8.8-1ubuntu3.1) trusty-security; urgency=medium + + * SECURITY UPDATE: incorrect ssl cert validation + - debian/patches/CVE-2014-3522.patch: properly validate hostnames in + subversion/include/private/svn_cert.h, + subversion/libsvn_ra_serf/util.c, + subversion/libsvn_subr/dirent_uri.c, + added tests to subversion/tests/libsvn_subr/dirent_uri-test.c. + - CVE-2014-3522 + * SECURITY UPDATE: md5 collision authentication leak + - debian/patches/CVE-2014-3528.patch: check if realm matches in + subversion/libsvn_subr/config_auth.c. + - CVE-2014-3528 + + -- Marc Deslauriers Wed, 13 Aug 2014 10:28:59 -0400 + +subversion (1.8.8-1ubuntu3) trusty; urgency=medium + + * Run the tests on powerpc again. + + -- Matthias Klose Mon, 24 Feb 2014 11:05:59 +0100 + +subversion (1.8.8-1ubuntu2) trusty; urgency=medium + + * Re-add lost python-all-dbg build dependency. + + -- Matthias Klose Sun, 23 Feb 2014 17:15:51 +0100 + +subversion (1.8.8-1ubuntu1) trusty; urgency=medium + + * Merge with Debian; remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + - Add DEP-8 test for Apache functionality. + - debian/patches/ruby19.patch: disable check for ruby 1.8, and backport + a few changes to the test suite. + - debian/control: added ruby-test-unit to Build-Depends + - Check for libtoolize instead of libtool, which is not used for + the build. + - Temporarily disable running the tests on powerpc. + + -- Matthias Klose Sun, 23 Feb 2014 16:47:32 +0100 + +subversion (1.8.8-1) unstable; urgency=medium + + * New upstream release. Refresh patches. + - Remove backported patches sqlite_3.8.x_workaround & swig-pl_build_fix + - Fix integer overflows with 32-bit svnserv, which could cause an infinite + loop (Closes: #738840) or inaccurate statistics (Closes: #738841) + - Work around SQLite not honoring umask when creating rep-cache.db. + (Closes: #735446) + - Includes security fix: + + CVE-2014-0032: mod_dav_svn crash when handling certain requests with + SVNListParentPath on (Closes: #737815) + * Add a subversion-dbg package. (Closes: #508147) + * Bump libdb5.1-dev → libdb5.3-dev (Closes: #738650) + + -- James McCoy Thu, 20 Feb 2014 20:38:10 -0500 + +subversion (1.8.5-2ubuntu3) trusty; urgency=medium + + * Temporarily disable running the tests on powerpc. + + -- Matthias Klose Sat, 22 Feb 2014 14:39:49 +0100 + +subversion (1.8.5-2ubuntu2) trusty; urgency=medium + + * Make the python and ruby tests verbose. + * Ignore the test results of the python-dbg bindings. + + -- Matthias Klose Fri, 21 Feb 2014 13:13:07 +0100 + +subversion (1.8.5-2ubuntu1) trusty; urgency=medium + + * Merge with Debian; remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + - Add DEP-8 test for Apache functionality. + - Build-depend on libdb5.3-dev, instead of libdb5.1-dev. + - debian/patches/ruby19.patch: disable check for ruby 1.8, and backport + a few changes to the test suite. + - debian/control: added ruby-test-unit to Build-Depends + - Check for libtoolize instead of libtool, which is not used for + the build. + + -- Matthias Klose Fri, 21 Feb 2014 10:47:48 +0100 + +subversion (1.8.5-2) unstable; urgency=medium + + * rules: Move comment out of multi-line variable definition so configure is + run with the correct flags. (Closes: #735609) + * control: Remove libsvn-ruby1.8 Provides from ruby-svn. + * Add patches/swig-pl_build_fix, from upstream, to fix a build failure when + configure is run with --enable-sqlite-compatibility. + + -- James McCoy Fri, 17 Jan 2014 20:05:25 -0500 + +subversion (1.8.5-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream release. (Closes: #725787) Rediff patches: + - Remove apr-abi1 (applied upstream), rename apr-abi2 to apr-abi + - Remove loosen-sqlite-version-check (shouldn't be needed) + - Remove java-osgi-metadata (applied upstream) + - svnmucc prompts for a changelog if none is provided. (Closes: #507430) + - Remove fix-bdb-version-detection, upstream uses "apu-config --dbm-libs" + - Remove ruby-test-wc (applied upstream) + - Fix “svn diff -r N file” when file has svn:mime-type set. + (Closes: #734163) + - Support specifying an encoding for mod_dav_svn's environment in which + hooks are run. (Closes: #601544) + - Fix ordering of “svnadmin dump” paths with certain APR versions. + (Closes: #687291) + - Provide a better error message when authentication fails with an + svn+ssh:// URL. (Closes: #273874) + - Updated Polish translations. (Closes: #690815) + + [ James McCoy ] + * Remove all traces of libneon, replaced by libserf. + * patches/sqlite_3.8.x_workaround: Upstream fix for wc-queries-test test + failurse. + * Run configure with --with-apache-libexecdir, which allows removing part of + patches/rpath. + * Re-enable auth-test as upstream has fixed the problem of picking up + libraries from the environment rather than the build tree. + (Closes: #654172) + * Point LD_LIBRARY_PATH at the built auth libraries when running the svn + command during the build. (Closes: #678224) + * Add a NEWS entry describing how to configure mod_dav_svn to understand + UTF-8. (Closes: #566148) + * Remove ancient transitional package, libsvn-ruby. + * Enable compatibility with Sqlite3 versions back to Wheezy. + * Enable hardening flags. (Closes: #734918) + * patches/build-fixes: Enable verbose build logs. + * Build against the default ruby version. (Closes: #722393) + + -- James McCoy Sun, 12 Jan 2014 19:48:33 -0500 + +subversion (1.7.14-1ubuntu2) trusty; urgency=medium + + * Check for libtoolize instead of libtool, which is not used for + the build. + + -- Matthias Klose Mon, 06 Jan 2014 23:47:01 +0100 + +subversion (1.7.14-1ubuntu1) trusty; urgency=medium + + * Merge with Debian; remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + - Add DEP-8 test for Apache functionality. + - Build-depend on libdb5.3-dev, instead of libdb5.1-dev. + - debian/control, debian/rules: build against default ruby, instead of + ruby1.8. + - debian/patches/ruby19.patch: disable check for ruby 1.8, and backport + a few changes to the test suite. + - debian/control: added ruby-test-unit to Build-Depends + + -- Matthias Klose Mon, 06 Jan 2014 23:18:34 +0100 + +subversion (1.7.14-1) unstable; urgency=medium + + * New upstream version. + - mod_dav_svn: Prevent crashes with some 3rd party modules. (Closes: + #728352) + - Includes security fix: + + CVE-2013-4505: mod_dontdothat restrictions bypassed by relative + requests (Closes: #730541) + + CVE-2013-4558: mod_dav_svn assertion when SVNAutoversioning is + enabled. + * Bump compat to debhelper 8 + * Use shlibs.local to handle intrapackage dependencies on private libraries. + * rules: Fix removal of libsvnjavahl-1.a/.la/.so from libsvn-dev. (Closes: + #711911) + * Remove obsolete conffiles under /etc/svn2cl. (Closes: #677990) + + -- James McCoy Fri, 27 Dec 2013 10:17:38 -0500 + +subversion (1.7.13-3) unstable; urgency=low + + * Remove architecture exclusions for libsvn-java. (Closes: #710498) + * Fix multi-arch Python include paths. (Closes: #698443) + * Add strict Depends on libsvn1 to libapach2-mod-svn since the latter + leverages some internal APIs and therefore must be upgraded in lock step. + (Closes: #705464) + * Standards-Version 3.9.5 (no change needed). + * Add strict minimum Depends on libsqlite3-0 to work around lack of build + time dependency information. (Closes: #721878) + + -- James McCoy Sat, 16 Nov 2013 11:33:37 -0500 + +subversion (1.7.13-2ubuntu3) trusty; urgency=low + + * debian/control, debian/rules: build against default ruby, instead of + ruby1.8. (LP: #1254052) + * debian/patches/ruby19.patch: disable check for ruby 1.8, and backport + a few changes to the test suite. + * debian/control: added ruby-test-unit to Build-Depends + + -- Marc Deslauriers Mon, 02 Dec 2013 10:03:16 -0500 + +subversion (1.7.13-2ubuntu2) trusty; urgency=low + + * Build-depend on libdb5.3-dev, instead of libdb5.1-dev. + + -- Dmitrijs Ledkovs Mon, 04 Nov 2013 08:01:36 +0000 + +subversion (1.7.13-2ubuntu1) trusty; urgency=low + + * Merge from Debian unstable. Remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + - Add DEP-8 test for Apache functionality. + + -- William Grant Sat, 19 Oct 2013 11:53:15 +0000 + +subversion (1.7.13-2) unstable; urgency=low + + * Remove unnecessary libapache2-svn.prem. (Closes: #726717) + + -- James McCoy Fri, 18 Oct 2013 23:23:06 -0400 + +subversion (1.7.13-1) unstable; urgency=low + + [ Peter Samuelson ] + * New upstream version. (Closes: #719476) + - patches/CVE-2013-1968.patch, patches/CVE-2013-2112.patch: remove, + obsoleted + - Includes security fixes: + + CVE-2013-4131: Remotely triggered crash in mod_dav_svn (Closes: + #717794) + + CVE-2013-4277: Local privilege escalation vulnerability via symlink + attack (Closes: #721542) + + CVE-2013-2088: Arbitrary code execution in check-mime-type.pl and + svn-keyword-check.pl contrib scripts. + + [ James McCoy ] + * Add myself to uploaders. + * Acknowledge NMUs. + * Canonicalize the Vcs-* URLs. Thanks, Lintian. + * Remove Guilherme de S. Pastore from Uploaders. (Closes: #698270) + * Add Breaks: svnmailer (<< 1.0.9) to python-subversion. (Closes: #726491) + * Remove obsolete conffile /etc/emacs/site-start.d/50psvn.el. (Closes: + #705033) + + -- James McCoy Wed, 16 Oct 2013 20:53:11 -0400 + +subversion (1.7.9-1+nmu6ubuntu3) saucy; urgency=low + + * Re-enable kwallet support on arm64 now that kde4libs is built. + + -- William Grant Tue, 15 Oct 2013 23:25:04 +1100 + +subversion (1.7.9-1+nmu6ubuntu2) saucy; urgency=low + + * Temporarily disable kwallet integration on aarch64, as having revision + control systems is more important than having all their fancy plugins. + + -- Adam Conrad Sat, 12 Oct 2013 06:44:12 -0600 + +subversion (1.7.9-1+nmu6ubuntu1) saucy; urgency=low + + * Merge from Debian unstable. Remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + * Includes changes from Debian nmu5 and nmu6 to restore the Apache module + (LP: #1209493). Thanks to James McCoy for the Debian NMUs. + * d/tests/libapache2-mod-svn: add dep8 test for Apache functionality. + + -- Robie Basak Mon, 07 Oct 2013 15:35:59 +0000 + +subversion (1.7.9-1+nmu6) unstable; urgency=low + + * Add Breaks/Replaces: libapache2-svn to libapach2-mod-svn. + + -- James McCoy Tue, 01 Oct 2013 00:28:55 -0400 + +subversion (1.7.9-1+nmu5) unstable; urgency=low + + * Non-maintainer upload. + * Re-enable libapache2-svn build (Closes: #725028) + * Adjust packaging for Apache 2.4 compatibility (Closes: #712004) + - Rename libapache2-svn to libapache2-mod-svn and add a transitional + package + - Add apache2-dev & dh-apache2 to Build-Depends + - Add apache2-api-20120211 as a Depends for libapache2-mod-svn + - Update maintainer scripts to use apache2-maintscript-helper + + -- James McCoy Mon, 30 Sep 2013 19:02:34 -0400 + +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+nmu3ubuntu1) saucy; urgency=low + + * Merge from Debian unstable. Remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + + -- Martin Pitt Fri, 12 Jul 2013 10:41:13 +0200 + +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+nmu2ubuntu2) saucy; urgency=low + + * Rebuild against pkg-create-dbgsym with fixed python*-dbg package handling. + (LP: #1192111) + + -- Martin Pitt Thu, 20 Jun 2013 07:50:39 +0200 + +subversion (1.7.9-1+nmu2ubuntu1) saucy; urgency=low + + * Merge from Debian unstable. Remaining changes: + - Create pot file on build. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - only build on requested python versions (X-Python-Versions:) + - Do not apply java-build patch. + - Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + + -- Andy Whitcroft Mon, 17 Jun 2013 11:20:34 +0100 + +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-1ubuntu3) raring; urgency=low + + * Fix python multi-arch includes issues. + + -- Chris J Arges Thu, 17 Jan 2013 12:25:15 -0600 + +subversion (1.7.5-1ubuntu2) quantal; urgency=low + + * Drop svn2cl to Suggests; we don't particularly need it in Ubuntu main + (LP: #1048824). + + -- Colin Watson Fri, 28 Sep 2012 11:53:18 +0100 + +subversion (1.7.5-1ubuntu1) quantal; urgency=low + + * Merge from Debian unstable. Remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - Build-depend on python-dbg. + - Build-depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + + -- Andy Whitcroft Thu, 21 Jun 2012 15:36:36 +0100 + +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-3ubuntu5) quantal; urgency=low + + * Switch from libdb4.8-dev to libdb5.1-dev, tracking apr-util. + + -- Adam Conrad Wed, 20 Jun 2012 19:19:02 -0600 + +subversion (1.6.17dfsg-3ubuntu4) quantal; urgency=low + + * Port to gcc-4.7. + * Fix APR hash ordering issues in much of the test suite. + * Fix python svn_stream_read() to allow Long integers matching its own + generated constants. + * Fix "svn log -g" output for merges. + + -- Andy Whitcroft Wed, 20 Jun 2012 13:44:11 +0100 + +subversion (1.6.17dfsg-3ubuntu3) precise; urgency=low + + * Build using dh_python2 + + -- Matthias Klose Sat, 17 Dec 2011 15:01:54 +0000 + +subversion (1.6.17dfsg-3ubuntu2) precise; urgency=low + + * Allow libserf-dev to satisfy serf build-dependency. + + -- Colin Watson Sun, 27 Nov 2011 19:02:00 +0000 + +subversion (1.6.17dfsg-3ubuntu1) precise; urgency=low + + * Resynchronise with Debian. Remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - Build-depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + * Re-enable the serf backend (LP: #830778). + + -- Colin Watson Sun, 27 Nov 2011 12:45:05 +0000 + +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-2ubuntu1) precise; urgency=low + + * Resynchronise with Debian. Remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - Build-depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Disable the serf backend because serf is in universe. + * Sync up python-subversion-dbg control fields with python-subversion. + + -- Colin Watson Wed, 16 Nov 2011 16:08:09 +0000 + +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-4ubuntu6) precise; urgency=low + + * Rebuild for Perl 5.14. + + -- Colin Watson Wed, 16 Nov 2011 01:03:49 +0000 + +subversion (1.6.12dfsg-4ubuntu5) oneiric; urgency=low + + * SECURITY UPDATE: denial of service via baselined WebDAV resource + request + - debian/patches/CVE-2011-1752.patch: disallow GETs of baselined + versions of resources in subversion/mod_dav_svn/repos.c. + - CVE-2011-1752 + * SECURITY UPDATE: mod_dav_svn resource exhaustion via infinite loop + - debian/patches/CVE-2011-1783.patch: validate path in + subversion/libsvn_repos/authz.c. + - CVE-2011-1783 + * SECURITY UPDATE: mod_dav_svn permissions bypass via incorrect + resource URL + - debian/patches/CVE-2011-1921.patch: validate path in + subversion/mod_dav_svn/authz.c. + - CVE-2011-1921 + + -- Marc Deslauriers Fri, 05 Aug 2011 10:53:00 -0400 + +subversion (1.6.12dfsg-4ubuntu4) oneiric; urgency=low + + * Disable KWallet support on armel, again temporarily. + + -- Colin Watson Fri, 06 May 2011 14:21:16 +0100 + +subversion (1.6.12dfsg-4ubuntu3) oneiric; urgency=low + + * Temporarily disable Java and tests on armel to resolve a circular + build-depends loop in Oneiric. These will be re-enabled shortly. + + -- Colin Watson Fri, 06 May 2011 12:27:29 +0100 + +subversion (1.6.12dfsg-4ubuntu2) natty; urgency=low + + * SECURITY UPDATE: denial of service via request containing lock token + - debian/patches/CVE-2011-0715.patch: correctly handle locks being + passed when authn isn't enabled in subversion/mod_dav_svn/repos.c, + subversion/mod_dav_svn/version.c. + - CVE-2011-0715 + + -- Marc Deslauriers Mon, 21 Mar 2011 13:03:32 -0400 + +subversion (1.6.12dfsg-4ubuntu1) natty; urgency=low + + * Merge with Debian unstable. Remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Disable the serf backend because serf is in universe. + - Don't override LD_LIBRARY_PATH completely but prepend to it as to not + break fakeroot. + - Fix FTBFS against Python 2.7 by disabling some problematic tests. + - debian/tools/Makefile: + + Add APR_LIBS and use it when linking svn-make-config + + svn_config_ensure() moved from libsvn_client/libsvn_client-1.la to + libsvn_subr/libsvn_subr-1.la. + + -- Michael Bienia Fri, 28 Jan 2011 14:14:19 +0100 + +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-2ubuntu3) natty; urgency=low + + * debian/tools/Makefile: add APR_LIBS and use it when linking + svn-make-config: + APR_LIBS = `apr-config --ldflags --link-ld --libs` + + -- Loïc Minier Sat, 20 Nov 2010 11:21:18 +0100 + +subversion (1.6.12dfsg-2ubuntu2) natty; urgency=low + + [ Barry Warsaw ] + * Fix FTBFS against Python 2.7 by disabling some problematic tests. + (LP: #670139) + + [ Loïc Minier ] + * Fix FTBFS in natty; LP: #670139; thanks Barry Warsaw. + - Don't override LD_LIBRARY_PATH completely but prepend to it as to not + break fakeroot. + - debian/tools/Makefile: svn_config_ensure() moved from + libsvn_client/libsvn_client-1.la to libsvn_subr/libsvn_subr-1.la. + + -- Barry Warsaw Fri, 12 Nov 2010 15:16:04 -0500 + +subversion (1.6.12dfsg-2ubuntu1) natty; urgency=low + + * Merge from debian unstable. Remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Disable the serf backend because serf is in universe. + - Amend the XS-Python-Version line to ">= 2.4" rather than explicit + versions. + + -- Michael Vogt Mon, 18 Oct 2010 15:34:10 +0200 + +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-1ubuntu1) maverick; urgency=low + + * Merge from debian testing (LP: #600914), remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Disable the serf backend because serf is in universe. + - Amend the XS-Python-Version line to ">= 2.4" rather than explicit + versions. + + -- Max Bowsher Fri, 02 Jul 2010 06:54:21 +0100 + +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-2ubuntu1) lucid; urgency=low + + * Merge from debian unstable (LP: #483953). + Includes enabling kwallet support (LP: #481792, #466078). + Remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + - Disable the serf backend because serf is in universe. + * Amend the XS-Python-Version line to ">= 2.4" rather than explicit + versions (only building for 2.6 in Lucid since that is the onl Python in + Lucid). + + -- Max Bowsher Fri, 11 Dec 2009 23:48:13 +0000 + +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-1ubuntu1) karmic; urgency=low + + * Merge from debian unstable (LP: #406245), remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - Don't build for python2.4, not in main. + - debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + * Disable the serf backend because serf is in universe. + + -- Anders Kaseorg Mon, 24 Aug 2009 19:09:22 -0400 + +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-1ubuntu2) karmic; urgency=low + + * debian/rules: Manually create the doxygen output directory, otherwise + we get weird build failures when running parallel builds. + + -- Steve Langasek Wed, 10 Jun 2009 05:43:50 +0000 + +subversion (1.6.1dfsg-1ubuntu1) karmic; urgency=low + + * Merge from Debian experimental, remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - Don't build for python2.4, not in main. + * Fixes autodetection of neon. LP: #384715. + + -- Steve Langasek Tue, 09 Jun 2009 23:53:06 +0000 + +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-1ubuntu1) karmic; urgency=low + + * Merge from Debian unstable, remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + - Do not build-depend on serf. The client can be compiled against either + libneon or libserf (or both), as they offer competing implementations. + serf is available in universe only. + - Don't build for python2.4, not in main. + - Build-depend on libdb4.7-dev instead of libdb4.6-dev, tracking + libaprutil. + + -- Steve Langasek Sat, 06 Jun 2009 22:57:04 +0000 + +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-1ubuntu2) jaunty; urgency=low + + * Build for python2.6. + + -- Matthias Klose Mon, 23 Feb 2009 17:39:04 +0100 + +subversion (1.5.4dfsg1-1ubuntu1) jaunty; urgency=low + + * Merge with Debian; remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + - (Build-)depend on default-jre-headless/-jdk. + - Do not apply java-build patch. + + -- Matthias Klose Mon, 17 Nov 2008 08:56:51 +0100 + +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-1ubuntu2) intrepid; urgency=low + + * (Build-)depend on default-jre-headless/-jdk. + * Do not apply java-build patch. + + -- Matthias Klose Thu, 31 Jul 2008 08:29:58 +0000 + +subversion (1.5.1dfsg1-1ubuntu1) intrepid; urgency=low + + * Merge with Debian; remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + + -- Matthias Klose Sun, 27 Jul 2008 11:21:14 +0200 + +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-4ubuntu2) intrepid; urgency=low + + * Explicitely build-depend on libdb4.6-dev to match the db dependency + of libaprutil1-dev. + + -- Matthias Klose Mon, 07 Jul 2008 14:15:22 +0200 + +subversion (1.5.0dfsg1-4ubuntu1) intrepid; urgency=low + + * Merge with Debian; remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + + -- Matthias Klose Mon, 07 Jul 2008 13:44:50 +0200 + +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-1ubuntu2) intrepid; urgency=low + + * Do not build-depend on serf. The client can be compiled against either + libneon or libserf (or both), as they offer competing implementations. + serf is available in universe only. + + -- Matthias Klose Tue, 24 Jun 2008 15:05:21 +0000 + +subversion (1.5.0dfsg1-1ubuntu1) intrepid; urgency=low + + * Merge with Debian; remaining changes: + - Create pot file on build. + - Build a python-subversion-dbg package. + + -- Matthias Klose Tue, 24 Jun 2008 14:13:13 +0200 + +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-2ubuntu1) hardy; urgency=low + + * Merge with Debian; remaining changes: + - Create pot file on build. + - Fix bashisms in tools/po/po-update.sh. + - Build for all supported python versions. + - Build a python-subversion-dbg package. + - debian/rules: Do not let the failed ruby swig tests fail the build. They + are currently broken, work in progress in Debian (Debian #453166). + - Drop hppa java support. + + -- Matthias Klose Tue, 11 Mar 2008 06:28:25 +0000 + +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.6dfsg1-0ubuntu1) hardy; urgency=low + + * Merge with Debian svn repository (trunk r823); remaining changes: + - Create pot file on build. + - Fix bashisms in tools/po/po-update.sh. + - Build for all supported python versions. + - Build a python-subversion-dbg package. + - debian/rules: Do not let the failed ruby swig tests fail the build. They + are currently broken, work in progress in Debian (Debian #453166). + - Drop hppa java support. + + -- Matthias Klose Wed, 30 Jan 2008 12:45:05 +0100 + +subversion (1.4.6dfsg1-1) unstable; urgency=low + + * New upstream version. + * 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-1ubuntu5) hardy; urgency=medium + + * Add debian/patches/python-memleak: Fix major memory leak in the + Python bindings. Taken from Debian SVN head. (LP: #54253) + + -- Jelmer Vernooij Fri, 18 Jan 2008 01:28:28 +0100 + +subversion (1.4.4dfsg1-1ubuntu4) hardy; urgency=low + + * debian/control: + - libneon 26 -> 27. + - libdb 4.4 -> 4.6. + - Bump libaprutil1-dev build dependency to ensure that we build against + one that also links against db4.6. + * Add debian/patches/neon27: Fix configure tests for defining the + right version #defines for libneon27. Taken from Debian SVN head. + * Add debian/patches/ruby-newswig: Fix duplicate symbols in SWIG so that it + actually builds. Taken from Debian SVN head. (Debian #458771) + * debian/rules: Do not let the failed ruby swig tests fail the build. They + are currently broken, work in progress in Debian (Debian #453166). + + -- Martin Pitt Thu, 03 Jan 2008 10:16:24 +0100 + +subversion (1.4.4dfsg1-1ubuntu3) gutsy; urgency=low + + * Build separate libsvn_swig_py libraries for each python version. + LP: #91848. + + -- Matthias Klose Thu, 27 Sep 2007 11:10:46 +0200 + +subversion (1.4.4dfsg1-1ubuntu2) gutsy; urgency=low + + * Drop hppa java support for now + + -- LaMont Jones Mon, 13 Aug 2007 15:43:46 -0600 + +subversion (1.4.4dfsg1-1ubuntu1) gutsy; urgency=low + + * Merge with Debian; remaining changes: + - Create pot file on build. + - Fix bashisms in tools/po/po-update.sh. + - Build for all supported python versions. + - Build a python-subversion-dbg package. + + -- Matthias Klose Mon, 11 Jun 2007 11:24:52 +0200 + +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-1ubuntu1) feisty; urgency=low + + * Merge from Debian experimental; remaining changes: + - Create pot file on build. + - Fix bashisms in tools/po/po-update.sh. + - Build for all supported python versions. + - Build a python-subversion-dbg package. + + -- Matthias Klose Tue, 20 Mar 2007 06:47:26 +0100 + +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-2ubuntu5) feisty; urgency=low + + * Build-depend on python-all-dev, python-all-dbg. + + -- Matthias Klose Sun, 18 Feb 2007 15:44:48 +0100 + +subversion (1.4.2dfsg1-2ubuntu4) feisty; urgency=low + + * Build a python-subversion-dbg package. + * Add modules for all supported python versions. + * Set Ubuntu maintainer address. + + -- Matthias Klose Sun, 18 Feb 2007 00:43:04 +0100 + +subversion (1.4.2dfsg1-2ubuntu3) feisty; urgency=low + + * Rebuild for python2.5 as the default python version. + + -- Matthias Klose Fri, 12 Jan 2007 13:18:35 +0000 + +subversion (1.4.2dfsg1-2ubuntu2) feisty; urgency=low + + * Fix bashisms in tools/po/po-update.sh. + + -- Matthias Klose Wed, 13 Dec 2006 20:29:01 +0100 + +subversion (1.4.2dfsg1-2ubuntu1) feisty; urgency=low + + * Merge with Debian unstable; remaining changes: + - Create pot file on build. + + -- Matthias Klose Wed, 13 Dec 2006 17:57:16 +0100 + +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-3ubuntu2) edgy; urgency=low + + * Backport improved python bindings (Jelmer Vernooij), + cleanup patch and adapt for 1.3.2. Ubuntu #51304. + + -- Matthias Klose Wed, 4 Oct 2006 21:36:23 +0000 + +subversion (1.3.2-3ubuntu1) edgy; urgency=low + + * Merge from debian unstable, remaining changes: + - create pot file on build, + - python2.4. + + -- Scott James Remnant Mon, 10 Jul 2006 16:22:15 +0100 + +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-3ubuntu1) dapper; urgency=low + + * Merge new upstream version from Debian, UVF exception approved by mdz. + * Very (very, very) carefully merge our Java-related changes with Debian's + rather different Java changes to produce something that should work. + * Create a python2.4-subversion transitional package to smooth upgrades. + + -- Adam Conrad Mon, 8 May 2006 14:07:51 +1000 + +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-1ubuntu3) dapper; urgency=low + + * debian/rules: Create a POT file on package build + + -- Michael Vogt Fri, 5 May 2006 01:48:11 +0200 + +subversion (1.3.0-1ubuntu2) dapper; urgency=low + + * Reenable the build of libsvn-javahl, build using java-gcj-compat-dev. + * libsvn-javahl: Prefer gij over kaffe. + + -- Matthias Klose Thu, 23 Mar 2006 14:10:04 +0000 + +subversion (1.3.0-1ubuntu1) dapper; urgency=low + + * Merge with Debian by hand, bringing in shiny new upstream version. + * Disable the testsuite for the ruby bindings for now, as they are + failing obscurely, and "broken bindings are slightly better than + no bindings"; I will investigate the breakage later. + + -- Adam Conrad Tue, 17 Jan 2006 12:35:07 +1100 + +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-3ubuntu1) dapper; urgency=low + + * Merge with the final Debian release of 1.2.3dfsg1-3, bringing in + fixes to the clean target, better documentation of the libdb4.3 + upgrade and build fixes to work with swig1.3_1.3.27. + + -- Adam Conrad Mon, 5 Dec 2005 01:26:14 +1100 + +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-2ubuntu1) dapper; urgency=low + + * Roll this release from the Debian pkg-subversion SVN repo (Ubuntu #19334) + * Stop building python2.3 bindings, as python2.3 is leaving Ubuntu main. + * Disable the build of libsvn-javahl, since kaffe is in Ubuntu universe. + + -- Adam Conrad Sat, 26 Nov 2005 01:17:20 +1100 + +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-1ubuntu1) breezy; urgency=low + + * Resynchronise with Debian. + + -- Michael Vogt Wed, 29 Jun 2005 13:09:32 +0200 + +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-2ubuntu1) breezy; urgency=low + + * Sync with Debian. + + -- Matthias Klose Wed, 25 May 2005 00:09:22 +0000 + +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-2ubuntu4) hoary; urgency=low + + * Build a python2.3-subversion package as well. + + -- Matthias Klose Tue, 17 May 2005 09:55:44 +0000 + +subversion (1.1.1-2ubuntu3) hoary; urgency=low + + * python2.4-subversion: Add conflict to python2.3-subversion. + Closes: #4957. + + -- Matthias Klose Mon, 10 Jan 2005 08:31:59 +0100 + +subversion (1.1.1-2ubuntu2) hoary; urgency=low + + * Tighten build dependency on python. + + -- Matthias Klose Fri, 17 Dec 2004 14:02:19 +0100 + +subversion (1.1.1-2ubuntu1) hoary; urgency=low + + * Build using python2.4. + * debian/control.m4: Fix generation of control file for PYVERSION != 2.3. + + -- Matthias Klose Wed, 15 Dec 2004 20:37:50 +0100 + +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.8.8.orig/debian/compat +++ subversion-1.8.8/debian/compat @@ -0,0 +1 @@ +8 --- subversion-1.8.8.orig/debian/contrib/commit-email.pl +++ subversion-1.8.8/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.8.8.orig/debian/contrib/emacs/50psvn.el +++ subversion-1.8.8/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.8.8.orig/debian/contrib/emacs/dsvn.el +++ subversion-1.8.8/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.8.8.orig/debian/contrib/emacs/psvn.el +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn-clean +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn-fast-backup +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn_apply_autoprops.py +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn_load_dirs/LICENSE_AFL3.txt +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn_load_dirs/svn_load_dirs.README +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn_load_dirs/svn_load_dirs.pl +++ subversion-1.8.8/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.8.8.orig/debian/contrib/svn_load_dirs/svn_load_dirs_property_table.example +++ subversion-1.8.8/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.8.8.orig/debian/control +++ subversion-1.8.8/debian/control @@ -0,0 +1,211 @@ +Source: subversion +Section: vcs +Priority: optional +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Peter Samuelson +Uploaders: Troy Heber , + James McCoy +Build-Depends: debhelper (>= 8), libserf-dev (>= 1.2), zlib1g-dev, + libapr1-dev, libaprutil1-dev, libdb5.3-dev, + libsasl2-dev, apache2-dev (>= 2.4.7-1ubuntu4.5), dh-apache2, + libsqlite3-dev (>= 3.7.12), libgnome-keyring-dev, libdbus-1-dev, kdelibs5-dev, + quilt, doxygen, autotools-dev, autoconf, libtool, swig, + python-all-dev, perl, libperl-dev, ruby, ruby-dev, + python-all-dbg, default-jdk, junit +Build-Conflicts: libsvn-dev (<< 1.8~), ruby-test-unit +Homepage: http://subversion.apache.org/ +Vcs-Svn: svn://anonscm.debian.org/pkg-subversion/src/1.8.x/ +Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-subversion/src/1.8.x/ +Standards-Version: 3.9.5 +X-Python-Version: >= 2.4 +XS-Testsuite: autopkgtest + +Package: subversion +Architecture: any +Depends: libsvn1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} +Suggests: subversion-tools, db5.3-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: subversion-dbg +Section: debug +Priority: extra +Architecture: any +Depends: subversion (= ${binary:Version}) | libsvn1 (= ${binary:Version}) | + libapache2-mod-svn (= ${binary:Version}) | subversion-tools (= ${binary:Version}) | + python-subversion (= ${binary:Version}) | ruby-svn (= ${binary:Version}) | + libsvn-perl (= ${binary:Version}) | libsvn-java (= ${binary:Version}) | ${misc:Depends} +Description: Debug symbols for Apache Subversion + This package contains debug symbols for libsvn1 and its dependent packages + including subversion, libapache2-mod-svn, and the various programming language + interfaces. + +Package: libsvn1 +Section: libs +Architecture: any +Multi-Arch: same +Pre-Depends: multiarch-support +Depends: libsqlite3-0 (>= 3.7.12), ${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, libserf-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: libapache2-mod-svn +Section: httpd +Architecture: any +Depends: apache2-bin (>= 2.4.7-1ubuntu4.5), apache2-api-20120211, libsvn1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} +Breaks: libapache2-svn (<< 1.7.9-1+nmu5) +Replaces: libapache2-svn (<< 1.7.9-1+nmu5) +Suggests: db5.3-util +Description: Apache Subversion server modules for Apache httpd + This package provides the mod_dav_svn and mod_authz_svn modules for + the Apache 2.4 web server. These modules provide Apache Subversion's WebDAV + server backend, to serve repositories over the http and https + protocols. See the 'subversion' package for more information. + +Package: libapache2-svn +Section: oldlibs +Priority: extra +Architecture: all +Depends: libapache2-mod-svn, ${misc:Depends} +Description: Apache Subversion server modules for Apache httpd (dummy package) + This is a transition package to install the Apache Subversion server + module for Apache httpd. You may remove this package if nothing depends + on it. + +Package: python-subversion +Section: python +Architecture: any +Pre-Depends: multiarch-support +Depends: ${shlibs:Depends}, ${python:Depends}, ${misc:Depends} +Suggests: python-subversion-dbg +Provides: ${python:Provides} +Breaks: svnmailer (<< 1.0.9) +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: python-subversion-dbg +Priority: extra +Section: python +Architecture: any +Pre-Depends: multiarch-support +Depends: python-subversion (= ${binary:Version}), python-dbg, ${shlibs:Depends}, ${python:Depends}, ${misc:Depends} +Provides: ${python:Provides} +Description: Python bindings for Subversion (debug extension) + This is a set of Python interfaces to libsvn, the 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. + . + This package contains the extension built for the python debug interpreter. + +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 +Suggests: ruby-svn, svn2cl +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: ruby, ${shlibs:Depends}, ${misc:Depends} +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. --- subversion-1.8.8.orig/debian/copyright +++ subversion-1.8.8/debian/copyright @@ -0,0 +1,418 @@ +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. + +==================================================================== + +subversion/libsvn_subr/utf_width.c is: + Copyright 2007 by Markus Kuhn + Permission to use, copy, modify, and distribute this software + for any purpose and without fee is hereby granted. The author + disclaims all warranties with regard to this software. + +==================================================================== + +tools/dist/_gnupg.py is: + Copyright (c) 2008-2011 by Vinay Sajip. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name(s) of the copyright holder(s) may not be used to endorse or + promote products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) "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 COPYRIGHT HOLDER(S) 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. + +==================================================================== + +Original content of subversion/libsvn_subr/pseudo_md5.c is, with modifications +following Subversion's license: + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +==================================================================== + +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.8.8.orig/debian/dav_svn.conf +++ subversion-1.8.8/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.8.8.orig/debian/dav_svn.load +++ subversion-1.8.8/debian/dav_svn.load @@ -0,0 +1,2 @@ +# Depends: dav +LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so --- subversion-1.8.8.orig/debian/libapache2-mod-svn.NEWS +++ subversion-1.8.8/debian/libapache2-mod-svn.NEWS @@ -0,0 +1,15 @@ +libapache2-mod-svn (1.8.5-1) unstable; urgency=low + + Prior to Subversion 1.8, hook scripts run on a mod_dav_svn-based Subversion + server had problems with non-ASCII input and output because Apache HTTPD + modules always run in the "C" locale. + + Subversion 1.8 addresses these problems with a new SVNUseUTF8 option for + mod_dav_svn. If this option is set, mod_dav_svn assumes that all hook script + input/output is encoded in UTF-8. If this option is set, hook scripts must + write error messages to stderr in UTF-8. + + Hook scripts should use a UTF-8 locale if the SVNUseUTF8 option is active, + which can be configured in the new hooks-env configuration file. + + -- James McCoy Sat, 04 Jan 2014 19:33:40 -0500 --- subversion-1.8.8.orig/debian/libapache2-mod-svn.README.Debian +++ subversion-1.8.8/debian/libapache2-mod-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.8.8.orig/debian/libapache2-mod-svn.dirs +++ subversion-1.8.8/debian/libapache2-mod-svn.dirs @@ -0,0 +1 @@ +usr/share/doc/libapache2-mod-svn --- subversion-1.8.8.orig/debian/libapache2-mod-svn.examples +++ subversion-1.8.8/debian/libapache2-mod-svn.examples @@ -0,0 +1 @@ +tools/xslt/svnindex.* --- subversion-1.8.8.orig/debian/libapache2-mod-svn.install +++ subversion-1.8.8/debian/libapache2-mod-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.8.8.orig/debian/libapache2-mod-svn.lintian-overrides +++ subversion-1.8.8/debian/libapache2-mod-svn.lintian-overrides @@ -0,0 +1,2 @@ +# this is config documentation, not "how to build the package" +libapache2-mod-svn: package-contains-upstream-install-documentation usr/share/doc/libapache2-mod-svn/INSTALL.authz.gz --- subversion-1.8.8.orig/debian/libapache2-mod-svn.postinst +++ subversion-1.8.8/debian/libapache2-mod-svn.postinst @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + if [ -f '/etc/apache2/#enable_authz_svn#' ]; then + # Enable on upgrades where this used to be implied by dav_svn.load + if [ -e /usr/share/apache2/apache2-maintscript-helper ]; then + . /usr/share/apache2/apache2-maintscript-helper + apache2_invoke enmod authz_svn + rm -f '/etc/apache2/#enable_authz_svn#' + fi + fi + ;; +esac + +#DEBHELPER# --- subversion-1.8.8.orig/debian/libapache2-mod-svn.preinst +++ subversion-1.8.8/debian/libapache2-mod-svn.preinst @@ -0,0 +1,17 @@ +#!/bin/sh + +set -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.8.8.orig/debian/libsvn-dev.install +++ subversion-1.8.8/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.8.8.orig/debian/libsvn-dev.links +++ subversion-1.8.8/debian/libsvn-dev.links @@ -0,0 +1 @@ +usr/share/doc/libsvn1 usr/share/doc/libsvn-dev --- subversion-1.8.8.orig/debian/libsvn-dev.postinst +++ subversion-1.8.8/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.8.8.orig/debian/libsvn-doc.examples +++ subversion-1.8.8/debian/libsvn-doc.examples @@ -0,0 +1 @@ +tools/examples/*.c --- subversion-1.8.8.orig/debian/libsvn-java.install +++ subversion-1.8.8/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.8.8.orig/debian/libsvn-java.links +++ subversion-1.8.8/debian/libsvn-java.links @@ -0,0 +1 @@ +usr/share/doc/libsvn1 usr/share/doc/libsvn-java --- subversion-1.8.8.orig/debian/libsvn-java.postinst +++ subversion-1.8.8/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.8.8.orig/debian/libsvn-perl.install +++ subversion-1.8.8/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.8.8.orig/debian/libsvn-perl.lintian-overrides +++ subversion-1.8.8/debian/libsvn-perl.lintian-overrides @@ -0,0 +1,3 @@ +# 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.* +no-symbols-control-file usr/lib/*/libsvn_swig_perl-1.so.* --- subversion-1.8.8.orig/debian/libsvn-ruby1.8.links +++ subversion-1.8.8/debian/libsvn-ruby1.8.links @@ -0,0 +1 @@ +usr/share/doc/ruby-svn usr/share/doc/libsvn-ruby1.8 --- subversion-1.8.8.orig/debian/libsvn-ruby1.8.postinst +++ subversion-1.8.8/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.8.8.orig/debian/libsvn1.examples +++ subversion-1.8.8/debian/libsvn1.examples @@ -0,0 +1 @@ +tools/dev/gdb-py --- subversion-1.8.8.orig/debian/libsvn1.install +++ subversion-1.8.8/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.8.8.orig/debian/libsvn1.lintian-overrides +++ subversion-1.8.8/debian/libsvn1.lintian-overrides @@ -0,0 +1,24 @@ +# 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_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 * +shlib-missing-in-symbols-control-file libsvn_fs_util-1 * +shlib-missing-in-symbols-control-file libsvn_fs_fs-1 * +shlib-missing-in-symbols-control-file libsvn_ra_serf-1 * +shlib-missing-in-symbols-control-file libsvn_ra_local-1 * +shlib-missing-in-symbols-control-file libsvn_fs_base-1 * +shlib-missing-in-symbols-control-file libsvn_auth_kwallet-1 * +shlib-missing-in-symbols-control-file libsvn_auth_gnome_keyring-1 * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_fs_util-1* * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_fs_fs-1* * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_ra_serf-1* * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_ra_local-1* * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_fs_base-1* * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_auth_kwallet-1* * +dev-pkg-without-shlib-symlink usr/lib/*/libsvn_auth_gnome_keyring-1* * +# Intentional, so people don't try to use private symbols. +symbols-declares-dependency-on-other-package libsvn-private --- subversion-1.8.8.orig/debian/libsvn1.symbols +++ subversion-1.8.8/debian/libsvn1.symbols @@ -0,0 +1,1484 @@ +libsvn_client-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + arbitrary_diff_walker_baton@Base 1.8 + svn_client_add2@Base 1.4 + svn_client_add3@Base 1.4 + svn_client_add4@Base 1.5 + svn_client_add5@Base 1.8 + 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_commit6@Base 1.8 + 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_context2@Base 1.8 + 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_diff6@Base 1.8 + 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_peg6@Base 1.8 + 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_merging_summary@Base 1.8 + svn_client_get_repos_root@Base 1.8 + 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_import5@Base 1.8 + 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_list3@Base 1.8 + 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_merge5@Base 1.8 + 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_peg5@Base 1.8 + 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_log2@Base 1.8 + 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_move7@Base 1.8 + svn_client_move@Base 1.4 + svn_client_open_ra_session2@Base 1.8 + 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_propget5@Base 1.8 + svn_client_propget@Base 1.4 + svn_client_proplist2@Base 1.4 + svn_client_proplist3@Base 1.5 + svn_client_proplist4@Base 1.8 + 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_driver2@Base 1.8 + svn_delta_path_driver@Base 1.4 + svn_delta_shim_callbacks_default@Base 1.8 + 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_alter_directory@Base 1.8 + svn_editor_alter_file@Base 1.8 + svn_editor_alter_symlink@Base 1.8 + 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_get_baton@Base 1.8 + svn_editor_move@Base 1.7 + svn_editor_rotate@Base 1.8 + 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_alter_directory@Base 1.8 + svn_editor_setcb_alter_file@Base 1.8 + svn_editor_setcb_alter_symlink@Base 1.8 + 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_rotate@Base 1.8 + svn_txdelta2@Base 1.8 + 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_contents@Base 1.8 + 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 + common_pool_lock@Base 1.8 + 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_config@Base 1.8 + 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_freeze@Base 1.8 + 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_mergeinfo2@Base 1.8 + 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_hotcopy2@Base 1.8 + 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_try_process_file_contents@Base 1.8 + 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_verify@Base 1.8 + svn_fs_verify_root@Base 1.8 + 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_dav_init@Base 1.8 + 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_switch3@Base 1.8 + svn_ra_do_switch@Base 1.4 + svn_ra_do_update2@Base 1.5 + svn_ra_do_update3@Base 1.8 + 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_inherited_props@Base 1.8 + 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_conn3@Base 1.8 + 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 + svn_ra_svn_zero_copy_limit@Base 1.8 +libsvn_repos-1.so.1 libsvn1 #MINVER# +| libsvn-private +* Build-Depends-Package: libsvn-dev + (regex)__ 0 1 + parse_hooks_env_option_baton@Base 1.8 + parse_hooks_env_section_baton@Base 1.8 + svn_repos_abort_report@Base 1.4 + svn_repos_authz_check_access@Base 1.4 + svn_repos_authz_parse@Base 1.8 + svn_repos_authz_read2@Base 1.8 + svn_repos_authz_read@Base 1.4 + svn_repos_begin_report2@Base 1.5 + svn_repos_begin_report3@Base 1.8 + 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_freeze@Base 1.8 + 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_inherited_props@Base 1.8 + 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_parser4@Base 1.8 + 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_hooks_setenv@Base 1.8 + svn_repos_hotcopy2@Base 1.8 + 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_fs4@Base 1.8 + 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_dumpstream3@Base 1.8 + 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_forget_credentials@Base 1.8 + svn_auth_get_gpg_agent_simple_provider@Base 1.8 + 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_is_empty_checksum@Base 1.8 + 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_copy_config@Base 1.8 + svn_config_create2@Base 1.8 + svn_config_create@Base 1.7 + svn_config_dup@Base 1.8 + 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_int64@Base 1.8 + 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_tristate@Base 1.8 + 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_parse@Base 1.8 + svn_config_read2@Base 1.7 + svn_config_read3@Base 1.8 + 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_set_int64@Base 1.8 + svn_config_walk_auth_data@Base 1.8 + 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_cstring_tokenize@Base 1.8 + 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_create@Base 1.8 + 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_symbolic_name@Base 1.8 + 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_readline@Base 1.8 + 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_files_contents_three_same_p@Base 1.8 + svn_io_filesizes_different_p@Base 1.4 + svn_io_filesizes_three_different_p@Base 1.8 + 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_lock_open_file@Base 1.8 + 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_cmd3@Base 1.8 + svn_io_start_cmd@Base 1.4 + svn_io_stat@Base 1.4 + svn_io_stat_dirent2@Base 1.8 + svn_io_stat_dirent@Base 1.7 + svn_io_temp_dir@Base 1.4 + svn_io_unlock_open_file@Base 1.8 + 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_diff2@Base 1.8 + 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_merge2@Base 1.8 + 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_help4@Base 1.8 + 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_illegal_path_escape@Base 1.8 + 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_repos_relative_url@Base 1.8 + 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_resolve_repos_relative_url@Base 1.8 + 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_allocator@Base 1.8 + 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_known_svn_dir_prop@Base 1.8 + svn_prop_is_known_svn_file_prop@Base 1.8 + svn_prop_is_known_svn_node_prop@Base 1.8 + svn_prop_is_known_svn_rev_prop@Base 1.8 + 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_kind2@Base 1.8 + 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_merge2@Base 1.8 + 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_buffered@Base 1.8 + 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_lazyopen_create@Base 1.8 + 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_puts@Base 1.8 + 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_empty@Base 1.8 + 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_empty@Base 1.8 + 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_insert@Base 1.8 + svn_stringbuf_isempty@Base 1.4 + svn_stringbuf_ncreate@Base 1.4 + svn_stringbuf_remove@Base 1.8 + svn_stringbuf_replace@Base 1.8 + 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_keywords3@Base 1.8 + 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_cstring_utf8_width@Base 1.8 + svn_utf_initialize2@Base 1.8 + 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_version_ext_build_date@Base 1.8 + svn_version_ext_build_host@Base 1.8 + svn_version_ext_build_time@Base 1.8 + svn_version_ext_copyright@Base 1.8 + svn_version_ext_linked_libs@Base 1.8 + svn_version_ext_loaded_libs@Base 1.8 + svn_version_ext_runtime_host@Base 1.8 + svn_version_ext_runtime_osname@Base 1.8 + svn_version_extended@Base 1.8 + 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 + op_delete_many_baton_t@Base 1.8 + 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_disk2@Base 1.8 + 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_root@Base 1.8 + 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_create2@Base 1.8 + 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_create@Base 1.8 + 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_merge5@Base 1.8 + 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_kind2@Base 1.8 + 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.8.8.orig/debian/man/svn-backup-dumps.1 +++ subversion-1.8.8/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.8.8.orig/debian/man/svn-bisect.1 +++ subversion-1.8.8/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.8.8.orig/debian/man/svn-fast-backup.1 +++ subversion-1.8.8/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.8.8.orig/debian/man/svn-hot-backup.1 +++ subversion-1.8.8/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.8.8.orig/debian/man/svn_load_dirs.1 +++ subversion-1.8.8/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.8.8.orig/debian/man/svnwrap.1 +++ subversion-1.8.8/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.8.8.orig/debian/patches/CVE-2014-3522.patch +++ subversion-1.8.8/debian/patches/CVE-2014-3522.patch @@ -0,0 +1,444 @@ +Description: fix incorrect ssl cert validation +Origin: upstream, http://svn.apache.org/viewvc?view=revision&revision=1615204 +Origin: upstream, http://svn.apache.org/viewvc?view=revision&revision=1615212 + +Index: subversion-1.8.8/subversion/include/private/svn_cert.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ subversion-1.8.8/subversion/include/private/svn_cert.h 2014-08-13 10:27:25.164425847 -0400 +@@ -0,0 +1,68 @@ ++/** ++ * @copyright ++ * ==================================================================== ++ * 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. ++ * ==================================================================== ++ * @endcopyright ++ * ++ * @file svn_cert.h ++ * @brief Implementation of certificate validation functions ++ */ ++ ++#ifndef SVN_CERT_H ++#define SVN_CERT_H ++ ++#include ++ ++#include "svn_types.h" ++#include "svn_string.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++ ++/* Return TRUE iff @a pattern matches @a hostname as defined ++ * by the matching rules of RFC 6125. In the context of RFC ++ * 6125 the pattern is the domain name portion of the presented ++ * identifier (which comes from the Common Name or a DNSName ++ * portion of the subjectAltName of an X.509 certificate) and ++ * the hostname is the source domain (i.e. the host portion ++ * of the URI the user entered). ++ * ++ * @note With respect to wildcards we only support matching ++ * wildcards in the left-most label and as the only character ++ * in the left-most label (i.e. we support RFC 6125 § 6.4.3 ++ * Rule 1 and 2 but not the optional Rule 3). This may change ++ * in the future. ++ * ++ * @note Subversion does not at current support internationalized ++ * domain names. Both values are presumed to be in NR-LDH label ++ * or A-label form (see RFC 5890 for the definition). ++ * ++ * @since New in 1.9. ++ */ ++svn_boolean_t ++svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname); ++ ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* SVN_CERT_H */ +Index: subversion-1.8.8/subversion/libsvn_ra_serf/util.c +=================================================================== +--- subversion-1.8.8.orig/subversion/libsvn_ra_serf/util.c 2014-08-13 10:25:49.120422261 -0400 ++++ subversion-1.8.8/subversion/libsvn_ra_serf/util.c 2014-08-13 10:26:53.804424676 -0400 +@@ -28,7 +28,6 @@ + #define APR_WANT_STRFUNC + #include + #include +-#include + + #include + #include +@@ -49,6 +48,7 @@ + #include "private/svn_fspath.h" + #include "private/svn_subr_private.h" + #include "private/svn_auth_private.h" ++#include "private/svn_cert.h" + + #include "ra_serf.h" + +@@ -274,7 +274,6 @@ + apr_hash_t *subject = NULL; + apr_hash_t *serf_cert = NULL; + void *creds; +- int found_matching_hostname = 0; + + svn_failures = (ssl_convert_serf_failures(failures) + | conn->server_cert_failures); +@@ -286,26 +285,37 @@ + ### This should really be handled by serf, which should pass an error + for this case, but that has backwards compatibility issues. */ + apr_array_header_t *san; ++ svn_boolean_t found_san_entry = FALSE; ++ svn_boolean_t found_matching_hostname = FALSE; ++ svn_string_t *actual_hostname = ++ svn_string_create(conn->session->session_url.hostname, scratch_pool); + + serf_cert = serf_ssl_cert_certificate(cert, scratch_pool); + + san = svn_hash_gets(serf_cert, "subjectAltName"); + /* Try to find matching server name via subjectAltName first... */ +- if (san) { ++ if (san) ++ { + int i; +- for (i = 0; i < san->nelts; i++) { ++ found_san_entry = san->nelts > 0; ++ for (i = 0; i < san->nelts; i++) ++ { + const char *s = APR_ARRAY_IDX(san, i, const char*); +- if (apr_fnmatch(s, conn->session->session_url.hostname, +- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS) +- { +- found_matching_hostname = 1; ++ svn_string_t *cert_hostname = svn_string_create(s, scratch_pool); ++ ++ if (svn_cert__match_dns_identity(cert_hostname, actual_hostname)) ++ { ++ found_matching_hostname = TRUE; + break; +- } +- } +- } ++ } ++ } ++ } + +- /* Match server certificate CN with the hostname of the server */ +- if (!found_matching_hostname) ++ /* Match server certificate CN with the hostname of the server iff ++ * we didn't find any subjectAltName fields and try to match them. ++ * Per RFC 2818 they are authoritative if present and CommonName ++ * should be ignored. */ ++ if (!found_matching_hostname && !found_san_entry) + { + const char *hostname = NULL; + +@@ -314,13 +324,20 @@ + if (subject) + hostname = svn_hash_gets(subject, "CN"); + +- if (!hostname +- || apr_fnmatch(hostname, conn->session->session_url.hostname, +- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) != APR_SUCCESS) +- { +- svn_failures |= SVN_AUTH_SSL_CNMISMATCH; +- } +- } ++ if (hostname) ++ { ++ svn_string_t *cert_hostname = svn_string_create(hostname, ++ scratch_pool); ++ ++ if (svn_cert__match_dns_identity(cert_hostname, actual_hostname)) ++ { ++ found_matching_hostname = TRUE; ++ } ++ } ++ } ++ ++ if (!found_matching_hostname) ++ svn_failures |= SVN_AUTH_SSL_CNMISMATCH; + } + + if (!svn_failures) +Index: subversion-1.8.8/subversion/libsvn_subr/dirent_uri.c +=================================================================== +--- subversion-1.8.8.orig/subversion/libsvn_subr/dirent_uri.c 2013-10-10 00:01:59.000000000 -0400 ++++ subversion-1.8.8/subversion/libsvn_subr/dirent_uri.c 2014-08-13 10:27:00.160424914 -0400 +@@ -38,6 +38,7 @@ + + #include "dirent_uri.h" + #include "private/svn_fspath.h" ++#include "private/svn_cert.h" + + /* The canonical empty path. Can this be changed? Well, change the empty + test below and the path library will work, not so sure about the fs/wc +@@ -2597,3 +2598,81 @@ + } + return uri; + } ++ ++ ++/* -------------- The cert API (see private/svn_cert.h) ------------- */ ++ ++svn_boolean_t ++svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname) ++{ ++ apr_size_t pattern_pos = 0, hostname_pos = 0; ++ ++ /* support leading wildcards that composed of the only character in the ++ * left-most label. */ ++ if (pattern->len >= 2 && ++ pattern->data[pattern_pos] == '*' && ++ pattern->data[pattern_pos + 1] == '.') ++ { ++ while (hostname_pos < hostname->len && ++ hostname->data[hostname_pos] != '.') ++ { ++ hostname_pos++; ++ } ++ /* Assume that the wildcard must match something. Rule 2 says ++ * that *.example.com should not match example.com. If the wildcard ++ * ends up not matching anything then it matches .example.com which ++ * seems to be essentially the same as just example.com */ ++ if (hostname_pos == 0) ++ return FALSE; ++ ++ pattern_pos++; ++ } ++ ++ while (pattern_pos < pattern->len && hostname_pos < hostname->len) ++ { ++ char pattern_c = pattern->data[pattern_pos]; ++ char hostname_c = hostname->data[hostname_pos]; ++ ++ /* fold case as described in RFC 4343. ++ * Note: We actually convert to lowercase, since our URI ++ * canonicalization code converts to lowercase and generally ++ * most certs are issued with lowercase DNS names, meaning ++ * this avoids the fold operation in most cases. The RFC ++ * suggests the opposite transformation, but doesn't require ++ * any specific implementation in any case. It is critical ++ * that this folding be locale independent so you can't use ++ * tolower(). */ ++ pattern_c = canonicalize_to_lower(pattern_c); ++ hostname_c = canonicalize_to_lower(hostname_c); ++ ++ if (pattern_c != hostname_c) ++ { ++ /* doesn't match */ ++ return FALSE; ++ } ++ else ++ { ++ /* characters match so skip both */ ++ pattern_pos++; ++ hostname_pos++; ++ } ++ } ++ ++ /* ignore a trailing period on the hostname since this has no effect on the ++ * security of the matching. See the following for the long explanation as ++ * to why: ++ * https://bugzilla.mozilla.org/show_bug.cgi?id=134402#c28 ++ */ ++ if (pattern_pos == pattern->len && ++ hostname_pos == hostname->len - 1 && ++ hostname->data[hostname_pos] == '.') ++ hostname_pos++; ++ ++ if (pattern_pos != pattern->len || hostname_pos != hostname->len) ++ { ++ /* end didn't match */ ++ return FALSE; ++ } ++ ++ return TRUE; ++} +Index: subversion-1.8.8/subversion/tests/libsvn_subr/dirent_uri-test.c +=================================================================== +--- subversion-1.8.8.orig/subversion/tests/libsvn_subr/dirent_uri-test.c 2013-10-10 00:01:59.000000000 -0400 ++++ subversion-1.8.8/subversion/tests/libsvn_subr/dirent_uri-test.c 2014-08-13 10:27:04.040425059 -0400 +@@ -37,6 +37,7 @@ + #include "svn_pools.h" + #include "svn_dirent_uri.h" + #include "private/svn_fspath.h" ++#include "private/svn_cert.h" + + #include "../svn_test.h" + +@@ -2714,6 +2715,145 @@ + return SVN_NO_ERROR; + } + ++struct cert_match_dns_test { ++ const char *pattern; ++ const char *hostname; ++ svn_boolean_t expected; ++}; ++ ++static svn_error_t * ++run_cert_match_dns_tests(struct cert_match_dns_test *tests, apr_pool_t *pool) ++{ ++ struct cert_match_dns_test *ct; ++ apr_pool_t *iterpool = svn_pool_create(pool); ++ ++ for (ct = tests; ct->pattern; ct++) ++ { ++ svn_boolean_t result; ++ svn_string_t *pattern, *hostname; ++ ++ svn_pool_clear(iterpool); ++ ++ pattern = svn_string_create(ct->pattern, iterpool); ++ hostname = svn_string_create(ct->hostname, iterpool); ++ ++ result = svn_cert__match_dns_identity(pattern, hostname); ++ if (result != ct->expected) ++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, ++ "Expected %s but got %s for pattern '%s' on " ++ "hostname '%s'", ++ ct->expected ? "match" : "no match", ++ result ? "match" : "no match", ++ pattern->data, hostname->data); ++ ++ } ++ ++ svn_pool_destroy(iterpool); ++ ++ return SVN_NO_ERROR; ++} ++ ++static struct cert_match_dns_test cert_match_dns_tests[] = { ++ { "foo.example.com", "foo.example.com", TRUE }, /* exact match */ ++ { "foo.example.com", "FOO.EXAMPLE.COM", TRUE }, /* case differences */ ++ { "FOO.EXAMPLE.COM", "foo.example.com", TRUE }, ++ { "*.example.com", "FoO.ExAmPlE.CoM", TRUE }, ++ { "*.ExAmPlE.CoM", "foo.example.com", TRUE }, ++ { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", TRUE }, ++ { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", TRUE }, ++ { "foo.example.com", "bar.example.com", FALSE }, /* difference at start */ ++ { "foo.example.com", "foo.example.net", FALSE }, /* difference at end */ ++ { "foo.example.com", "foo.example.commercial", FALSE }, /* hostname longer */ ++ { "foo.example.commercial", "foo.example.com", FALSE }, /* pattern longer */ ++ { "foo.example.comcom", "foo.example.com", FALSE }, /* repeated suffix */ ++ { "foo.example.com", "foo.example.comcom", FALSE }, ++ { "foo.example.com.com", "foo.example.com", FALSE }, ++ { "foo.example.com", "foo.example.com.com", FALSE }, ++ { "foofoo.example.com", "foo.example.com", FALSE }, /* repeated prefix */ ++ { "foo.example.com", "foofoo.example.com", FALSE }, ++ { "foo.foo.example.com", "foo.example.com", FALSE }, ++ { "foo.example.com", "foo.foo.example.com", FALSE }, ++ { "foo.*.example.com", "foo.bar.example.com", FALSE }, /* RFC 6125 s. 6.4.3 ++ Rule 1 */ ++ { "*.example.com", "foo.example.com", TRUE }, /* RFC 6125 s. 6.4.3 Rule 2 */ ++ { "*.example.com", "bar.foo.example.com", FALSE }, /* Rule 2 */ ++ { "*.example.com", "example.com", FALSE }, /* Rule 2 */ ++ { "*.example.com", ".example.com", FALSE }, /* RFC doesn't say what to do ++ here and a leading period on ++ a hostname doesn't make sense ++ so we'll just reject this. */ ++ { "*", "foo.example.com", FALSE }, /* wildcard must be left-most label, ++ implies that there must be more than ++ one label. */ ++ { "*", "example.com", FALSE }, ++ { "*", "com", FALSE }, ++ { "*.example.com", "foo.example.net", FALSE }, /* difference in literal text ++ with a wildcard. */ ++ { "*.com", "example.com", TRUE }, /* See Errata ID 3090 for RFC 6125, ++ probably shouldn't allow this but ++ we do for now. */ ++ { "*.", "example.com", FALSE }, /* test some dubious 2 character wildcard ++ patterns */ ++ { "*.", "example.", TRUE }, /* This one feels questionable */ ++ { "*.", "example", FALSE }, ++ { "*.", ".", FALSE }, ++ { "a", "a", TRUE }, /* check that single letter exact matches work */ ++ { "a", "b", FALSE }, /* and single letter not matches shouldn't */ ++ { "*.*.com", "foo.example.com", FALSE }, /* unsupported wildcards */ ++ { "*.*.com", "example.com", FALSE }, ++ { "**.example.com", "foo.example.com", FALSE }, ++ { "**.example.com", "example.com", FALSE }, ++ { "f*.example.com", "foo.example.com", FALSE }, ++ { "f*.example.com", "bar.example.com", FALSE }, ++ { "*o.example.com", "foo.example.com", FALSE }, ++ { "*o.example.com", "bar.example.com", FALSE }, ++ { "f*o.example.com", "foo.example.com", FALSE }, ++ { "f*o.example.com", "bar.example.com", FALSE }, ++ { "foo.e*.com", "foo.example.com", FALSE }, ++ { "foo.*e.com", "foo.example.com", FALSE }, ++ { "foo.e*e.com", "foo.example.com", FALSE }, ++ { "foo.example.com", "foo.example.com.", TRUE }, /* trailing dot */ ++ { "*.example.com", "foo.example.com.", TRUE }, ++ { "foo", "foo.", TRUE }, ++ { "foo.example.com.", "foo.example.com", FALSE }, ++ { "*.example.com.", "foo.example.com", FALSE }, ++ { "foo.", "foo", FALSE }, ++ { "foo.example.com", "foo.example.com..", FALSE }, ++ { "*.example.com", "foo.example.com..", FALSE }, ++ { "foo", "foo..", FALSE }, ++ { "foo.example.com..", "foo.example.com", FALSE }, ++ { "*.example.com..", "foo.example.com", FALSE }, ++ { "foo..", "foo", FALSE }, ++ { NULL } ++}; ++ ++static svn_error_t * ++test_cert_match_dns_identity(apr_pool_t *pool) ++{ ++ return run_cert_match_dns_tests(cert_match_dns_tests, pool); ++} ++ ++/* This test table implements results that should happen if we supported ++ * RFC 6125 s. 6.4.3 Rule 3. We don't so it's expected to fail for now. */ ++static struct cert_match_dns_test rule3_tests[] = { ++ { "baz*.example.net", "baz1.example.net", TRUE }, ++ { "*baz.example.net", "foobaz.example.net", TRUE }, ++ { "b*z.example.net", "buuz.example.net", TRUE }, ++ { "b*z.example.net", "bz.example.net", FALSE }, /* presume wildcard can't ++ match nothing */ ++ { "baz*.example.net", "baz.example.net", FALSE }, ++ { "*baz.example.net", "baz.example.net", FALSE }, ++ { "b*z.example.net", "buuzuuz.example.net", TRUE }, /* presume wildcard ++ should be greedy */ ++ { NULL } ++}; ++ ++static svn_error_t * ++test_rule3(apr_pool_t *pool) ++{ ++ return run_cert_match_dns_tests(rule3_tests, pool); ++} ++ + + /* The test table. */ + +@@ -2812,5 +2952,9 @@ + "test svn_fspath__dirname/basename/split"), + SVN_TEST_PASS2(test_fspath_get_longest_ancestor, + "test svn_fspath__get_longest_ancestor"), ++ SVN_TEST_PASS2(test_cert_match_dns_identity, ++ "test svn_cert__match_dns_identity"), ++ SVN_TEST_XFAIL2(test_rule3, ++ "test match with RFC 6125 s. 6.4.3 Rule 3"), + SVN_TEST_NULL + }; --- subversion-1.8.8.orig/debian/patches/CVE-2014-3528.patch +++ subversion-1.8.8/debian/patches/CVE-2014-3528.patch @@ -0,0 +1,27 @@ +Description: fix md5 collision authentication leak +Origin: upstream, http://svn.apache.org/viewvc?view=revision&revision=1605944 + +Index: subversion-1.8.8/subversion/libsvn_subr/config_auth.c +=================================================================== +--- subversion-1.8.8.orig/subversion/libsvn_subr/config_auth.c 2013-08-13 00:00:40.000000000 -0400 ++++ subversion-1.8.8/subversion/libsvn_subr/config_auth.c 2014-08-13 10:28:48.996428978 -0400 +@@ -94,6 +94,7 @@ + if (kind == svn_node_file) + { + svn_stream_t *stream; ++ svn_string_t *stored_realm; + + SVN_ERR_W(svn_stream_open_readonly(&stream, auth_path, pool, pool), + _("Unable to open auth file for reading")); +@@ -104,6 +105,11 @@ + apr_psprintf(pool, _("Error parsing '%s'"), + svn_dirent_local_style(auth_path, pool))); + ++ stored_realm = svn_hash_gets(*hash, SVN_CONFIG_REALMSTRING_KEY); ++ ++ if (!stored_realm || strcmp(stored_realm->data, realmstring) != 0) ++ *hash = NULL; /* Hash collision, or somebody tampering with storage */ ++ + SVN_ERR(svn_stream_close(stream)); + } + --- subversion-1.8.8.orig/debian/patches/CVE-2014-3580.patch +++ subversion-1.8.8/debian/patches/CVE-2014-3580.patch @@ -0,0 +1,101 @@ +Description: fix denial of service via non-existing REPORT request +Origin: upstream, http://subversion.apache.org/security/CVE-2014-3580-advisory.txt + +Index: subversion/mod_dav_svn/reports/deleted-rev.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/deleted-rev.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/deleted-rev.c (working copy) +@@ -56,6 +56,9 @@ dav_svn__get_deleted_rev_report(const dav_resource + dav_error *derr = NULL; + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0, +Index: subversion/mod_dav_svn/reports/file-revs.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/file-revs.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/file-revs.c (working copy) +@@ -254,6 +254,9 @@ dav_svn__file_revs_report(const dav_resource *reso + arb.repos = resource->info->repos; + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + /* ### This is done on other places, but the document element is + in this namespace, so is this necessary at all? */ +Index: subversion/mod_dav_svn/reports/get-location-segments.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/get-location-segments.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/get-location-segments.c (working copy) +@@ -123,6 +123,9 @@ dav_svn__get_location_segments_report(const dav_re + struct location_segment_baton location_segment_baton; + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + { +Index: subversion/mod_dav_svn/reports/get-locations.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/get-locations.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/get-locations.c (working copy) +@@ -106,6 +106,9 @@ dav_svn__get_locations_report(const dav_resource * + sizeof(svn_revnum_t)); + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + { +Index: subversion/mod_dav_svn/reports/inherited-props.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/inherited-props.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/inherited-props.c (working copy) +@@ -63,6 +63,9 @@ dav_svn__get_inherited_props_report(const dav_reso + apr_pool_t *iterpool; + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + { +Index: subversion/mod_dav_svn/reports/log.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/log.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/log.c (working copy) +@@ -307,6 +307,9 @@ dav_svn__log_report(const dav_resource *resource, + = apr_array_make(resource->pool, 1, sizeof(const char *)); + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + { +Index: subversion/mod_dav_svn/reports/mergeinfo.c +=================================================================== +--- a/subversion/mod_dav_svn/reports/mergeinfo.c (revision 1624477) ++++ b/subversion/mod_dav_svn/reports/mergeinfo.c (working copy) +@@ -67,6 +67,9 @@ dav_svn__get_mergeinfo_report(const dav_resource * + = apr_array_make(resource->pool, 0, sizeof(const char *)); + + /* Sanity check. */ ++ if (!resource->info->repos_path) ++ return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, ++ "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + { --- subversion-1.8.8.orig/debian/patches/CVE-2014-8108.patch +++ subversion-1.8.8/debian/patches/CVE-2014-8108.patch @@ -0,0 +1,55 @@ +Description: fix denial of service via non-existing virtual transaction name +Origin: upstream, http://subversion.apache.org/security/CVE-2014-8108-advisory.txt + +Index: subversion/mod_dav_svn/repos.c +=================================================================== +--- a/subversion/mod_dav_svn/repos.c (revision 1624477) ++++ b/subversion/mod_dav_svn/repos.c (working copy) +@@ -508,6 +508,9 @@ parse_vtxnstub_uri(dav_resource_combined *comb, + if (parse_txnstub_uri(comb, path, label, use_checked_in)) + return TRUE; + ++ if (!comb->priv.root.txn_name) ++ return TRUE; ++ + comb->priv.root.vtxn_name = comb->priv.root.txn_name; + comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, + comb->priv.root.vtxn_name); +@@ -576,6 +579,9 @@ parse_vtxnroot_uri(dav_resource_combined *comb, + if (parse_txnroot_uri(comb, path, label, use_checked_in)) + return TRUE; + ++ if (!comb->priv.root.txn_name) ++ return TRUE; ++ + comb->priv.root.vtxn_name = comb->priv.root.txn_name; + comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, + comb->priv.root.vtxn_name); +@@ -921,6 +927,10 @@ prep_working(dav_resource_combined *comb) + point. */ + if (txn_name == NULL) + { ++ if (!comb->priv.root.activity_id) ++ return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, ++ "The request did not specify an activity ID"); ++ + txn_name = dav_svn__get_txn(comb->priv.repos, + comb->priv.root.activity_id); + if (txn_name == NULL) +@@ -1031,9 +1041,14 @@ prep_working(dav_resource_combined *comb) + static dav_error * + prep_activity(dav_resource_combined *comb) + { +- const char *txn_name = dav_svn__get_txn(comb->priv.repos, +- comb->priv.root.activity_id); ++ const char *txn_name; + ++ if (!comb->priv.root.activity_id) ++ return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, ++ "The request did not specify an activity ID"); ++ ++ txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); ++ + comb->priv.root.txn_name = txn_name; + comb->res.exists = txn_name != NULL; + --- subversion-1.8.8.orig/debian/patches/CVE-2015-0202.patch +++ subversion-1.8.8/debian/patches/CVE-2015-0202.patch @@ -0,0 +1,477 @@ +Description: fix denial of service via large number of REPORT requests +Origin: upstream, https://subversion.apache.org/security/CVE-2015-0202-advisory.txt + +Index: subversion/libsvn_fs_fs/tree.c +=================================================================== +--- a/subversion/libsvn_fs_fs/tree.c (revision 1655679) ++++ b/subversion/libsvn_fs_fs/tree.c (working copy) +@@ -127,7 +127,6 @@ typedef struct fs_txn_root_data_t + static svn_error_t * get_dag(dag_node_t **dag_node_p, + svn_fs_root_t *root, + const char *path, +- svn_boolean_t needs_lock_cache, + apr_pool_t *pool); + + static svn_fs_root_t *make_revision_root(svn_fs_t *fs, svn_revnum_t rev, +@@ -178,34 +177,10 @@ typedef struct cache_entry_t + */ + enum { BUCKET_COUNT = 256 }; + +-/* Each pool that has received a DAG node, will hold at least on lock on +- our cache to ensure that the node remains valid despite being allocated +- in the cache's pool. This is the structure to represent the lock. +- */ +-typedef struct cache_lock_t +-{ +- /* pool holding the lock */ +- apr_pool_t *pool; +- +- /* cache being locked */ +- fs_fs_dag_cache_t *cache; +- +- /* next lock. NULL at EOL */ +- struct cache_lock_t *next; +- +- /* previous lock. NULL at list head. Only then this==cache->first_lock */ +- struct cache_lock_t *prev; +-} cache_lock_t; +- + /* The actual cache structure. All nodes will be allocated in POOL. + When the number of INSERTIONS (i.e. objects created form that pool) + exceeds a certain threshold, the pool will be cleared and the cache + with it. +- +- To ensure that nodes returned from this structure remain valid, the +- cache will get locked for the lifetime of the _receiving_ pools (i.e. +- those in which we would allocate the node if there was no cache.). +- The cache will only be cleared FIRST_LOCK is 0. + */ + struct fs_fs_dag_cache_t + { +@@ -221,47 +196,8 @@ struct fs_fs_dag_cache_t + /* Property lookups etc. have a very high locality (75% re-hit). + Thus, remember the last hit location for optimistic lookup. */ + apr_size_t last_hit; +- +- /* List of receiving pools that are still alive. */ +- cache_lock_t *first_lock; + }; + +-/* Cleanup function to be called when a receiving pool gets cleared. +- Unlocks the cache once. +- */ +-static apr_status_t +-unlock_cache(void *baton_void) +-{ +- cache_lock_t *lock = baton_void; +- +- /* remove lock from chain. Update the head */ +- if (lock->next) +- lock->next->prev = lock->prev; +- if (lock->prev) +- lock->prev->next = lock->next; +- else +- lock->cache->first_lock = lock->next; +- +- return APR_SUCCESS; +-} +- +-/* Cleanup function to be called when the cache itself gets destroyed. +- In that case, we must unregister all unlock requests. +- */ +-static apr_status_t +-unregister_locks(void *baton_void) +-{ +- fs_fs_dag_cache_t *cache = baton_void; +- cache_lock_t *lock; +- +- for (lock = cache->first_lock; lock; lock = lock->next) +- apr_pool_cleanup_kill(lock->pool, +- lock, +- unlock_cache); +- +- return APR_SUCCESS; +-} +- + fs_fs_dag_cache_t* + svn_fs_fs__create_dag_cache(apr_pool_t *pool) + { +@@ -268,59 +204,15 @@ svn_fs_fs__create_dag_cache(apr_pool_t *pool) + fs_fs_dag_cache_t *result = apr_pcalloc(pool, sizeof(*result)); + result->pool = svn_pool_create(pool); + +- apr_pool_cleanup_register(pool, +- result, +- unregister_locks, +- apr_pool_cleanup_null); +- + return result; + } + +-/* Prevent the entries in CACHE from being destroyed, for as long as the +- POOL lives. +- */ +-static void +-lock_cache(fs_fs_dag_cache_t* cache, apr_pool_t *pool) +-{ +- /* we only need to lock / unlock once per pool. Since we will often ask +- for multiple nodes with the same pool, we can reduce the overhead. +- However, if e.g. pools are being used in an alternating pattern, +- we may lock the cache more than once for the same pool (and register +- just as many cleanup actions). +- */ +- cache_lock_t *lock = cache->first_lock; +- +- /* try to find an existing lock for POOL. +- But limit the time spent on chasing pointers. */ +- int limiter = 8; +- while (lock && --limiter) +- if (lock->pool == pool) +- return; +- +- /* create a new lock and put it at the beginning of the lock chain */ +- lock = apr_palloc(pool, sizeof(*lock)); +- lock->cache = cache; +- lock->pool = pool; +- lock->next = cache->first_lock; +- lock->prev = NULL; +- +- if (cache->first_lock) +- cache->first_lock->prev = lock; +- cache->first_lock = lock; +- +- /* instruct POOL to remove the look upon cleanup */ +- apr_pool_cleanup_register(pool, +- lock, +- unlock_cache, +- apr_pool_cleanup_null); +-} +- + /* Clears the CACHE at regular intervals (destroying all cached nodes) + */ + static void + auto_clear_dag_cache(fs_fs_dag_cache_t* cache) + { +- if (cache->first_lock == NULL && cache->insertions > BUCKET_COUNT) ++ if (cache->insertions > BUCKET_COUNT) + { + svn_pool_clear(cache->pool); + +@@ -433,18 +325,12 @@ locate_cache(svn_cache__t **cache, + } + } + +-/* Return NODE for PATH from ROOT's node cache, or NULL if the node +- isn't cached; read it from the FS. *NODE remains valid until either +- POOL or the FS gets cleared or destroyed (whichever comes first). +- +- Since locking can be expensive and POOL may be long-living, for +- nodes that will not need to survive the next call to this function, +- set NEEDS_LOCK_CACHE to FALSE. */ ++/* Return NODE_P for PATH from ROOT's node cache, or NULL if the node ++ isn't cached; read it from the FS. *NODE_P is allocated in POOL. */ + static svn_error_t * + dag_node_cache_get(dag_node_t **node_p, + svn_fs_root_t *root, + const char *path, +- svn_boolean_t needs_lock_cache, + apr_pool_t *pool) + { + svn_boolean_t found; +@@ -466,25 +352,23 @@ dag_node_cache_get(dag_node_t **node_p, + if (bucket->node == NULL) + { + locate_cache(&cache, &key, root, path, pool); +- SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, +- ffd->dag_node_cache->pool)); ++ SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, pool)); + if (found && node) + { + /* Patch up the FS, since this might have come from an old FS + * object. */ + svn_fs_fs__dag_set_fs(node, root->fs); +- bucket->node = node; ++ ++ /* Retain the DAG node in L1 cache. */ ++ bucket->node = svn_fs_fs__dag_dup(node, ++ ffd->dag_node_cache->pool); + } + } + else + { +- node = bucket->node; ++ /* Copy the node from L1 cache into the passed-in POOL. */ ++ node = svn_fs_fs__dag_dup(bucket->node, pool); + } +- +- /* if we found a node, make sure it remains valid at least as long +- as it would when allocated in POOL. */ +- if (node && needs_lock_cache) +- lock_cache(ffd->dag_node_cache, pool); + } + else + { +@@ -822,7 +706,7 @@ get_copy_inheritance(copy_id_inherit_t *inherit_p, + SVN_ERR(svn_fs_fs__dag_get_copyroot(©root_rev, ©root_path, + child->node)); + SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, pool)); +- SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, FALSE, pool)); ++ SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); + copyroot_id = svn_fs_fs__dag_get_id(copyroot_node); + + if (svn_fs_fs__id_compare(copyroot_id, child_id) == -1) +@@ -938,7 +822,7 @@ open_path(parent_path_t **parent_path_p, + { + directory = svn_dirent_dirname(path, pool); + if (directory[1] != 0) /* root nodes are covered anyway */ +- SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool)); ++ SVN_ERR(dag_node_cache_get(&here, root, directory, pool)); + } + + /* did the shortcut work? */ +@@ -998,8 +882,8 @@ open_path(parent_path_t **parent_path_p, + element if we already know the lookup to fail for the + complete path. */ + if (next || !(flags & open_path_uncached)) +- SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, +- TRUE, pool)); ++ SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, pool)); ++ + if (cached_node) + child = cached_node; + else +@@ -1136,8 +1020,7 @@ make_path_mutable(svn_fs_root_t *root, + parent_path->node)); + SVN_ERR(svn_fs_fs__revision_root(©root_root, root->fs, + copyroot_rev, pool)); +- SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, +- FALSE, pool)); ++ SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); + + child_id = svn_fs_fs__dag_get_id(parent_path->node); + copyroot_id = svn_fs_fs__dag_get_id(copyroot_node); +@@ -1174,16 +1057,11 @@ make_path_mutable(svn_fs_root_t *root, + + /* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the + node we find, allocated in POOL. Return the error +- SVN_ERR_FS_NOT_FOUND if this node doesn't exist. +- +- Since locking can be expensive and POOL may be long-living, for +- nodes that will not need to survive the next call to this function, +- set NEEDS_LOCK_CACHE to FALSE. */ ++ SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */ + static svn_error_t * + get_dag(dag_node_t **dag_node_p, + svn_fs_root_t *root, + const char *path, +- svn_boolean_t needs_lock_cache, + apr_pool_t *pool) + { + parent_path_t *parent_path; +@@ -1192,7 +1070,7 @@ get_dag(dag_node_t **dag_node_p, + /* First we look for the DAG in our cache + (if the path may be canonical). */ + if (*path == '/') +- SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, pool)); ++ SVN_ERR(dag_node_cache_get(&node, root, path, pool)); + + if (! node) + { +@@ -1202,8 +1080,7 @@ get_dag(dag_node_t **dag_node_p, + path = svn_fs__canonicalize_abspath(path, pool); + + /* Try again with the corrected path. */ +- SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, +- pool)); ++ SVN_ERR(dag_node_cache_get(&node, root, path, pool)); + } + + if (! node) +@@ -1281,7 +1158,7 @@ svn_fs_fs__node_id(const svn_fs_id_t **id_p, + { + dag_node_t *node; + +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + *id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool); + } + return SVN_NO_ERROR; +@@ -1296,7 +1173,7 @@ svn_fs_fs__node_created_rev(svn_revnum_t *revision + { + dag_node_t *node; + +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + return svn_fs_fs__dag_get_revision(revision, node, pool); + } + +@@ -1311,7 +1188,7 @@ fs_node_created_path(const char **created_path, + { + dag_node_t *node; + +- SVN_ERR(get_dag(&node, root, path, TRUE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + *created_path = svn_fs_fs__dag_get_created_path(node); + + return SVN_NO_ERROR; +@@ -1375,7 +1252,7 @@ fs_node_prop(svn_string_t **value_p, + dag_node_t *node; + apr_hash_t *proplist; + +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool)); + *value_p = NULL; + if (proplist) +@@ -1398,7 +1275,7 @@ fs_node_proplist(apr_hash_t **table_p, + apr_hash_t *table; + dag_node_t *node; + +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool)); + *table_p = table ? table : apr_hash_make(pool); + +@@ -1515,8 +1392,8 @@ fs_props_changed(svn_boolean_t *changed_p, + (SVN_ERR_FS_GENERAL, NULL, + _("Cannot compare property value between two different filesystems")); + +- SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool)); +- SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool)); ++ SVN_ERR(get_dag(&node1, root1, path1, pool)); ++ SVN_ERR(get_dag(&node2, root2, path2, pool)); + return svn_fs_fs__dag_things_different(changed_p, NULL, + node1, node2); + } +@@ -1529,7 +1406,7 @@ fs_props_changed(svn_boolean_t *changed_p, + static svn_error_t * + get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool) + { +- return get_dag(node, root, "/", TRUE, pool); ++ return get_dag(node, root, "/", pool); + } + + +@@ -2193,7 +2070,7 @@ fs_dir_entries(apr_hash_t **table_p, + dag_node_t *node; + + /* Get the entries for this path in the caller's pool. */ +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + return svn_fs_fs__dag_dir_entries(table_p, node, pool); + } + +@@ -2365,7 +2242,7 @@ copy_helper(svn_fs_root_t *from_root, + _("Copy from mutable tree not currently supported")); + + /* Get the NODE for FROM_PATH in FROM_ROOT.*/ +- SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool)); ++ SVN_ERR(get_dag(&from_node, from_root, from_path, pool)); + + /* Build up the parent path from TO_PATH in TO_ROOT. If the last + component does not exist, it's not that big a deal. We'll just +@@ -2442,7 +2319,7 @@ copy_helper(svn_fs_root_t *from_root, + pool)); + + /* Make a record of this modification in the changes table. */ +- SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool)); ++ SVN_ERR(get_dag(&new_node, to_root, to_path, pool)); + SVN_ERR(add_change(to_root->fs, txn_id, to_path, + svn_fs_fs__dag_get_id(new_node), kind, FALSE, FALSE, + svn_fs_fs__dag_node_kind(from_node), +@@ -2553,7 +2430,7 @@ fs_copied_from(svn_revnum_t *rev_p, + { + /* There is no cached entry, look it up the old-fashioned + way. */ +- SVN_ERR(get_dag(&node, root, path, TRUE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(©from_rev, node)); + SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©from_path, node)); + } +@@ -2628,7 +2505,7 @@ fs_file_length(svn_filesize_t *length_p, + dag_node_t *file; + + /* First create a dag_node_t from the root/path pair. */ +- SVN_ERR(get_dag(&file, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&file, root, path, pool)); + + /* Now fetch its length */ + return svn_fs_fs__dag_file_length(length_p, file, pool); +@@ -2647,7 +2524,7 @@ fs_file_checksum(svn_checksum_t **checksum, + { + dag_node_t *file; + +- SVN_ERR(get_dag(&file, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&file, root, path, pool)); + return svn_fs_fs__dag_file_checksum(checksum, file, kind, pool); + } + +@@ -2666,7 +2543,7 @@ fs_file_contents(svn_stream_t **contents, + svn_stream_t *file_stream; + + /* First create a dag_node_t from the root/path pair. */ +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + + /* Then create a readable stream from the dag_node_t. */ + SVN_ERR(svn_fs_fs__dag_get_contents(&file_stream, node, pool)); +@@ -2689,7 +2566,7 @@ fs_try_process_file_contents(svn_boolean_t *succes + apr_pool_t *pool) + { + dag_node_t *node; +- SVN_ERR(get_dag(&node, root, path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, root, path, pool)); + + return svn_fs_fs__dag_try_process_file_contents(success, node, + processor, baton, pool); +@@ -3071,8 +2948,8 @@ fs_contents_changed(svn_boolean_t *changed_p, + (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2); + } + +- SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool)); +- SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool)); ++ SVN_ERR(get_dag(&node1, root1, path1, pool)); ++ SVN_ERR(get_dag(&node2, root2, path2, pool)); + return svn_fs_fs__dag_things_different(NULL, changed_p, + node1, node2); + } +@@ -3092,10 +2969,10 @@ fs_get_file_delta_stream(svn_txdelta_stream_t **st + dag_node_t *source_node, *target_node; + + if (source_root && source_path) +- SVN_ERR(get_dag(&source_node, source_root, source_path, TRUE, pool)); ++ SVN_ERR(get_dag(&source_node, source_root, source_path, pool)); + else + source_node = NULL; +- SVN_ERR(get_dag(&target_node, target_root, target_path, TRUE, pool)); ++ SVN_ERR(get_dag(&target_node, target_root, target_path, pool)); + + /* Create a delta stream that turns the source into the target. */ + return svn_fs_fs__dag_get_file_delta_stream(stream_p, source_node, +@@ -3588,7 +3465,7 @@ history_prev(void *baton, apr_pool_t *pool) + + SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, + pool)); +- SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, FALSE, pool)); ++ SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, pool)); + copy_dst = svn_fs_fs__dag_get_created_path(node); + + /* If our current path was the very destination of the copy, +@@ -3785,7 +3662,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *r + svn_pool_clear(iterpool); + + kid_path = svn_fspath__join(this_path, dirent->name, iterpool); +- SVN_ERR(get_dag(&kid_dag, root, kid_path, TRUE, iterpool)); ++ SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool)); + + SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag)); + SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag)); +@@ -4031,7 +3908,7 @@ add_descendant_mergeinfo(svn_mergeinfo_catalog_t r + dag_node_t *this_dag; + svn_boolean_t go_down; + +- SVN_ERR(get_dag(&this_dag, root, path, TRUE, scratch_pool)); ++ SVN_ERR(get_dag(&this_dag, root, path, scratch_pool)); + SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, + this_dag)); + if (go_down) --- subversion-1.8.8.orig/debian/patches/CVE-2015-0248.patch +++ subversion-1.8.8/debian/patches/CVE-2015-0248.patch @@ -0,0 +1,112 @@ +Description: fix denial of service via crafted parameter combinations +Origin: upstream, https://subversion.apache.org/security/CVE-2015-0248-advisory.txt + +Index: subversion-1.8.8/subversion/mod_dav_svn/reports/get-location-segments.c +=================================================================== +--- subversion-1.8.8.orig/subversion/mod_dav_svn/reports/get-location-segments.c 2015-08-19 14:29:37.188830523 -0400 ++++ subversion-1.8.8/subversion/mod_dav_svn/reports/get-location-segments.c 2015-08-19 14:29:37.180830431 -0400 +@@ -181,17 +181,36 @@ + "Not all parameters passed.", + SVN_DAV_ERROR_NAMESPACE, + SVN_DAV_ERROR_TAG); +- if (SVN_IS_VALID_REVNUM(start_rev) +- && SVN_IS_VALID_REVNUM(end_rev) +- && (end_rev > start_rev)) ++ ++ /* No START_REV or PEG_REVISION? We'll use HEAD. */ ++ if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision)) ++ { ++ svn_revnum_t youngest; ++ ++ serr = svn_fs_youngest_rev(&youngest, resource->info->repos->fs, ++ resource->pool); ++ if (serr != NULL) ++ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, ++ "Could not determine youngest revision", ++ resource->pool); ++ ++ if (!SVN_IS_VALID_REVNUM(start_rev)) ++ start_rev = youngest; ++ if (!SVN_IS_VALID_REVNUM(peg_revision)) ++ peg_revision = youngest; ++ } ++ ++ /* No END_REV? We'll use 0. */ ++ if (!SVN_IS_VALID_REVNUM(end_rev)) ++ end_rev = 0; ++ ++ if (end_rev > start_rev) + return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0, + "End revision must not be younger than " + "start revision", + SVN_DAV_ERROR_NAMESPACE, + SVN_DAV_ERROR_TAG); +- if (SVN_IS_VALID_REVNUM(peg_revision) +- && SVN_IS_VALID_REVNUM(start_rev) +- && (start_rev > peg_revision)) ++ if (start_rev > peg_revision) + return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0, + "Start revision must not be younger than " + "peg revision", +Index: subversion-1.8.8/subversion/svnserve/serve.c +=================================================================== +--- subversion-1.8.8.orig/subversion/svnserve/serve.c 2015-08-19 14:29:37.188830523 -0400 ++++ subversion-1.8.8/subversion/svnserve/serve.c 2015-08-19 14:29:37.184830477 -0400 +@@ -2450,9 +2450,30 @@ + + abs_path = svn_fspath__join(b->fs_path->data, relative_path, pool); + +- if (SVN_IS_VALID_REVNUM(start_rev) +- && SVN_IS_VALID_REVNUM(end_rev) +- && (end_rev > start_rev)) ++ SVN_ERR(trivial_auth_request(conn, pool, b)); ++ SVN_ERR(log_command(baton, conn, pool, "%s", ++ svn_log__get_location_segments(abs_path, peg_revision, ++ start_rev, end_rev, ++ pool))); ++ ++ /* No START_REV or PEG_REVISION? We'll use HEAD. */ ++ if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision)) ++ { ++ svn_revnum_t youngest; ++ ++ SVN_CMD_ERR(svn_fs_youngest_rev(&youngest, b->fs, pool)); ++ ++ if (!SVN_IS_VALID_REVNUM(start_rev)) ++ start_rev = youngest; ++ if (!SVN_IS_VALID_REVNUM(peg_revision)) ++ peg_revision = youngest; ++ } ++ ++ /* No END_REV? We'll use 0. */ ++ if (!SVN_IS_VALID_REVNUM(end_rev)) ++ end_rev = 0; ++ ++ if (end_rev > start_rev) + { + err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + "Get-location-segments end revision must not be " +@@ -2460,9 +2481,7 @@ + return log_fail_and_flush(err, b, conn, pool); + } + +- if (SVN_IS_VALID_REVNUM(peg_revision) +- && SVN_IS_VALID_REVNUM(start_rev) +- && (start_rev > peg_revision)) ++ if (start_rev > peg_revision) + { + err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + "Get-location-segments start revision must not " +@@ -2470,12 +2489,6 @@ + return log_fail_and_flush(err, b, conn, pool); + } + +- SVN_ERR(trivial_auth_request(conn, pool, b)); +- SVN_ERR(log_command(baton, conn, pool, "%s", +- svn_log__get_location_segments(abs_path, peg_revision, +- start_rev, end_rev, +- pool))); +- + /* All the parameters are fine - let's perform the query against the + * repository. */ + --- subversion-1.8.8.orig/debian/patches/CVE-2015-0251.patch +++ subversion-1.8.8/debian/patches/CVE-2015-0251.patch @@ -0,0 +1,65 @@ +Description: fix svn:author property spoofing issue +Origin: upstream, https://subversion.apache.org/security/CVE-2015-0251-advisory.txt + +Index: subversion/mod_dav_svn/deadprops.c +=================================================================== +--- a/subversion/mod_dav_svn/deadprops.c (revision 1660122) ++++ b/subversion/mod_dav_svn/deadprops.c (working copy) +@@ -163,6 +163,23 @@ get_value(dav_db *db, const dav_prop_name *name, s + } + + ++static svn_error_t * ++change_txn_prop(svn_fs_txn_t *txn, ++ const char *propname, ++ const svn_string_t *value, ++ apr_pool_t *scratch_pool) ++{ ++ if (strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0) ++ return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, ++ "Attempted to modify 'svn:author' property " ++ "on a transaction"); ++ ++ SVN_ERR(svn_repos_fs_change_txn_prop(txn, propname, value, scratch_pool)); ++ ++ return SVN_NO_ERROR; ++} ++ ++ + static dav_error * + save_value(dav_db *db, const dav_prop_name *name, + const svn_string_t *const *old_value_p, +@@ -213,9 +230,8 @@ save_value(dav_db *db, const dav_prop_name *name, + { + if (resource->working) + { +- serr = svn_repos_fs_change_txn_prop(resource->info->root.txn, +- propname, value, +- subpool); ++ serr = change_txn_prop(resource->info->root.txn, propname, ++ value, subpool); + } + else + { +@@ -254,8 +270,8 @@ save_value(dav_db *db, const dav_prop_name *name, + } + else if (resource->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION) + { +- serr = svn_repos_fs_change_txn_prop(resource->info->root.txn, +- propname, value, subpool); ++ serr = change_txn_prop(resource->info->root.txn, propname, ++ value, subpool); + } + else + { +@@ -560,8 +576,8 @@ db_remove(dav_db *db, const dav_prop_name *name) + /* Working Baseline or Working (Version) Resource */ + if (db->resource->baselined) + if (db->resource->working) +- serr = svn_repos_fs_change_txn_prop(db->resource->info->root.txn, +- propname, NULL, subpool); ++ serr = change_txn_prop(db->resource->info->root.txn, propname, ++ NULL, subpool); + else + /* ### VIOLATING deltaV: you can't proppatch a baseline, it's + not a working resource! But this is how we currently --- subversion-1.8.8.orig/debian/patches/CVE-2015-3184.patch +++ subversion-1.8.8/debian/patches/CVE-2015-3184.patch @@ -0,0 +1,2077 @@ +Description: fix incorrect anonymous access restriction +Origin: backport, http://subversion.apache.org/security/CVE-2015-3184-advisory.txt + +Index: subversion-1.8.8/Makefile.in +=================================================================== +--- subversion-1.8.8.orig/Makefile.in 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/Makefile.in 2015-08-19 14:29:57.297060812 -0400 +@@ -358,6 +358,7 @@ + fi; + + APXS = @APXS@ ++HTTPD_VERSION = @HTTPD_VERSION@ + + PYTHON = @PYTHON@ + PERL = @PERL@ +@@ -510,6 +511,9 @@ + if test "$(HTTP_LIBRARY)" != ""; then \ + flags="--http-library $(HTTP_LIBRARY) $$flags"; \ + fi; \ ++ if test "$(HTTPD_VERSION)" != ""; then \ ++ flags="--httpd-version $(HTTPD_VERSION) $$flags"; \ ++ fi; \ + if test "$(SERVER_MINOR_VERSION)" != ""; then \ + flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \ + fi; \ +Index: subversion-1.8.8/build/ac-macros/apache.m4 +=================================================================== +--- subversion-1.8.8.orig/build/ac-macros/apache.m4 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/build/ac-macros/apache.m4 2015-08-19 14:29:57.301060858 -0400 +@@ -139,6 +139,20 @@ + BUILD_APACHE_RULE=apache-mod + INSTALL_APACHE_RULE=install-mods-shared + INSTALL_APACHE_MODS=true ++ HTTPD="`$APXS -q sbindir`/`$APXS -q PROGNAME`" ++ if ! test -e $HTTPD ; then ++ HTTPD="`$APXS -q bindir`/`$APXS -q PROGNAME`" ++ fi ++ HTTPD_VERSION=["`$HTTPD -v | $SED -e 's@^.*/\([0-9.]*\)\(.*$\)@\1@ ; 1q'`"] ++ AC_ARG_ENABLE(broken-httpd-auth, ++ AS_HELP_STRING([--enable-broken-httpd-auth], ++ [Allow building against httpd 2.4 with broken auth]), ++ [broken_httpd_auth=$enableval],[broken_httpd_auth=no]) ++ if test "$enable_broken_httpd_auth" = "yes"; then ++ AC_MSG_NOTICE([Building with broken httpd auth]) ++ AC_DEFINE(SVN_ALLOW_BROKEN_HTTPD_AUTH, 1, ++ [Defined to allow building against httpd 2.4 with broken auth]) ++ fi + + case $host in + *-*-cygwin*) +@@ -157,6 +171,7 @@ + AC_SUBST(APACHE_INCLUDES) + AC_SUBST(APACHE_LIBEXECDIR) + AC_SUBST(INSTALL_APACHE_MODS) ++AC_SUBST(HTTPD_VERSION) + + # there aren't any flags that interest us ... + #if test -n "$APXS" && test "$APXS" != "no"; then +Index: subversion-1.8.8/build/run_tests.py +=================================================================== +--- subversion-1.8.8.orig/build/run_tests.py 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/build/run_tests.py 2015-08-19 14:29:57.301060858 -0400 +@@ -29,6 +29,7 @@ + [--fs-type=] [--fsfs-packing] [--fsfs-sharding=] + [--list] [--milestone-filter=] [--mode-filter=] + [--server-minor-version=] [--http-proxy=:] ++ [--httpd-version=] + [--config-file=] [--ssl-cert=] + + +@@ -125,7 +126,7 @@ + fsfs_sharding=None, fsfs_packing=None, + list_tests=None, svn_bin=None, mode_filter=None, + milestone_filter=None, set_log_level=None, ssl_cert=None, +- http_proxy=None): ++ http_proxy=None, httpd_version=None): + '''Construct a TestHarness instance. + + ABS_SRCDIR and ABS_BUILDDIR are the source and build directories. +@@ -178,6 +179,7 @@ + self.log = None + self.ssl_cert = ssl_cert + self.http_proxy = http_proxy ++ self.httpd_version = httpd_version + if not sys.stdout.isatty() or sys.platform == 'win32': + TextColors.disable() + +@@ -481,6 +483,8 @@ + svntest.main.options.ssl_cert = self.ssl_cert + if self.http_proxy is not None: + svntest.main.options.http_proxy = self.http_proxy ++ if self.httpd_version is not None: ++ svntest.main.options.httpd_version = self.httpd_version + + svntest.main.options.srcdir = self.srcdir + +@@ -645,7 +649,7 @@ + 'enable-sasl', 'parallel', 'config-file=', + 'log-to-stdout', 'list', 'milestone-filter=', + 'mode-filter=', 'set-log-level=', 'ssl-cert=', +- 'http-proxy=']) ++ 'http-proxy=', 'httpd-version=']) + except getopt.GetoptError: + args = [] + +@@ -656,9 +660,9 @@ + base_url, fs_type, verbose, cleanup, enable_sasl, http_library, \ + server_minor_version, fsfs_sharding, fsfs_packing, parallel, \ + config_file, log_to_stdout, list_tests, mode_filter, milestone_filter, \ +- set_log_level, ssl_cert, http_proxy = \ ++ set_log_level, ssl_cert, http_proxy, httpd_version = \ + None, None, None, None, None, None, None, None, None, None, None, \ +- None, None, None, None, None, None, None ++ None, None, None, None, None, None, None, None + for opt, val in opts: + if opt in ['-u', '--url']: + base_url = val +@@ -696,6 +700,8 @@ + ssl_cert = val + elif opt in ['--http-proxy']: + http_proxy = val ++ elif opt in ['--httpd-version']: ++ httpd_version = val + else: + raise getopt.GetoptError + +@@ -712,7 +718,7 @@ + fsfs_sharding, fsfs_packing, list_tests, + mode_filter=mode_filter, milestone_filter=milestone_filter, + set_log_level=set_log_level, ssl_cert=ssl_cert, +- http_proxy=http_proxy) ++ http_proxy=http_proxy, httpd_version=httpd_version) + + failed = th.run(args[2:]) + if failed: +Index: subversion-1.8.8/subversion/mod_authz_svn/mod_authz_svn.c +=================================================================== +--- subversion-1.8.8.orig/subversion/mod_authz_svn/mod_authz_svn.c 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/subversion/mod_authz_svn/mod_authz_svn.c 2015-08-19 14:29:57.301060858 -0400 +@@ -48,6 +48,23 @@ + #include "svn_dirent_uri.h" + #include "private/svn_fspath.h" + ++/* The apache headers define these and they conflict with our definitions. */ ++#ifdef PACKAGE_BUGREPORT ++#undef PACKAGE_BUGREPORT ++#endif ++#ifdef PACKAGE_NAME ++#undef PACKAGE_NAME ++#endif ++#ifdef PACKAGE_STRING ++#undef PACKAGE_STRING ++#endif ++#ifdef PACKAGE_TARNAME ++#undef PACKAGE_TARNAME ++#endif ++#ifdef PACKAGE_VERSION ++#undef PACKAGE_VERSION ++#endif ++#include "svn_private_config.h" + + #ifdef APLOG_USE_MODULE + APLOG_USE_MODULE(authz_svn); +@@ -74,6 +91,31 @@ + #define dav_svn_split_uri split_uri + #endif + ++#if AP_MODULE_MAGIC_AT_LEAST(20060110,0) /* version where ++ ap_some_auth_required breaks */ ++/* Patched without bumping version in Ubuntu, so adjusted to 27 */ ++# if AP_MODULE_MAGIC_AT_LEAST(20120211,27) /* first version with ++ force_authn hook and ++ ap_some_authn_required() which ++ allows us to work without ++ ap_some_auth_required() */ ++# define USE_FORCE_AUTHN 1 ++# define IN_SOME_AUTHN_NOTE "authz_svn-in-some-authn" ++# define FORCE_AUTHN_NOTE "authz_svn-force-authn" ++# else ++ /* ap_some_auth_required() is busted and no viable alternative exists */ ++# ifndef SVN_ALLOW_BROKEN_HTTPD_AUTH ++# error This version of httpd has a security hole with mod_authz_svn ++# else ++ /* user wants to build anyway */ ++# define USE_FORCE_AUTHN 0 ++# endif ++# endif ++#else ++ /* old enough that ap_some_auth_required() still works */ ++# define USE_FORCE_AUTHN 0 ++#endif ++ + /* + * Configuration + */ +@@ -826,7 +868,49 @@ + &authz_svn_module); + const char *repos_path = NULL; + const char *dest_repos_path = NULL; +- int status; ++ int status, authn_required; ++ ++#if USE_FORCE_AUTHN ++ /* Use the force_authn() hook available in 2.4.x to work securely ++ * given that ap_some_auth_required() is no longer functional for our ++ * purposes in 2.4.x. ++ */ ++ int authn_configured; ++ ++ /* We are not configured to run */ ++ if (!conf->anonymous || apr_table_get(r->notes, IN_SOME_AUTHN_NOTE) ++ || (! (conf->access_file || conf->repo_relative_access_file))) ++ return DECLINED; ++ ++ /* Authentication is configured */ ++ authn_configured = ap_auth_type(r) != NULL; ++ if (authn_configured) ++ { ++ /* If the user is trying to authenticate, let him. It doesn't ++ * make much sense to grant anonymous access but deny authenticated ++ * users access, even though you can do that with '$anon' in the ++ * access file. ++ */ ++ if (apr_table_get(r->headers_in, ++ (PROXYREQ_PROXY == r->proxyreq) ++ ? "Proxy-Authorization" : "Authorization")) ++ { ++ /* Set the note to force authn regardless of what access_checker_ex ++ hook requires */ ++ apr_table_setn(r->notes, FORCE_AUTHN_NOTE, (const char*)1); ++ ++ /* provide the proper return so the access_checker hook doesn't ++ * prevent the code from continuing on to the other auth hooks */ ++ if (ap_satisfies(r) != SATISFY_ANY) ++ return OK; ++ else ++ return HTTP_FORBIDDEN; ++ } ++ } ++ ++#else ++ /* Support for older versions of httpd that have a working ++ * ap_some_auth_required() */ + + /* We are not configured to run */ + if (!conf->anonymous +@@ -841,9 +925,10 @@ + if (ap_satisfies(r) != SATISFY_ANY) + return DECLINED; + +- /* If the user is trying to authenticate, let him. If anonymous +- * access is allowed, so is authenticated access, by definition +- * of the meaning of '*' in the access file. ++ /* If the user is trying to authenticate, let him. It doesn't ++ * make much sense to grant anonymous access but deny authenticated ++ * users access, even though you can do that with '$anon' in the ++ * access file. + */ + if (apr_table_get(r->headers_in, + (PROXYREQ_PROXY == r->proxyreq) +@@ -855,6 +940,7 @@ + return HTTP_FORBIDDEN; + } + } ++#endif + + /* If anon access is allowed, return OK */ + status = req_check_access(r, conf, &repos_path, &dest_repos_path); +@@ -863,7 +949,26 @@ + if (!conf->authoritative) + return DECLINED; + ++#if USE_FORCE_AUTHN ++ if (authn_configured) { ++ /* We have to check to see if authn is required because if so we must ++ * return UNAUTHORIZED (401) rather than FORBIDDEN (403) since returning ++ * the 403 leaks information about what paths may exist to ++ * unauthenticated users. We must set a note here in order ++ * to use ap_some_authn_rquired() without triggering an infinite ++ * loop since the call will trigger this function to be called again. */ ++ apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, (const char*)1); ++ authn_required = ap_some_authn_required(r); ++ apr_table_unset(r->notes, IN_SOME_AUTHN_NOTE); ++ if (authn_required) ++ { ++ ap_note_auth_failure(r); ++ return HTTP_UNAUTHORIZED; ++ } ++ } ++#else + if (!ap_some_auth_required(r)) ++#endif + log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path); + + return HTTP_FORBIDDEN; +@@ -954,6 +1059,17 @@ + } + #endif + ++#if USE_FORCE_AUTHN ++static int ++force_authn(request_rec *r) ++{ ++ if (apr_table_get(r->notes, FORCE_AUTHN_NOTE)) ++ return OK; ++ ++ return DECLINED; ++} ++#endif ++ + /* + * Module flesh + */ +@@ -970,6 +1086,9 @@ + * give SSLOptions +FakeBasicAuth a chance to work. */ + ap_hook_check_user_id(check_user_id, mod_ssl, NULL, APR_HOOK_FIRST); + ap_hook_auth_checker(auth_checker, NULL, NULL, APR_HOOK_FIRST); ++#if USE_FORCE_AUTHN ++ ap_hook_force_authn(force_authn, NULL, NULL, APR_HOOK_FIRST); ++#endif + ap_register_provider(p, + AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP, + AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME, +Index: subversion-1.8.8/subversion/tests/cmdline/README +=================================================================== +--- subversion-1.8.8.orig/subversion/tests/cmdline/README 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/subversion/tests/cmdline/README 2015-08-19 14:29:57.301060858 -0400 +@@ -83,6 +83,133 @@ + Require valid-user + + ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ # This may seem unnecessary but granting access to everyone here is necessary ++ # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is ++ # new to 2.3.x+ which we can detect with the mod_authz_core.c module ++ # signature. Use the "Allow from all" syntax with older versions for symmetry. ++ ++ Require all granted ++ ++ ++ Allow from all ++ ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ Require valid-user ++ Satisfy Any ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ Require valid-user ++ AuthzSVNNoAuthWhenAnonymousAllowed On ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ Require valid-user ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ Require valid-user ++ AuthzSVNAnonymous Off ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ Require valid-user ++ AuthzForceUsernameCase Lower ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ Require valid-user ++ AuthzForceUsernameCase Lower ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ AuthGroupFile /usr/local/apache2/conf/groups ++ Require group random ++ AuthzSVNAuthoritative Off ++ ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ AuthzSendForbiddenOnFailure On ++ Satisfy All ++ ++ Require valid-user ++ Require expr req('ALLOW') == '1' ++ ++ ++ ++ DAV svn ++ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp ++ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile /usr/local/apache2/conf/users ++ AuthzSendForbiddenOnFailure On ++ Satisfy All ++ ++ Require valid-user ++ Require expr req('ALLOW') == '1' ++ ++ ++ ++ ++ + RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1 + RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1 + +@@ -101,6 +228,15 @@ + ---------------------------- + jrandom:xCGl35kV9oWCY + jconstant:xCGl35kV9oWCY ++JRANDOM:xCGl35kV9oWCY ++JCONSTANT:xCGl35kV9oWCY ++---------------------------- ++ ++and these lines into the ++/usr/local/apache/conf/groups file: ++---------------------------- ++random: jrandom ++constant: jconstant + ---------------------------- + + Now, (re)start Apache and run the tests over mod_dav_svn. +@@ -138,6 +274,8 @@ + ---------------------------- + jrandom:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0 + jconstant:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0 ++ JRANDOM:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0 ++ JCONSTANT:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0 + ---------------------------- + + +Index: subversion-1.8.8/subversion/tests/cmdline/davautocheck.sh +=================================================================== +--- subversion-1.8.8.orig/subversion/tests/cmdline/davautocheck.sh 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/subversion/tests/cmdline/davautocheck.sh 2015-08-19 14:29:57.301060858 -0400 +@@ -289,8 +289,6 @@ + || fail "Authn_Core module not found." + LOAD_MOD_AUTHZ_CORE="$(get_loadmodule_config mod_authz_core)" \ + || fail "Authz_Core module not found." +-LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \ +- || fail "Authz_Host module not found." + LOAD_MOD_UNIXD=$(get_loadmodule_config mod_unixd) \ + || fail "UnixD module not found" + } +@@ -298,6 +296,10 @@ + || fail "Authn_File module not found." + LOAD_MOD_AUTHZ_USER="$(get_loadmodule_config mod_authz_user)" \ + || fail "Authz_User module not found." ++LOAD_MOD_AUTHZ_GROUPFILE="$(get_loadmodule_config mod_authz_groupfile)" \ ++ || fail "Authz_GroupFile module not found." ++LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \ ++ || fail "Authz_Host module not found." + } + if [ ${APACHE_MPM:+set} ]; then + LOAD_MOD_MPM=$(get_loadmodule_config mod_mpm_$APACHE_MPM) \ +@@ -328,6 +330,7 @@ + HTTPD_MIME_TYPES="$HTTPD_ROOT/mime.types" + BASE_URL="http://localhost:$HTTPD_PORT" + HTTPD_USERS="$HTTPD_ROOT/users" ++HTTPD_GROUPS="$HTTPD_ROOT/groups" + + mkdir "$HTTPD_ROOT" \ + || fail "couldn't create temporary directory '$HTTPD_ROOT'" +@@ -388,6 +391,14 @@ + say "Adding users for lock authentication" + $HTPASSWD -bc $HTTPD_USERS jrandom rayjandom + $HTPASSWD -b $HTTPD_USERS jconstant rayjandom ++$HTPASSWD -b $HTTPD_USERS JRANDOM rayjandom ++$HTPASSWD -b $HTTPD_USERS JCONSTANT rayjandom ++ ++say "Adding groups for mod_authz_svn tests" ++cat > "$HTTPD_GROUPS" <<__EOF__ ++random: jrandom ++constant: jconstant ++__EOF__ + + touch $HTTPD_MIME_TYPES + +@@ -405,7 +416,9 @@ + $LOAD_MOD_AUTHN_FILE + $LOAD_MOD_AUTHZ_CORE + $LOAD_MOD_AUTHZ_USER ++$LOAD_MOD_AUTHZ_GROUPFILE + $LOAD_MOD_AUTHZ_HOST ++$LOAD_MOD_ACCESS_COMPAT + LoadModule authz_svn_module "$MOD_AUTHZ_SVN" + + __EOF__ +@@ -489,6 +502,161 @@ + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} + ${SVN_PATH_AUTHZ_LINE} + ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ # This may seem unnecessary but granting access to everyone here is necessary ++ # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is ++ # new to 2.3.x+ which we can detect with the mod_authz_core.c module ++ # signature. Use the "Allow from all" syntax with older versions for symmetry. ++ ++ Require all granted ++ ++ ++ Allow from all ++ ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ Require valid-user ++ Satisfy Any ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ Require valid-user ++ AuthzSVNNoAuthWhenAnonymousAllowed On ++ SVNPathAuthz On ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ Require valid-user ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ Require valid-user ++ AuthzSVNAnonymous Off ++ SVNPathAuthz On ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ Require valid-user ++ AuthzForceUsernameCase Lower ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ Require valid-user ++ AuthzForceUsernameCase Lower ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ AuthGroupFile $HTTPD_GROUPS ++ Require group random ++ AuthzSVNAuthoritative Off ++ SVNPathAuthz On ++ ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ AuthzSendForbiddenOnFailure On ++ Satisfy All ++ ++ Require valid-user ++ Require expr req('ALLOW') == '1' ++ ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ ++ DAV svn ++ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" ++ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" ++ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} ++ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} ++ SVNListParentPath On ++ AuthType Basic ++ AuthName "Subversion Repository" ++ AuthUserFile $HTTPD_USERS ++ AuthzSendForbiddenOnFailure On ++ Satisfy All ++ ++ Require valid-user ++ Require expr req('ALLOW') == '1' ++ ++ ${SVN_PATH_AUTHZ_LINE} ++ ++ + RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)\$ /svn-test-work/repositories/\$1 + RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)\$ /svn-test-work/repositories/\$1 + __EOF__ +Index: subversion-1.8.8/subversion/tests/cmdline/mod_authz_svn_tests.py +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ subversion-1.8.8/subversion/tests/cmdline/mod_authz_svn_tests.py 2015-08-19 14:29:57.305060904 -0400 +@@ -0,0 +1,1073 @@ ++#!/usr/bin/env python ++# ++# mod_authz_svn_tests.py: testing mod_authz_svn ++# ++# Subversion is a tool for revision control. ++# See http://subversion.apache.org for more information. ++# ++# ==================================================================== ++# 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. ++###################################################################### ++ ++# General modules ++import os, re, logging ++ ++logger = logging.getLogger() ++ ++# Our testing module ++import svntest ++ ++# (abbreviation) ++Skip = svntest.testcase.Skip_deco ++SkipUnless = svntest.testcase.SkipUnless_deco ++XFail = svntest.testcase.XFail_deco ++Issues = svntest.testcase.Issues_deco ++Issue = svntest.testcase.Issue_deco ++Wimp = svntest.testcase.Wimp_deco ++ ++ls_of_D_no_H = '''repos - Revision 1: /A/D ++ ++

repos - Revision 1: /A/D

++ ++''' ++ ++ls_of_D_H = '''repos - Revision 1: /A/D ++ ++

repos - Revision 1: /A/D

++ ++''' ++ ++ls_of_H = '''repos - Revision 1: /A/D/H ++ ++

repos - Revision 1: /A/D/H

++ ++''' ++ ++user1 = svntest.main.wc_author ++user1_upper = user1.upper() ++user1_pass = svntest.main.wc_passwd ++user1_badpass = 'XXX' ++assert user1_pass != user1_badpass, "Passwords can't match" ++user2 = svntest.main.wc_author2 ++user2_upper = user2.upper() ++user2_pass = svntest.main.wc_passwd ++user2_badpass = 'XXX' ++assert user2_pass != user2_badpass, "Passwords can't match" ++ ++def write_authz_file(sbox): ++ svntest.main.write_authz_file(sbox, { ++ '/': '$anonymous = r\n' + ++ 'jrandom = rw\n' + ++ 'jconstant = rw', ++ '/A/D/H': '$anonymous =\n' + ++ '$authenticated =\n' + ++ 'jrandom = rw' ++ }) ++ ++def write_authz_file_groups(sbox): ++ authz_name = sbox.authz_name() ++ svntest.main.write_authz_file(sbox,{ ++ '/': '* =', ++ }) ++ ++def verify_get(test_area_url, path, user, pw, ++ expected_status, expected_body, headers): ++ import httplib ++ from urlparse import urlparse ++ import base64 ++ ++ req_url = test_area_url + path ++ ++ loc = urlparse(req_url) ++ ++ if loc.scheme == 'http': ++ h = httplib.HTTPConnection(loc.hostname, loc.port) ++ else: ++ h = httplib.HTTPSConnection(loc.hostname, loc.port) ++ ++ if headers is None: ++ headers = {} ++ ++ if user and pw: ++ auth_info = user + ':' + pw ++ headers['Authorization'] = 'Basic ' + base64.b64encode(auth_info) ++ else: ++ auth_info = "anonymous" ++ ++ h.request('GET', req_url, None, headers) ++ ++ r = h.getresponse() ++ ++ actual_status = r.status ++ if expected_status and expected_status != actual_status: ++ ++ logger.warn("Expected status '" + str(expected_status) + ++ "' but got '" + str(actual_status) + ++ "' on url '" + req_url + "' (" + ++ auth_info + ").") ++ raise svntest.Failure ++ ++ if expected_body: ++ actual_body = r.read() ++ if expected_body != actual_body: ++ logger.warn("Expected body:") ++ logger.warn(expected_body) ++ logger.warn("But got:") ++ logger.warn(actual_body) ++ logger.warn("on url '" + req_url + "' (" + auth_info + ").") ++ raise svntest.Failure ++ ++def verify_gets(test_area_url, tests): ++ for test in tests: ++ verify_get(test_area_url, test['path'], test.get('user'), test.get('pw'), ++ test['status'], test.get('body'), test.get('headers')) ++ ++ ++###################################################################### ++# Tests ++# ++# Each test must return on success or raise on failure. ++ ++ ++#---------------------------------------------------------------------- ++ ++ ++@SkipUnless(svntest.main.is_ra_type_dav) ++def anon(sbox): ++ "test anonymous access" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/anon') ++ ++ write_authz_file(sbox) ++ ++ anon_tests = ( ++ { 'path': '', 'status': 301 }, ++ { 'path': '/', 'status': 200 }, ++ { 'path': '/repos', 'status': 301 }, ++ { 'path': '/repos/', 'status': 200 }, ++ { 'path': '/repos/A', 'status': 301 }, ++ { 'path': '/repos/A/', 'status': 200 }, ++ { 'path': '/repos/A/D', 'status': 301 }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H }, ++ { 'path': '/repos/A/D/gamma', 'status': 200 }, ++ { 'path': '/repos/A/D/H', 'status': 403 }, ++ { 'path': '/repos/A/D/H/', 'status': 403 }, ++ { 'path': '/repos/A/D/H/chi', 'status': 403 }, ++ # auth isn't configured so nothing should change when passing ++ # authn details ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ ) ++ ++ verify_gets(test_area_url, anon_tests) ++ ++ ++@SkipUnless(svntest.main.is_ra_type_dav) ++def mixed(sbox): ++ "test mixed anonymous and authenticated access" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/mixed') ++ ++ write_authz_file(sbox) ++ ++ mixed_tests = ( ++ { 'path': '', 'status': 301, }, ++ { 'path': '/', 'status': 200, }, ++ { 'path': '/repos', 'status': 301, }, ++ { 'path': '/repos/', 'status': 200, }, ++ { 'path': '/repos/A', 'status': 301, }, ++ { 'path': '/repos/A/', 'status': 200, }, ++ { 'path': '/repos/A/D', 'status': 301, }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, }, ++ { 'path': '/repos/A/D/H', 'status': 401, }, ++ { 'path': '/repos/A/D/H/', 'status': 401, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, }, ++ # auth is configured and user1 is allowed access to H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ ) ++ ++ verify_gets(test_area_url, mixed_tests) ++ ++@SkipUnless(svntest.main.is_ra_type_dav) ++@XFail(svntest.main.is_httpd_authz_provider_enabled) ++# uses the AuthzSVNNoAuthWhenAnonymousAllowed On directive ++# this is broken with httpd 2.3.x+ since it requires the auth system to accept ++# r->user == NULL and there is a test for this in server/request.c now. It ++# was intended as a workaround for the lack of Satisfy Any in 2.3.x+ which ++# was resolved by httpd with mod_access_compat in 2.3.x+. ++def mixed_noauthwhenanon(sbox): ++ "test mixed with noauthwhenanon directive" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/mixed-noauthwhenanon') ++ ++ write_authz_file(sbox) ++ ++ noauthwhenanon_tests = ( ++ { 'path': '', 'status': 301, }, ++ { 'path': '/', 'status': 200, }, ++ { 'path': '/repos', 'status': 301, }, ++ { 'path': '/repos/', 'status': 200, }, ++ { 'path': '/repos/A', 'status': 301, }, ++ { 'path': '/repos/A/', 'status': 200, }, ++ { 'path': '/repos/A/D', 'status': 301, }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, }, ++ { 'path': '/repos/A/D/H', 'status': 401, }, ++ { 'path': '/repos/A/D/H/', 'status': 401, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, }, ++ # auth is configured and user1 is allowed access to H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ # try with the wrong password for user1 ++ # note that unlike doing this with Satisfy Any this case ++ # actually provides anon access when provided with an invalid ++ # password ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ ) ++ ++ verify_gets(test_area_url, noauthwhenanon_tests) ++ ++ ++@SkipUnless(svntest.main.is_ra_type_dav) ++def authn(sbox): ++ "test authenticated only access" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/authn') ++ ++ write_authz_file(sbox) ++ ++ authn_tests = ( ++ { 'path': '', 'status': 401, }, ++ { 'path': '/', 'status': 401, }, ++ { 'path': '/repos', 'status': 401, }, ++ { 'path': '/repos/', 'status': 401, }, ++ { 'path': '/repos/A', 'status': 401, }, ++ { 'path': '/repos/A/', 'status': 401, }, ++ { 'path': '/repos/A/D', 'status': 401, }, ++ { 'path': '/repos/A/D/', 'status': 401, }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, }, ++ { 'path': '/repos/A/D/H', 'status': 401, }, ++ { 'path': '/repos/A/D/H/', 'status': 401, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, }, ++ # auth is configured and user1 is allowed access to H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ # try with upper case username for user1 ++ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ # try with upper case username for user2 ++ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ ) ++ ++ verify_gets(test_area_url, authn_tests) ++ ++@SkipUnless(svntest.main.is_ra_type_dav) ++def authn_anonoff(sbox): ++ "test authenticated only access with anonoff" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/authn-anonoff') ++ ++ write_authz_file(sbox) ++ ++ anonoff_tests = ( ++ { 'path': '', 'status': 401, }, ++ { 'path': '/', 'status': 401, }, ++ { 'path': '/repos', 'status': 401, }, ++ { 'path': '/repos/', 'status': 401, }, ++ { 'path': '/repos/A', 'status': 401, }, ++ { 'path': '/repos/A/', 'status': 401, }, ++ { 'path': '/repos/A/D', 'status': 401, }, ++ { 'path': '/repos/A/D/', 'status': 401, }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, }, ++ { 'path': '/repos/A/D/H', 'status': 401, }, ++ { 'path': '/repos/A/D/H/', 'status': 401, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, }, ++ # auth is configured and user1 is allowed access to H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ # try with upper case username for user1 ++ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ # try with upper case username for user2 ++ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ ) ++ ++ verify_gets(test_area_url, anonoff_tests) ++ ++@SkipUnless(svntest.main.is_ra_type_dav) ++def authn_lcuser(sbox): ++ "test authenticated only access with lcuser" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/authn-lcuser') ++ ++ write_authz_file(sbox) ++ ++ lcuser_tests = ( ++ # try with upper case username for user1 (works due to lcuser option) ++ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1_upper, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, ++ # try with upper case username for user2 (works due to lcuser option) ++ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, ++ ) ++ ++ verify_gets(test_area_url, lcuser_tests) ++ ++# authenticated access only by group - a excuse to use AuthzSVNAuthoritative Off ++# this is terribly messed up, Require group runs after mod_authz_svn. ++# so if mod_authz_svn grants the access then it doesn't matter what the group ++# requirement says. If we reject the access then you can use the AuthzSVNAuthoritative Off ++# directive to fall through to the group check. Overall the behavior of setups like this ++# is almost guaranteed to not be what users expect. ++@SkipUnless(svntest.main.is_ra_type_dav) ++def authn_group(sbox): ++ "test authenticated only access via groups" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/authn-group') ++ ++ # Can't use write_authz_file() as most tests because we want to deny all ++ # access with mod_authz_svn so the tests fall through to the group handling ++ authz_name = sbox.authz_name() ++ svntest.main.write_authz_file(sbox, { ++ '/': '* =', ++ }) ++ ++ group_tests = ( ++ { 'path': '', 'status': 401, }, ++ { 'path': '/', 'status': 401, }, ++ { 'path': '/repos', 'status': 401, }, ++ { 'path': '/repos/', 'status': 401, }, ++ { 'path': '/repos/A', 'status': 401, }, ++ { 'path': '/repos/A/', 'status': 401, }, ++ { 'path': '/repos/A/D', 'status': 401, }, ++ { 'path': '/repos/A/D/', 'status': 401, }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, }, ++ { 'path': '/repos/A/D/H', 'status': 401, }, ++ { 'path': '/repos/A/D/H/', 'status': 401, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, }, ++ # auth is configured and user1 is allowed access repo including H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ ) ++ ++ verify_gets(test_area_url, group_tests) ++ ++# This test exists to validate our behavior when used with the new authz ++# provider system introduced in httpd 2.3.x. The Satisfy directive ++# determines how older authz hooks are combined and the RequireA(ll|ny) ++# blocks handles how new authz providers are combined. The overall results of ++# all the authz providers (combined per the Require* blocks) are then ++# combined with the other authz hooks via the Satisfy directive. ++# Meaning this test requires that mod_authz_svn says yes and there is ++# either a valid user or the ALLOW header is 1. The header may seem ++# like a silly test but it's easier to excercise than say a host directive ++# in a repeatable test. ++@SkipUnless(svntest.main.is_httpd_authz_provider_enabled) ++def authn_sallrany(sbox): ++ "test satisfy all require any config" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/sallrany') ++ ++ write_authz_file(sbox) ++ ++ allow_header = { 'ALLOW': '1' } ++ ++ sallrany_tests = ( ++ #anon access isn't allowed without ALLOW header ++ { 'path': '', 'status': 401, }, ++ { 'path': '/', 'status': 401, }, ++ { 'path': '/repos', 'status': 401, }, ++ { 'path': '/repos/', 'status': 401, }, ++ { 'path': '/repos/A', 'status': 401, }, ++ { 'path': '/repos/A/', 'status': 401, }, ++ { 'path': '/repos/A/D', 'status': 401, }, ++ { 'path': '/repos/A/D/', 'status': 401, }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, }, ++ { 'path': '/repos/A/D/H', 'status': 401, }, ++ { 'path': '/repos/A/D/H/', 'status': 401, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, }, ++ # auth is configured and user1 is allowed access repo including H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, ++ # anon is allowed with the ALLOW header ++ { 'path': '', 'status': 301, 'headers': allow_header }, ++ { 'path': '/', 'status': 200, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 301, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 200, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 301, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 200, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 301, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'headers': allow_header }, ++ # these 3 tests return 403 instead of 401 becasue the config allows ++ # the anon user with the ALLOW header without any auth and the old hook ++ # system has no way of knowing it should return 401 since authentication is ++ # configured and can change the behavior. It could decide to return 401 just on ++ # the basis of authentication being configured but then that leaks info in other ++ # cases so it's better for this case to be "broken". ++ { 'path': '/repos/A/D/H', 'status': 403, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'headers': allow_header }, ++ # auth is configured and user1 is allowed access repo including H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ ++ ) ++ ++ verify_gets(test_area_url, sallrany_tests) ++ ++# See comments on authn_sallrany test for some background on the interaction ++# of Satisfy Any and the newer Require blocks. ++@SkipUnless(svntest.main.is_httpd_authz_provider_enabled) ++def authn_sallrall(sbox): ++ "test satisfy all require all config" ++ sbox.build(read_only = True, create_wc = False) ++ ++ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', ++ '/authz-test-work/sallrall') ++ ++ write_authz_file(sbox) ++ ++ allow_header = { 'ALLOW': '1' } ++ ++ sallrall_tests = ( ++ #anon access isn't allowed without ALLOW header ++ { 'path': '', 'status': 403, }, ++ { 'path': '/', 'status': 403, }, ++ { 'path': '/repos', 'status': 403, }, ++ { 'path': '/repos/', 'status': 403, }, ++ { 'path': '/repos/A', 'status': 403, }, ++ { 'path': '/repos/A/', 'status': 403, }, ++ { 'path': '/repos/A/D', 'status': 403, }, ++ { 'path': '/repos/A/D/', 'status': 403, }, ++ { 'path': '/repos/A/D/gamma', 'status': 403, }, ++ { 'path': '/repos/A/D/H', 'status': 403, }, ++ { 'path': '/repos/A/D/H/', 'status': 403, }, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, }, ++ # auth is configured but no access is allowed without the ALLOW header ++ { 'path': '', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass}, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass}, ++ # auth is configured but no access is allowed without the ALLOW header ++ { 'path': '', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass}, ++ # anon is not allowed even with ALLOW header ++ { 'path': '', 'status': 401, 'headers': allow_header }, ++ { 'path': '/', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'headers': allow_header }, ++ # auth is configured and user1 is allowed access repo including H ++ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, ++ 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, ++ # try with the wrong password for user1 ++ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, ++ # auth is configured and user2 is not allowed access to H ++ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, ++ 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, ++ # try with the wrong password for user2 ++ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, ++ ++ ) ++ ++ verify_gets(test_area_url, sallrall_tests) ++ ++ ++######################################################################## ++# Run the tests ++ ++ ++# list all tests here, starting with None: ++test_list = [ None, ++ anon, ++ mixed, ++ mixed_noauthwhenanon, ++ authn, ++ authn_anonoff, ++ authn_lcuser, ++ authn_group, ++ authn_sallrany, ++ authn_sallrall, ++ ] ++serial_only = True ++ ++if __name__ == '__main__': ++ svntest.main.run_tests(test_list) ++ # NOTREACHED ++ ++ ++### End of file. +Index: subversion-1.8.8/subversion/tests/cmdline/svntest/main.py +=================================================================== +--- subversion-1.8.8.orig/subversion/tests/cmdline/svntest/main.py 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/subversion/tests/cmdline/svntest/main.py 2015-08-19 14:29:57.305060904 -0400 +@@ -1367,6 +1367,30 @@ + return False + return True + ++ ++# https://issues.apache.org/bugzilla/show_bug.cgi?id=56480 ++# https://issues.apache.org/bugzilla/show_bug.cgi?id=55397 ++__mod_dav_url_quoting_broken_versions = frozenset([ ++ '2.2.27', ++ '2.2.26', ++ '2.2.25', ++ '2.4.9', ++ '2.4.8', ++ '2.4.7', ++ '2.4.6', ++ '2.4.5', ++]) ++def is_mod_dav_url_quoting_broken(): ++ if is_ra_type_dav(): ++ return (options.httpd_version in __mod_dav_url_quoting_broken_versions) ++ return None ++ ++def is_httpd_authz_provider_enabled(): ++ if is_ra_type_dav(): ++ v = options.httpd_version.split('.') ++ return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 ++ return None ++ + ###################################################################### + + +@@ -1424,6 +1448,8 @@ + args.append('--ssl-cert=' + options.ssl_cert) + if options.http_proxy: + args.append('--http-proxy=' + options.http_proxy) ++ if options.httpd_version: ++ args.append('--httpd-version=' + options.httpd_version) + + result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None, + *args) +@@ -1589,6 +1615,12 @@ + sandbox.cleanup_test_paths() + return exit_code + ++def is_httpd_authz_provider_enabled(): ++ if is_ra_type_dav(): ++ v = options.httpd_version.split('.') ++ return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 ++ return None ++ + ###################################################################### + # Main testing functions + +@@ -1769,6 +1801,8 @@ + help='Path to SSL server certificate.') + parser.add_option('--http-proxy', action='store', + help='Use the HTTP Proxy at hostname:port.') ++ parser.add_option('--httpd-version', action='store', ++ help='Assume HTTPD is this version.') + parser.add_option('--tools-bin', action='store', dest='tools_bin', + help='Use the svn tools installed in this path') + +Index: subversion-1.8.8/win-tests.py +=================================================================== +--- subversion-1.8.8.orig/win-tests.py 2015-08-19 14:29:57.309060949 -0400 ++++ subversion-1.8.8/win-tests.py 2015-08-19 14:29:57.305060904 -0400 +@@ -481,6 +481,7 @@ + self.httpd_config = os.path.join(self.root, 'httpd.conf') + self.httpd_users = os.path.join(self.root, 'users') + self.httpd_mime_types = os.path.join(self.root, 'mime.types') ++ self.httpd_groups = os.path.join(self.root, 'groups') + self.abs_builddir = abs_builddir + self.abs_objdir = abs_objdir + self.service_name = 'svn-test-httpd-' + str(httpd_port) +@@ -494,6 +495,7 @@ + create_target_dir(self.root_dir) + + self._create_users_file() ++ self._create_groups_file() + self._create_mime_types_file() + self._create_dontdothat_file() + +@@ -540,6 +542,8 @@ + if self.httpd_ver >= 2.2: + fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so')) + fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so')) ++ fp.write(self._sys_module('authz_groupfile_module', 'mod_authz_groupfile.so')) ++ fp.write(self._sys_module('authz_host_module', 'mod_authz_host.so')) + else: + fp.write(self._sys_module('auth_module', 'mod_auth.so')) + fp.write(self._sys_module('alias_module', 'mod_alias.so')) +@@ -562,6 +566,7 @@ + # Define two locations for repositories + fp.write(self._svn_repo('repositories')) + fp.write(self._svn_repo('local_tmp')) ++ fp.write(self._svn_authz_repo()) + + # And two redirects for the redirect tests + fp.write('RedirectMatch permanent ^/svn-test-work/repositories/' +@@ -592,6 +597,17 @@ + 'jrandom', 'rayjandom']) + os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, + 'jconstant', 'rayjandom']) ++ os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, ++ 'JRANDOM', 'rayjandom']) ++ os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, ++ 'JCONSTANT', 'rayjandom']) ++ ++ def _create_groups_file(self): ++ "Create groups for mod_authz_svn tests" ++ fp = open(self.httpd_groups, 'w') ++ fp.write('random: jrandom\n') ++ fp.write('constant: jconstant\n') ++ fp.close() + + def _create_mime_types_file(self): + "Create empty mime.types file" +@@ -652,6 +668,153 @@ + ' DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \ + '\n' + ++ def _svn_authz_repo(self): ++ local_tmp = os.path.join(self.abs_builddir, ++ CMDLINE_TEST_SCRIPT_NATIVE_PATH, ++ 'svn-test-work', 'local_tmp') ++ return \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' ' + '\n' \ ++ ' Require all granted' + '\n' \ ++ ' ' + '\n' \ ++ ' ' + '\n' \ ++ ' Allow from all' + '\n' \ ++ ' ' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' Satisfy Any' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' AuthzSVNNoAuthWhenAnonymousAllowed On' + '\n' \ ++ ' SVNPathAuthz On' + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' AuthzSVNAnonymous Off' + '\n' \ ++ ' SVNPathAuthz On' + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' AuthzForceUsernameCase Lower' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' AuthzForceUsernameCase Lower' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' AuthGroupFile ' + self._quote(self.httpd_groups) + '\n' \ ++ ' Require group random' + '\n' \ ++ ' AuthzSVNAuthoritative Off' + '\n' \ ++ ' SVNPathAuthz On' + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' AuthzSendForbiddenOnFailure On' + '\n' \ ++ ' Satisfy All' + '\n' \ ++ ' ' + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ ++ ' ' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ ''+ '\n' \ ++ ' DAV svn' + '\n' \ ++ ' SVNParentPath ' + local_tmp + '\n' \ ++ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ ++ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ ++ ' SVNListParentPath On' + '\n' \ ++ ' AuthType Basic' + '\n' \ ++ ' AuthName "Subversion Repository"' + '\n' \ ++ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ ++ ' AuthzSendForbiddenOnFailure On' + '\n' \ ++ ' Satisfy All' + '\n' \ ++ ' ' + '\n' \ ++ ' Require valid-user' + '\n' \ ++ ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ ++ ' ' + '\n' \ ++ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ ++ '' + '\n' \ ++ '' + '\n' \ ++ + def start(self): + if self.service: + self._start_service() +@@ -786,6 +949,10 @@ + log_file = os.path.join(abs_builddir, log) + fail_log_file = os.path.join(abs_builddir, faillog) + ++ if run_httpd: ++ httpd_version = "%.1f" % daemon.httpd_ver ++ else: ++ httpd_version = None + th = run_tests.TestHarness(abs_srcdir, abs_builddir, + log_file, + fail_log_file, +@@ -795,6 +962,7 @@ + fsfs_sharding, fsfs_packing, + list_tests, svn_bin, mode_filter, + milestone_filter, ++ httpd_version=httpd_version, + set_log_level=log_level, ssl_cert=ssl_cert) + old_cwd = os.getcwd() + try: --- subversion-1.8.8.orig/debian/patches/CVE-2015-3187.patch +++ subversion-1.8.8/debian/patches/CVE-2015-3187.patch @@ -0,0 +1,340 @@ +Description: fix sensitive path information disclosure +Origin: backport, http://subversion.apache.org/security/CVE-2015-3187-advisory.txt + +Index: subversion-1.8.8/subversion/libsvn_repos/rev_hunt.c +=================================================================== +--- subversion-1.8.8.orig/subversion/libsvn_repos/rev_hunt.c 2015-08-19 14:30:14.809261292 -0400 ++++ subversion-1.8.8/subversion/libsvn_repos/rev_hunt.c 2015-08-19 14:30:14.805261247 -0400 +@@ -726,23 +726,6 @@ + if (! prev_path) + break; + +- if (authz_read_func) +- { +- svn_boolean_t readable; +- svn_fs_root_t *tmp_root; +- +- SVN_ERR(svn_fs_revision_root(&tmp_root, fs, revision, currpool)); +- SVN_ERR(authz_read_func(&readable, tmp_root, path, +- authz_read_baton, currpool)); +- if (! readable) +- { +- svn_pool_destroy(lastpool); +- svn_pool_destroy(currpool); +- +- return SVN_NO_ERROR; +- } +- } +- + /* Assign the current path to all younger revisions until we reach + the copy target rev. */ + while ((revision_ptr < revision_ptr_end) +@@ -765,6 +748,20 @@ + path = prev_path; + revision = prev_rev; + ++ if (authz_read_func) ++ { ++ svn_boolean_t readable; ++ SVN_ERR(svn_fs_revision_root(&root, fs, revision, currpool)); ++ SVN_ERR(authz_read_func(&readable, root, path, ++ authz_read_baton, currpool)); ++ if (!readable) ++ { ++ svn_pool_destroy(lastpool); ++ svn_pool_destroy(currpool); ++ return SVN_NO_ERROR; ++ } ++ } ++ + /* Clear last pool and switch. */ + svn_pool_clear(lastpool); + tmppool = lastpool; +Index: subversion-1.8.8/subversion/tests/cmdline/authz_tests.py +=================================================================== +--- subversion-1.8.8.orig/subversion/tests/cmdline/authz_tests.py 2015-08-19 14:30:14.809261292 -0400 ++++ subversion-1.8.8/subversion/tests/cmdline/authz_tests.py 2015-08-19 14:30:14.805261247 -0400 +@@ -609,8 +609,10 @@ + + ## cat + ++ expected_err2 = ".*svn: E195012: Unable to find repository location.*" ++ + # now see if we can look at the older version of rho +- svntest.actions.run_and_verify_svn(None, None, expected_err, ++ svntest.actions.run_and_verify_svn(None, None, expected_err2, + 'cat', '-r', '2', D_url+'/rho') + + if sbox.repo_url.startswith('http'): +@@ -627,10 +629,11 @@ + svntest.actions.run_and_verify_svn(None, None, expected_err, + 'diff', '-r', 'HEAD', G_url+'/rho') + +- svntest.actions.run_and_verify_svn(None, None, expected_err, ++ # diff treats the unreadable path as indicating an add so no error ++ svntest.actions.run_and_verify_svn(None, None, [], + 'diff', '-r', '2', D_url+'/rho') + +- svntest.actions.run_and_verify_svn(None, None, expected_err, ++ svntest.actions.run_and_verify_svn(None, None, [], + 'diff', '-r', '2:4', D_url+'/rho') + + # test whether read access is correctly granted and denied +Index: subversion-1.8.8/subversion/tests/libsvn_repos/repos-test.c +=================================================================== +--- subversion-1.8.8.orig/subversion/tests/libsvn_repos/repos-test.c 2015-08-19 14:30:14.809261292 -0400 ++++ subversion-1.8.8/subversion/tests/libsvn_repos/repos-test.c 2015-08-19 14:32:26.402765498 -0400 +@@ -3260,6 +3260,245 @@ + return SVN_NO_ERROR; + } + ++static svn_error_t * ++mkdir_delete_copy(svn_repos_t *repos, ++ const char *src, ++ const char *dst, ++ apr_pool_t *pool) ++{ ++ svn_fs_t *fs = svn_repos_fs(repos); ++ svn_revnum_t youngest_rev; ++ svn_fs_txn_t *txn; ++ svn_fs_root_t *txn_root, *rev_root; ++ ++ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool)); ++ ++ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool)); ++ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); ++ SVN_ERR(svn_fs_make_dir(txn_root, "A/T", pool)); ++ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool)); ++ ++ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool)); ++ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); ++ SVN_ERR(svn_fs_delete(txn_root, "A/T", pool)); ++ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool)); ++ ++ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool)); ++ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); ++ SVN_ERR(svn_fs_revision_root(&rev_root, fs, youngest_rev - 1, pool)); ++ SVN_ERR(svn_fs_copy(rev_root, src, txn_root, dst, pool)); ++ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool)); ++ ++ return SVN_NO_ERROR; ++} ++ ++struct authz_read_baton_t { ++ apr_hash_t *paths; ++ apr_pool_t *pool; ++ const char *deny; ++}; ++ ++static svn_error_t * ++authz_read_func(svn_boolean_t *allowed, ++ svn_fs_root_t *root, ++ const char *path, ++ void *baton, ++ apr_pool_t *pool) ++{ ++ struct authz_read_baton_t *b = baton; ++ ++ if (b->deny && !strcmp(b->deny, path)) ++ *allowed = FALSE; ++ else ++ *allowed = TRUE; ++ ++ svn_hash_sets(b->paths, apr_pstrdup(b->pool, path), (void*)1); ++ ++ return SVN_NO_ERROR; ++} ++ ++static svn_error_t * ++verify_locations(apr_hash_t *actual, ++ apr_hash_t *expected, ++ apr_hash_t *checked, ++ apr_pool_t *pool) ++{ ++ apr_hash_index_t *hi; ++ ++ for (hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi)) ++ { ++ const svn_revnum_t *rev = svn__apr_hash_index_key(hi); ++ const char *path = apr_hash_get(actual, rev, sizeof(svn_revnum_t)); ++ ++ if (!path) ++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, ++ "expected %s for %d found (null)", ++ (char*)svn__apr_hash_index_val(hi), ++ (int)*rev); ++ else if (strcmp(path, svn__apr_hash_index_val(hi))) ++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, ++ "expected %s for %d found %s", ++ (char*)svn__apr_hash_index_val(hi), ++ (int)*rev, path); ++ ++ } ++ ++ for (hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi)) ++ { ++ const svn_revnum_t *rev = svn__apr_hash_index_key(hi); ++ const char *path = apr_hash_get(expected, rev, sizeof(svn_revnum_t)); ++ ++ if (!path) ++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, ++ "found %s for %d expected (null)", ++ (char*)svn__apr_hash_index_val(hi), ++ (int)*rev); ++ else if (strcmp(path, svn__apr_hash_index_val(hi))) ++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, ++ "found %s for %d expected %s", ++ (char*)svn__apr_hash_index_val(hi), ++ (int)*rev, path); ++ ++ if (!svn_hash_gets(checked, path)) ++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, ++ "did not check %s", path); ++ } ++ ++ return SVN_NO_ERROR; ++} ++ ++static void ++set_expected(apr_hash_t *expected, ++ svn_revnum_t rev, ++ const char *path, ++ apr_pool_t *pool) ++{ ++ svn_revnum_t *rp = apr_palloc(pool, sizeof(svn_revnum_t)); ++ *rp = rev; ++ apr_hash_set(expected, rp, sizeof(svn_revnum_t), path); ++} ++ ++static svn_error_t * ++trace_node_locations_authz(const svn_test_opts_t *opts, ++ apr_pool_t *pool) ++{ ++ svn_repos_t *repos; ++ svn_fs_t *fs; ++ svn_revnum_t youngest_rev = 0; ++ svn_fs_txn_t *txn; ++ svn_fs_root_t *txn_root; ++ struct authz_read_baton_t arb; ++ apr_array_header_t *revs = apr_array_make(pool, 10, sizeof(svn_revnum_t)); ++ apr_hash_t *locations; ++ apr_hash_t *expected = apr_hash_make(pool); ++ int i; ++ ++ /* Create test repository. */ ++ SVN_ERR(svn_test__create_repos(&repos, "test-repo-trace-node-locations-authz", ++ opts, pool)); ++ fs = svn_repos_fs(repos); ++ ++ /* r1 create A */ ++ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool)); ++ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); ++ SVN_ERR(svn_fs_make_dir(txn_root, "A", pool)); ++ SVN_ERR(svn_fs_make_file(txn_root, "A/f", pool)); ++ SVN_ERR(svn_test__set_file_contents(txn_root, "A/f", "foobar", pool)); ++ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool)); ++ ++ /* r4 copy A to B */ ++ SVN_ERR(mkdir_delete_copy(repos, "A", "B", pool)); ++ ++ /* r7 copy B to C */ ++ SVN_ERR(mkdir_delete_copy(repos, "B", "C", pool)); ++ ++ /* r10 copy C to D */ ++ SVN_ERR(mkdir_delete_copy(repos, "C", "D", pool)); ++ ++ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool)); ++ SVN_ERR_ASSERT(youngest_rev == 10); ++ ++ arb.paths = apr_hash_make(pool); ++ arb.pool = pool; ++ arb.deny = NULL; ++ ++ apr_array_clear(revs); ++ for (i = 0; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ set_expected(expected, 10, "/D/f", pool); ++ set_expected(expected, 8, "/C/f", pool); ++ set_expected(expected, 7, "/C/f", pool); ++ set_expected(expected, 5, "/B/f", pool); ++ set_expected(expected, 4, "/B/f", pool); ++ set_expected(expected, 2, "/A/f", pool); ++ set_expected(expected, 1, "/A/f", pool); ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ apr_array_clear(revs); ++ for (i = 1; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ apr_array_clear(revs); ++ for (i = 2; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ set_expected(expected, 1, NULL, pool); ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ apr_array_clear(revs); ++ for (i = 3; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ set_expected(expected, 2, NULL, pool); ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ apr_array_clear(revs); ++ for (i = 6; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ set_expected(expected, 5, NULL, pool); ++ set_expected(expected, 4, NULL, pool); ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ arb.deny = "/B/f"; ++ apr_array_clear(revs); ++ for (i = 0; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ apr_array_clear(revs); ++ for (i = 6; i <= youngest_rev; ++i) ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = i; ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ APR_ARRAY_PUSH(revs, svn_revnum_t) = 0; ++ apr_hash_clear(arb.paths); ++ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs, ++ authz_read_func, &arb, pool)); ++ SVN_ERR(verify_locations(locations, expected, arb.paths, pool)); ++ ++ return SVN_NO_ERROR; ++} ++ + + /* The test table. */ + +@@ -3306,5 +3545,7 @@ + "test svn_repos_delete"), + SVN_TEST_OPTS_PASS(filename_with_control_chars, + "test filenames with control characters"), ++ SVN_TEST_OPTS_PASS(trace_node_locations_authz, ++ "authz for svn_repos_trace_node_locations"), + SVN_TEST_NULL + }; --- subversion-1.8.8.orig/debian/patches/CVE-2015-5343.patch +++ subversion-1.8.8/debian/patches/CVE-2015-5343.patch @@ -0,0 +1,36 @@ +------------------------------------------------------------------------ +r1718290 | kotkov | 2015-12-07 02:15:26 -0800 (Mon, 07 Dec 2015) | 10 lines + +Merge r1718269 from trunk: + + * r1718269 + mod_dav_svn: Defer the actual memory allocation when reading skel-encoded + requests. + Justification: + Avoids unneeded memory allocation. + Votes: + +1: kotkov, philip, ivan + +------------------------------------------------------------------------ + +CVE-2015-5343 + +Index: subversion/mod_dav_svn/util.c +=================================================================== +diff --git a/subversion/mod_dav_svn/util.c b/subversion/mod_dav_svn/util.c +--- a/subversion/mod_dav_svn/util.c (revision 1718289) ++++ b/subversion/mod_dav_svn/util.c (revision 1718290) +@@ -778,7 +778,12 @@ + + if (content_length) + { +- buf = svn_stringbuf_create_ensure(content_length, pool); ++ /* Do not allocate more than 1 MB until we receive request body. */ ++ apr_size_t alloc_len = 1 * 1024 *1024; ++ if (content_length < alloc_len) ++ alloc_len = (apr_size_t) content_length; ++ ++ buf = svn_stringbuf_create_ensure(alloc_len, pool); + } + else + { --- subversion-1.8.8.orig/debian/patches/CVE-2016-2167.patch +++ subversion-1.8.8/debian/patches/CVE-2016-2167.patch @@ -0,0 +1,30 @@ +------------------------------------------------------------------------ +r1740258 | kotkov | 2016-04-21 01:57:30 -0700 (Thu, 21 Apr 2016) | 9 lines + +Merge r1740254 from trunk: + + * r1740254 + svnserve: Reject invalid usernames when SASL is being used. + Justification: + Properly handle a few more cases with invalid usernames. + Votes: + +1: kotkov, philip, rhuijben + +------------------------------------------------------------------------ + +CVE-2016-2167 + +Index: subversion/svnserve/cyrus_auth.c +=================================================================== +diff --git a/subversion/svnserve/cyrus_auth.c b/subversion/svnserve/cyrus_auth.c +--- a/subversion/svnserve/cyrus_auth.c (revision 1740257) ++++ b/subversion/svnserve/cyrus_auth.c (revision 1740258) +@@ -74,6 +74,8 @@ + { + /* The only valid realm is user_realm (i.e. the repository's realm). + If the user gave us another realm, complain. */ ++ if (realm_len != inlen-(pos-in+1)) ++ return SASL_BADPROT; + if (strncmp(pos+1, user_realm, inlen-(pos-in+1)) != 0) + return SASL_BADPROT; + } --- subversion-1.8.8.orig/debian/patches/CVE-2016-2168.patch +++ subversion-1.8.8/debian/patches/CVE-2016-2168.patch @@ -0,0 +1,51 @@ +------------------------------------------------------------------------ +r1740256 | kotkov | 2016-04-21 01:54:35 -0700 (Thu, 21 Apr 2016) | 9 lines + +Merge r1740252 from trunk: + + * r1740252 + mod_authz_svn: Reject requests with invalid Destination headers. + Justification: + These requests aren't valid and should result in an error. + Votes: + +1: kotkov, ivan, rhuijben, philip + +------------------------------------------------------------------------ + +CVE-2016-2168 + +Index: subversion/mod_authz_svn/mod_authz_svn.c +=================================================================== +diff --git a/subversion/mod_authz_svn/mod_authz_svn.c b/subversion/mod_authz_svn/mod_authz_svn.c +--- a/subversion/mod_authz_svn/mod_authz_svn.c (revision 1740255) ++++ b/subversion/mod_authz_svn/mod_authz_svn.c (revision 1740256) +@@ -639,6 +639,8 @@ + + if (r->method_number == M_MOVE || r->method_number == M_COPY) + { ++ apr_status_t status; ++ + dest_uri = apr_table_get(r->headers_in, "Destination"); + + /* Decline MOVE or COPY when there is no Destination uri, this will +@@ -647,7 +649,19 @@ + if (!dest_uri) + return DECLINED; + +- apr_uri_parse(r->pool, dest_uri, &parsed_dest_uri); ++ status = apr_uri_parse(r->pool, dest_uri, &parsed_dest_uri); ++ if (status) ++ { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, ++ "Invalid URI in Destination header"); ++ return HTTP_BAD_REQUEST; ++ } ++ if (!parsed_dest_uri.path) ++ { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ "Invalid URI in Destination header"); ++ return HTTP_BAD_REQUEST; ++ } + + ap_unescape_url(parsed_dest_uri.path); + dest_uri = parsed_dest_uri.path; --- subversion-1.8.8.orig/debian/patches/CVE-2016-8734-1.8.patch +++ subversion-1.8.8/debian/patches/CVE-2016-8734-1.8.patch @@ -0,0 +1,203 @@ +------------------------------------------------------------------------ +r1770680 | kotkov | 2016-11-21 05:04:14 -0800 (Mon, 21 Nov 2016) | 9 lines + +Merge r1770677 from trunk: + + * r1770677 + Make the XML parser stricter by prohibiting custom XML entities. + Justification: + The parser should properly error out on invalid data. + Votes: + +1: kotkov, rhuijben, stefan2 + +------------------------------------------------------------------------ + +CVE-2016-8734 + +Index: subversion/libsvn_subr/xml.c +=================================================================== +diff --git a/subversion/libsvn_subr/xml.c b/subversion/libsvn_subr/xml.c +--- a/subversion/libsvn_subr/xml.c (revision 1770679) ++++ b/subversion/libsvn_subr/xml.c (revision 1770680) +@@ -259,6 +259,14 @@ + } + + ++#ifndef XML_VERSION_AT_LEAST ++#define XML_VERSION_AT_LEAST(major,minor,patch) \ ++(((major) < XML_MAJOR_VERSION) \ ++ || ((major) == XML_MAJOR_VERSION && (minor) < XML_MINOR_VERSION) \ ++ || ((major) == XML_MAJOR_VERSION && (minor) == XML_MINOR_VERSION && \ ++ (patch) <= XML_MICRO_VERSION)) ++#endif /* XML_VERSION_AT_LEAST */ ++ + const char * + svn_xml_fuzzy_escape(const char *string, apr_pool_t *pool) + { +@@ -338,6 +346,28 @@ + (*svn_parser->data_handler)(svn_parser->baton, s, (apr_size_t)len); + } + ++#if XML_VERSION_AT_LEAST(1, 95, 8) ++static void expat_entity_declaration(void *userData, ++ const XML_Char *entityName, ++ int is_parameter_entity, ++ const XML_Char *value, ++ int value_length, ++ const XML_Char *base, ++ const XML_Char *systemId, ++ const XML_Char *publicId, ++ const XML_Char *notationName) ++{ ++ svn_xml_parser_t *svn_parser = userData; ++ ++ /* Stop the parser if an entity declaration is hit. */ ++ XML_StopParser(svn_parser->parser, 0 /* resumable */); ++} ++#else ++/* A noop default_handler. */ ++static void expat_default_handler(void *userData, const XML_Char *s, int len) ++{ ++} ++#endif + + /*** Making a parser. ***/ + +@@ -359,6 +389,12 @@ + XML_SetCharacterDataHandler(parser, + data_handler ? expat_data_handler : NULL); + ++#if XML_VERSION_AT_LEAST(1, 95, 8) ++ XML_SetEntityDeclHandler(parser, expat_entity_declaration); ++#else ++ XML_SetDefaultHandler(parser, expat_default_handler); ++#endif ++ + /* ### we probably don't want this pool; or at least we should pass it + ### to the callbacks and clear it periodically. */ + subpool = svn_pool_create(pool); +@@ -440,6 +476,9 @@ + /* This will cause the current XML_Parse() call to finish quickly! */ + XML_SetElementHandler(svn_parser->parser, NULL, NULL); + XML_SetCharacterDataHandler(svn_parser->parser, NULL); ++#if XML_VERSION_AT_LEAST(1, 95, 8) ++ XML_SetEntityDeclHandler(svn_parser->parser, NULL); ++#endif + + /* Once outside of XML_Parse(), the existence of this field will + cause svn_delta_parse()'s main read-loop to return error. */ +Index: subversion/libsvn_ra_serf/util.c +=================================================================== +diff --git a/subversion/libsvn_ra_serf/util.c b/subversion/libsvn_ra_serf/util.c +--- a/subversion/libsvn_ra_serf/util.c (revision 1770679) ++++ b/subversion/libsvn_ra_serf/util.c (revision 1770680) +@@ -2694,7 +2694,31 @@ + #endif + } + ++#ifdef EXPAT_HAS_STOPPARSER ++static void ++expat_entity_declaration(void *userData, ++ const XML_Char *entityName, ++ int is_parameter_entity, ++ const XML_Char *value, ++ int value_length, ++ const XML_Char *base, ++ const XML_Char *systemId, ++ const XML_Char *publicId, ++ const XML_Char *notationName) ++{ ++ struct expat_ctx_t *ectx = userData; + ++ /* Stop the parser if an entity declaration is hit. */ ++ XML_StopParser(ectx->parser, 0 /* resumable */); ++} ++#else ++/* A noop default_handler. */ ++static void ++expat_default_handler(void *userData, const XML_Char *s, int len) ++{ ++} ++#endif ++ + /* Implements svn_ra_serf__response_handler_t */ + static svn_error_t * + expat_response_handler(serf_request_t *request, +@@ -2712,6 +2736,12 @@ + XML_SetUserData(ectx->parser, ectx); + XML_SetElementHandler(ectx->parser, expat_start, expat_end); + XML_SetCharacterDataHandler(ectx->parser, expat_cdata); ++ ++#ifdef EXPAT_HAS_STOPPARSER ++ XML_SetEntityDeclHandler(ectx->parser, expat_entity_declaration); ++#else ++ XML_SetDefaultHandler(ectx->parser, expat_default_handler); ++#endif + } + + /* ### TODO: sline.code < 200 should really be handled by the core */ +Index: tools/server-side/mod_dontdothat/mod_dontdothat.c +=================================================================== +diff --git a/tools/server-side/mod_dontdothat/mod_dontdothat.c b/tools/server-side/mod_dontdothat/mod_dontdothat.c +--- a/tools/server-side/mod_dontdothat/mod_dontdothat.c (revision 1770679) ++++ b/tools/server-side/mod_dontdothat/mod_dontdothat.c (revision 1770680) +@@ -42,6 +42,14 @@ + + module AP_MODULE_DECLARE_DATA dontdothat_module; + ++#ifndef XML_VERSION_AT_LEAST ++#define XML_VERSION_AT_LEAST(major,minor,patch) \ ++(((major) < XML_MAJOR_VERSION) \ ++ || ((major) == XML_MAJOR_VERSION && (minor) < XML_MINOR_VERSION) \ ++ || ((major) == XML_MAJOR_VERSION && (minor) == XML_MINOR_VERSION && \ ++ (patch) <= XML_MICRO_VERSION)) ++#endif /* XML_VERSION_AT_LEAST */ ++ + typedef struct dontdothat_config_rec { + const char *config_file; + const char *base_path; +@@ -551,6 +559,31 @@ + } + } + ++#if XML_VERSION_AT_LEAST(1, 95, 8) ++static void ++expat_entity_declaration(void *userData, ++ const XML_Char *entityName, ++ int is_parameter_entity, ++ const XML_Char *value, ++ int value_length, ++ const XML_Char *base, ++ const XML_Char *systemId, ++ const XML_Char *publicId, ++ const XML_Char *notationName) ++{ ++ dontdothat_filter_ctx *ctx = userData; ++ ++ /* Stop the parser if an entity declaration is hit. */ ++ XML_StopParser(ctx->xmlp, 0 /* resumable */); ++} ++#else ++/* A noop default_handler. */ ++static void ++expat_default_handler(void *userData, const XML_Char *s, int len) ++{ ++} ++#endif ++ + static svn_boolean_t + is_valid_wildcard(const char *wc) + { +@@ -696,6 +729,12 @@ + XML_SetElementHandler(ctx->xmlp, start_element, end_element); + XML_SetCharacterDataHandler(ctx->xmlp, cdata); + ++#if XML_VERSION_AT_LEAST(1, 95, 8) ++ XML_SetEntityDeclHandler(ctx->xmlp, expat_entity_declaration); ++#else ++ XML_SetDefaultHandler(ctx->xmlp, expat_default_handler); ++#endif ++ + ap_add_input_filter("DONTDOTHAT_FILTER", ctx, r, r->connection); + } + } --- subversion-1.8.8.orig/debian/patches/CVE-2017-9800-1.8.18.patch +++ subversion-1.8.8/debian/patches/CVE-2017-9800-1.8.18.patch @@ -0,0 +1,110 @@ +CVE-2017-9800 Patch for Subversion 1.9.6 +Origin: subversion notification + +[Ubuntu note: modified slightly to take into account added debian +setting that drops ssh's control master -- sbeattie] + +Index: subversion/libsvn_ra_svn/client.c +=================================================================== +--- subversion/libsvn_ra_svn/client.c (revision 1803926) ++++ subversion/libsvn_ra_svn/client.c (working copy) +@@ -46,6 +46,7 @@ + #include "svn_props.h" + #include "svn_mergeinfo.h" + #include "svn_version.h" ++#include "svn_ctype.h" + + #include "svn_private_config.h" + +@@ -395,7 +396,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 -o ControlMaster=no"; ++ val = "$SVN_SSH ssh -q -o ControlMaster=no --"; + } + + if (!val || !*val) +@@ -435,7 +436,7 @@ + ; + *argv = apr_palloc(pool, (n + 4) * sizeof(char *)); + memcpy((void *) *argv, cmd_argv, n * sizeof(char *)); +- (*argv)[n++] = svn_path_uri_decode(hostinfo, pool); ++ (*argv)[n++] = hostinfo; + (*argv)[n++] = "svnserve"; + (*argv)[n++] = "-t"; + (*argv)[n] = NULL; +@@ -716,7 +717,33 @@ + } + + ++/* A simple whitelist to ensure the following are valid: ++ * user@server ++ * [::1]:22 ++ * server-name ++ * server_name ++ * 127.0.0.1 ++ * with an extra restriction that a leading '-' is invalid. ++ */ ++static svn_boolean_t ++is_valid_hostinfo(const char *hostinfo) ++{ ++ const char *p = hostinfo; + ++ if (p[0] == '-') ++ return FALSE; ++ ++ while (*p) ++ { ++ if (!svn_ctype_isalnum(*p) && !strchr(":.-_[]@", *p)) ++ return FALSE; ++ ++ ++p; ++ } ++ ++ return TRUE; ++} ++ + static svn_error_t *ra_svn_open(svn_ra_session_t *session, + const char **corrected_url, + const char *url, +@@ -740,8 +767,17 @@ + parse_tunnel(url, &tunnel, pool); + + if (tunnel) +- SVN_ERR(find_tunnel_agent(tunnel, uri.hostinfo, &tunnel_argv, config, +- pool)); ++ { ++ const char *decoded_hostinfo; ++ ++ decoded_hostinfo = svn_path_uri_decode(uri.hostinfo, pool); ++ if (!is_valid_hostinfo(decoded_hostinfo)) ++ return svn_error_createf(SVN_ERR_BAD_URL, NULL, _("Invalid host '%s'"), ++ uri.hostinfo); ++ ++ SVN_ERR(find_tunnel_agent(tunnel, decoded_hostinfo, &tunnel_argv, ++ config, pool)); ++ } + else + tunnel_argv = NULL; + +Index: subversion/libsvn_subr/config_file.c +=================================================================== +--- subversion/libsvn_subr/config_file.c (revision 1803926) ++++ subversion/libsvn_subr/config_file.c (working copy) +@@ -1134,12 +1134,12 @@ + "### 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 -o ControlMaster=no" 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 ++ "# rsh = rsh --" NL + "### Or, if you wanted to specify a full path and arguments:" NL +- "# rsh = /path/to/rsh -l myusername" NL ++ "# rsh = /path/to/rsh -l myusername --" NL + "### On Windows, if you are specifying a full path to a command," NL + "### use a forward slash (/) or a paired backslash (\\\\) as the" NL + "### path separator. A single backslash will be treated as an" NL --- subversion-1.8.8.orig/debian/patches/apache_module_dependency +++ subversion-1.8.8/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 +@@ -67,6 +67,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 + */ +@@ -937,6 +944,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 + */ +@@ -958,6 +975,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 +@@ -1330,6 +1330,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.8.8.orig/debian/patches/apr-abi +++ subversion-1.8.8/debian/patches/apr-abi @@ -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 +@@ -111,9 +111,13 @@ + AC_SUBST(SVN_APRUTIL_INCLUDES) + AC_SUBST(SVN_APRUTIL_CONFIG, ["$apu_config"]) + AC_SUBST(SVN_APRUTIL_LIBS) ++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.8.8.orig/debian/patches/build-fixes +++ subversion-1.8.8/debian/patches/build-fixes @@ -0,0 +1,184 @@ +Fix some build problems: + +- SWIG out-of-tree stuff +- 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 +@@ -113,8 +113,8 @@ + + SHELL = @SHELL@ + LIBTOOL = @SVN_LIBTOOL@ +-LTFLAGS = --tag=CC --silent +-LTCXXFLAGS = --tag=CXX --silent ++LTFLAGS = --tag=CC ++LTCXXFLAGS = --tag=CXX + LT_CFLAGS = @LT_CFLAGS@ + LT_LDFLAGS = @LT_LDFLAGS@ + LT_SO_VERSION = @SVN_LT_SOVERSION@ +@@ -315,14 +315,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. +@@ -811,8 +811,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; \ +@@ -846,7 +845,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 {} ';' + +@@ -876,8 +875,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 +@@ -340,7 +340,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 +@@ -688,6 +688,7 @@ + fi + + AH_BOTTOM([ ++#undef /* */ _ + /* Indicate to translators that string X should be translated. Do not look + up the translation at run time; just expand to X. This macro is suitable + for use where a constant string is required at compile time. */ +@@ -1508,6 +1509,11 @@ + [Defined to the config.guess name of the build target]) + + AC_OUTPUT ++if test "$abs_srcdir" != "$abs_builddir" ++then ++ AC_MSG_NOTICE([Creating build directories]) ++ (cd "$abs_srcdir"; find subversion tools -type d) | xargs $MKDIR ++fi + + # ==== Print final messages to user ========================================== + +--- a/build.conf ++++ b/build.conf +@@ -213,7 +213,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 + +@@ -276,7 +276,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) +--- a/subversion/libsvn_ra_serf/update.c ++++ b/subversion/libsvn_ra_serf/update.c +@@ -3082,12 +3082,6 @@ + SVN_ERR(svn_ra_serf__process_pending(parser_ctx, + &report->report_received, + iterpool_inner)); +- +- /* Debugging purposes only! */ +- for (i = 0; i < sess->num_conns; i++) +- { +- serf_debug__closed_conn(sess->conns[i]->bkt_alloc); +- } + } + + /* If we got a complete report, close the edit. Otherwise, abort it. */ +--- a/subversion/libsvn_ra_serf/util.c ++++ b/subversion/libsvn_ra_serf/util.c +@@ -945,12 +945,6 @@ + + return svn_ra_serf__wrap_err(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.8.8.orig/debian/patches/examples-compile-instructions +++ subversion-1.8.8/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.8.8.orig/debian/patches/java-build +++ subversion-1.8.8/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/build-outputs.mk.ezt ++++ b/build/generator/templates/build-outputs.mk.ezt +@@ -102,7 +102,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.8.8.orig/debian/patches/last-changed-date-charset +++ subversion-1.8.8/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 +@@ -209,8 +209,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 'P': /* relative path of this file */ + if (repos_root_url && *repos_root_url != '\0' && url && *url != '\0') --- subversion-1.8.8.orig/debian/patches/libtool-check.diff +++ subversion-1.8.8/debian/patches/libtool-check.diff @@ -0,0 +1,13 @@ +Index: b/build/buildcheck.sh +=================================================================== +--- a/build/buildcheck.sh ++++ b/build/buildcheck.sh +@@ -97,7 +97,7 @@ + esac + fi + +-libtool=${LIBTOOL:-`./build/PrintPath glibtool libtool libtool15`} ++libtool=${LIBTOOL:-`./build/PrintPath libtoolize glibtool libtool libtool15`} + # Extract the libtool version number: everything from the first number in + # the version text until a hyphen or space. + lt_pversion=`$libtool --version 2>/dev/null | --- subversion-1.8.8.orig/debian/patches/no-extra-libs +++ subversion-1.8.8/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 +@@ -94,9 +94,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 +@@ -98,9 +98,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.8.8.orig/debian/patches/no-extra-libs-2 +++ subversion-1.8.8/debian/patches/no-extra-libs-2 @@ -0,0 +1,57 @@ +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/subversion/bindings/swig/perl/native/Makefile.PL.in ++++ b/subversion/bindings/swig/perl/native/Makefile.PL.in +@@ -43,6 +43,12 @@ + 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 = <<'EOT'; +@@ -86,10 +92,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" } + ); + +@@ -99,6 +101,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") } +@@ -113,6 +116,7 @@ + ); + + for (@modules) { ++ $config{LIBS} = [libs_line($_, 'subr')]; + WriteMakefile(%config, + MAKEFILE=> "Makefile.$_", + NAME => "SVN::_".perlish($_), +--- a/build.conf ++++ b/build.conf +@@ -1148,7 +1148,7 @@ + + [apriconv] + type = lib +-external-lib = $(SVN_APRUTIL_LIBS) ++external-lib = $(SVN_APR_LIBS) + + [bdb] + type = lib --- subversion-1.8.8.orig/debian/patches/python-builds +++ subversion-1.8.8/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 +@@ -133,6 +133,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]) +@@ -289,6 +290,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 +@@ -427,7 +427,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 +@@ -436,7 +436,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 +@@ -445,7 +445,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 +@@ -454,7 +454,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 +@@ -463,7 +463,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 +@@ -472,7 +472,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 +@@ -481,7 +481,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 +@@ -490,13 +490,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.8.8.orig/debian/patches/repos-templates +++ subversion-1.8.8/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 +@@ -276,7 +276,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 + +@@ -361,8 +361,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; +@@ -451,10 +454,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; +@@ -775,7 +781,7 @@ + "REV=\"$2\"" NL + "TXN_NAME=\"$3\"" 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 + +@@ -838,7 +844,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 + +@@ -899,7 +906,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 + +@@ -966,8 +974,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.8.8.orig/debian/patches/rpath +++ subversion-1.8.8/debian/patches/rpath @@ -0,0 +1,75 @@ +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 +@@ -216,10 +216,10 @@ + # special compilation for files destined for cxxhl + COMPILE_CXXHL_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=compile $(COMPILE_CXX) $(LT_CFLAGS) $(CXXHL_INCLUDES) -o $@ -c + +-LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(libdir) +-LINK_LIB = $(LINK) $(LT_SO_VERSION) +-LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS) $(LDFLAGS) -rpath $(libdir) +-LINK_CXX_LIB = $(LINK_CXX) $(LT_SO_VERSION) ++LINK = $(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) +@@ -777,7 +777,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 +@@ -501,7 +501,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) +@@ -524,7 +524,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 +@@ -415,7 +415,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') +@@ -467,6 +467,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') --- subversion-1.8.8.orig/debian/patches/ruby-no-strict-aliasing +++ subversion-1.8.8/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 +@@ -139,7 +139,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.8.8.orig/debian/patches/ruby-test-info +++ subversion-1.8.8/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.8.8.orig/debian/patches/ruby-test-svnserve-race +++ subversion-1.8.8/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" + + # Tale of a hack... + # +@@ -287,11 +288,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 +@@ -357,4 +354,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.8.8.orig/debian/patches/ruby-typemap-digest +++ subversion-1.8.8/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 +@@ -1093,7 +1093,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.8.8.orig/debian/patches/series +++ subversion-1.8.8/debian/patches/series @@ -0,0 +1,33 @@ +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-abi +python-builds +examples-compile-instructions +apache_module_dependency +workaround_EINVAL_on_kfreebsd +libtool-check.diff +verbose-tests.diff +CVE-2014-3522.patch +CVE-2014-3528.patch +CVE-2014-3580.patch +CVE-2014-8108.patch +CVE-2015-0202.patch +CVE-2015-0248.patch +CVE-2015-0251.patch +CVE-2015-3184.patch +CVE-2015-3187.patch +CVE-2015-5343.patch +CVE-2016-2167.patch +CVE-2016-2168.patch +CVE-2016-8734-1.8.patch +CVE-2017-9800-1.8.18.patch -p0 --- subversion-1.8.8.orig/debian/patches/ssh-no-controlmaster +++ subversion-1.8.8/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 +@@ -1134,7 +1134,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 +@@ -395,7 +395,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.8.8.orig/debian/patches/svnshell +++ subversion-1.8.8/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.8.8.orig/debian/patches/verbose-tests.diff +++ subversion-1.8.8/debian/patches/verbose-tests.diff @@ -0,0 +1,13 @@ +Index: b/Makefile.in +=================================================================== +--- a/Makefile.in ++++ b/Makefile.in +@@ -820,7 +820,7 @@ + check-swig-py: swig-py + $(TEST_SHLIB_VAR_SWIG_PY) \ + cd $(SWIG_PY_DIR); \ +- $(PYTHON) $(SWIG_PY_SRC_DIR)/tests/run_all.py ++ $(PYTHON) $(SWIG_PY_SRC_DIR)/tests/run_all.py --verbose + + EXTRACLEAN_SWIG_PY=rm -rf $(SWIG_PY_SRC_DIR)/svn_*.c $(SWIG_PY_SRC_DIR)/core.c \ + $(SWIG_PY_SRC_DIR)/[a-z]*.py --- subversion-1.8.8.orig/debian/patches/workaround_EINVAL_on_kfreebsd +++ subversion-1.8.8/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 +@@ -369,6 +369,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.8.8.orig/debian/python-subversion.README.Debian +++ subversion-1.8.8/debian/python-subversion.README.Debian @@ -0,0 +1 @@ +See /usr/bin/svnshell for an example that uses the python bindings. --- subversion-1.8.8.orig/debian/python-subversion.dirs +++ subversion-1.8.8/debian/python-subversion.dirs @@ -0,0 +1 @@ +usr/bin --- subversion-1.8.8.orig/debian/python-subversion.examples +++ subversion-1.8.8/debian/python-subversion.examples @@ -0,0 +1 @@ +tools/examples/*.py --- subversion-1.8.8.orig/debian/python-subversion.install +++ subversion-1.8.8/debian/python-subversion.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/*/libsvn_swig_py*.so.* +debian/tmp/usr/lib/python* --- subversion-1.8.8.orig/debian/python-subversion.lintian-overrides +++ subversion-1.8.8/debian/python-subversion.lintian-overrides @@ -0,0 +1,3 @@ +# 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.* +no-symbols-control-file usr/lib/*/libsvn_swig_py2.*-1.so.* --- subversion-1.8.8.orig/debian/ruby-svn.install +++ subversion-1.8.8/debian/ruby-svn.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/*/libsvn_swig_ruby*.so.* +debian/tmp/usr/lib/ruby --- subversion-1.8.8.orig/debian/ruby-svn.lintian-overrides +++ subversion-1.8.8/debian/ruby-svn.lintian-overrides @@ -0,0 +1,3 @@ +# 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.* +no-symbols-control-file usr/lib/*/libsvn_swig_ruby-1.so.* --- subversion-1.8.8.orig/debian/rules +++ subversion-1.8.8/debian/rules @@ -0,0 +1,482 @@ +#!/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 | + +include /usr/share/dpkg/default.mk + +# 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 := +ifneq (,$(filter $(DEB_HOST_ARCH), $(DISABLE_JAVAHL_ARCHS))) + ENABLE_JAVAHL := +endif + +# We may need to disable libapache2-mod-svn and/or libsvn-ruby*. +ENABLE_APACHE := yes +ENABLE_RUBY := yes + +DEB_BUILDDIR := BUILD +MAKE_B := $(MAKE) -C $(DEB_BUILDDIR) +AUTH_LIB_DIRS := $(DEB_BUILDDIR)/subversion/libsvn_auth_gnome_keyring/.libs:$(DEB_BUILDDIR)/subversion/libsvn_auth_kwallet/.libs + +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 -vr) +PYDEFAULT := $(shell pyversions -vd) + +allpy = \ + set -e; for v in $(PYVERSIONS); do \ + $(RM) $(PY_DIR); \ + ln -fs python$$v $(PY_DIR); \ + pyinc=$$(python$$v-config --includes); \ + pylib=$$(python$$v -c 'from distutils import sysconfig; print sysconfig.get_python_lib()'); \ + $1; \ + done + +allpydbg = \ + set -e; for v in $(PYVERSIONS); do \ + $(RM) $(PY_DIR); \ + ln -fs python$$v-dbg $(PY_DIR); \ + pyinc=$$(python$$v-dbg-config --includes); \ + pylib=$$(python$$v-dbg -c 'from distutils import sysconfig; print sysconfig.get_python_lib()'); \ + $1; \ + done + +libdir := /usr/lib/$(DEB_HOST_MULTIARCH) +# ~max(min required sqlite, stable's sqlite) +MIN_SQLITE_VER := 3.7.12 +confflags := \ + --prefix=/usr \ + --libdir=$(libdir) \ + --mandir=\$${prefix}/share/man \ + --with-apr=/usr \ + --with-apr-util=/usr \ + --with-serf=/usr \ + --enable-sqlite-compatibility-version=$(MIN_SQLITE_VER) \ + --with-berkeley-db=:::db \ + --with-sasl=/usr \ + --with-editor=/usr/bin/editor \ + --with-ruby-sitedir=/usr/lib/ruby \ + --with-ruby-test-verbose \ + --with-swig=/usr \ + --with-kwallet \ + $(shell dpkg-buildflags --export=configure) \ + --with-gnome-keyring + +ifdef DEB_OPT_DEBUG + confflags+= --enable-debug +endif +export EXTRA_CFLAGS := $(CFLAGS) +export EXTRA_CXXFLAGS := $(CXXFLAGS) +export EXTRA_CPPFLAGS := $(CPPFLAGS) +export EXTRA_LDFLAGS := $(LDFLAGS) +export EXTRA_SWIG_LDFLAGS := $(EXTRA_LDFLAGS) + +export DH_OPTIONS +ifdef DEB_OPT_WITH_JAVAHL + # jikes 1.22 cannot compile javahl. + confflags += --enable-javahl --without-jikes \ + --with-jdk=/usr/lib/jvm/default-java \ + --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 --with-apache-libexecdir=/usr/lib/apache2/modules +else + confflags += --without-apxs + DH_OPTIONS += -Nlibapache2-mod-svn -Nlibapache2-svn +endif + +ifdef DEB_OPT_WITH_RUBY + RUBY := ruby + 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-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-bindings + for v in $(PYVERSIONS); do \ + cp -la $(PY_DIR) $(PY_DIR)$$v; \ + done + for v in $(PYVERSIONS); do \ + cp -la $(PY_DIR) $(PY_DIR)$$v-dbg; \ + 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 + @echo checking swig-py with optimized interpreter + $(call allpy, \ + $(MAKE_B) $@ PYTHON=python$$v PYVER=$$v $(check_defs)) + @echo checking swig-py with debug interpreter + $(call allpydbg, \ + $(MAKE_B) $@ PYTHON=python$$v-dbg PYVER=$${v}_d \ + PYTHON_INCLUDES="$$pyinc" $(check_defs)) \ + || true + +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) + $(call allpydbg, $(MAKE_B) -j1 autogen-swig) + ln -sf python$(PYDEFAULT) $(PY_DIR) + +$(MAKE_B) all tools + # Run svn once, to make sure it populates $(HOME)/.subversion/* + env LD_LIBRARY_PATH="$(AUTH_LIB_DIRS):$(LD_LIBRARY_PATH)" $(DEB_BUILDDIR)/subversion/svn/svn --version > /dev/null + $(call allpy, \ + $(MAKE_B) swig-py PYTHON=python$$v PYVER=$$v \ + PYTHON_INCLUDES="$$pyinc" \ + swig_pydir=$$pylib/libsvn swig_pydir_extra=$$pylib/svn) + $(call allpydbg, \ + $(MAKE_B) swig-py PYTHON=python$$v PYVER=$${v}_d \ + PYTHON_INCLUDES="$$pyinc" \ + EXTRA_SWIG_PY_CFLAGS=-O0 \ + swig_pydir=$$pylib/libsvn swig_pydir_extra=$$pylib/svn) + ln -sf python$(PYDEFAULT) $(PY_DIR) + # 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 + mkdir -p $(DEB_BUILDDIR)/doc/doxygen + +$(MAKE_B) doc-api + $(MAKE) -C $(DEB_BUILDDIR) locale-gnu-pot + touch $@ + +clean: unpatch + dh_testdir + dh_clean + $(RM) patches + ! [ -f $(DEB_BUILDDIR)/Makefile ] || $(MAKE_B) extraclean-bindings 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 + $(RM) subversion/libsvn_fs_fs/rep-cache-db.h + $(RM) subversion/libsvn_subr/internal_statements.h + $(RM) subversion/libsvn_wc/wc-queries.h + 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) subversion/po/subversion.pot + $(RM) -r debian/tmp-dbg + $(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 allpydbg, \ + $(MAKE_B) install-swig-py DESTDIR=$(CURDIR)/debian/tmp \ + PYTHON=python$$v-dbg PYVER=$${v}_d \ + PYTHON_INCLUDES="$$pyinc" \ + EXTRA_SWIG_PY_CFLAGS=-O0 \ + swig_pydir=$$pylib/libsvn swig_pydir_extra=$$pylib/svn) + for i in $$(find debian/tmp/usr/lib/python* -name '*.so'); do \ + b=$$(basename $$i .so); \ + mv $$i $$(dirname $$i)/$${b}_d.so; \ + done + find debian/tmp/usr/lib/python* \ + ! -type d ! -name '*.so' ! -name '*.so.*' | xargs -r rm -f + $(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-1.a libsvnjavahl-1.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)/ + $(RM) debian/libsvn-dev/$(libdir)/libsvnjavahl-1.so +endif + + # move the python debug modules to the -dbg package + (cd debian/python-subversion && tar cf - $$(find -name '*_d.so')) \ + | (cd debian/python-subversion-dbg && tar xf - ) + mkdir -p debian/python-subversion-dbg/$(libdir) + mv debian/python-subversion/$(libdir)/libsvn_swig_py*d-1.so.* \ + debian/python-subversion-dbg/$(libdir)/ + find debian/python-subversion -name '*_d.so' | xargs rm -f + + install -m644 tools/client-side/bash_completion \ + debian/subversion/etc/bash_completion.d/subversion + + dh_apache2 -s +ifdef DEB_OPT_WITH_APACHE + install subversion/mod_authz_svn/INSTALL \ + debian/libapache2-mod-svn/usr/share/doc/libapache2-mod-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 -ppython-subversion --dbg-package=python-subversion-dbg + dh_strip -s -Npython-subversion --dbg-package=subversion-dbg + rm -rf debian/python-subversion-dbg/usr/share/doc/python-subversion-dbg + ln -s python-subversion \ + debian/python-subversion-dbg/usr/share/doc/python-subversion-dbg + 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_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.8.8.orig/debian/shlibs.local +++ subversion-1.8.8/debian/shlibs.local @@ -0,0 +1,7 @@ +libsvn_auth_gnome_keyring-1 1 libsvn1 (>= 1) +libsvn_auth_kwallet-1 1 libsvn1 (>= 1) +libsvn_ra_local-1 1 libsvn1 (>= 1) +libsvn_ra_serf-1 1 libsvn1 (>= 1) +libsvn_fs_base-1 1 libsvn1 (>= 1) +libsvn_fs_fs-1 1 libsvn1 (>= 1) +libsvn_fs_util-1 1 libsvn1 (>= 1) --- subversion-1.8.8.orig/debian/source/format +++ subversion-1.8.8/debian/source/format @@ -0,0 +1 @@ +1.0 --- subversion-1.8.8.orig/debian/source/lintian-overrides +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.NEWS +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.docs +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.install +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.lintian-overrides +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.manpages +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.postinst +++ subversion-1.8.8/debian/subversion-tools.postinst @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +dpkg-maintscript-helper rm_conffile /etc/svn2cl/authors.xml 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2html.css 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2html.xsl 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2cl.xsl 1.7.14-1~ subversion-tools -- "$@" + +#DEBHELPER# --- subversion-1.8.8.orig/debian/subversion-tools.postrm +++ subversion-1.8.8/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.8.8.orig/debian/subversion-tools.preinst +++ subversion-1.8.8/debian/subversion-tools.preinst @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +dpkg-maintscript-helper rm_conffile /etc/svn2cl/authors.xml 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2html.css 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2html.xsl 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2cl.xsl 1.7.14-1~ subversion-tools -- "$@" + +#DEBHELPER# --- subversion-1.8.8.orig/debian/subversion-tools.prerm +++ subversion-1.8.8/debian/subversion-tools.prerm @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +dpkg-maintscript-helper rm_conffile /etc/svn2cl/authors.xml 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2html.css 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2html.xsl 1.7.14-1~ subversion-tools -- "$@" +dpkg-maintscript-helper rm_conffile /etc/svn2cl/svn2cl.xsl 1.7.14-1~ subversion-tools -- "$@" + +#DEBHELPER# --- subversion-1.8.8.orig/debian/subversion.NEWS +++ subversion-1.8.8/debian/subversion.NEWS @@ -0,0 +1,59 @@ +subversion (1.8.8-1) unstable; urgency=medium + + If you are using BDB repositories, you will get “svn: E160029” errors + when you try to use them, due to the move to db5.3. To fix this, just + run “svnadmin recover /path/to/repo” for each affected repository. + + Note that BDB repositories have been deprecated upstream as of + Subversion 1.8.0, so it may also be an opportunity to switch to an + FSFS repository by using svnadmin dump/load. + + -- James McCoy Thu, 20 Feb 2014 20:38:10 -0500 + +subversion (1.8.5-1) unstable; urgency=low + + Subversion 1.8.x requires upgrading the format of a working copy. + This can be performed by running "svn upgrade" in the working copy. + Doing so will prevent use of older Subversion releases with that + working copy. + + -- James McCoy Sun, 05 Jan 2014 13:43:36 -0500 + +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.8.8.orig/debian/subversion.README.Debian +++ subversion-1.8.8/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.8.8.orig/debian/subversion.dirs +++ subversion-1.8.8/debian/subversion.dirs @@ -0,0 +1 @@ +etc/bash_completion.d --- subversion-1.8.8.orig/debian/subversion.docs +++ subversion-1.8.8/debian/subversion.docs @@ -0,0 +1,4 @@ +README +debian/svn_1.6_releasenotes.html +debian/svn_1.7_releasenotes.html +debian/svn_1.8_releasenotes.html --- subversion-1.8.8.orig/debian/subversion.examples +++ subversion-1.8.8/debian/subversion.examples @@ -0,0 +1,3 @@ +tools/dev/gnuify-changelog.pl +tools/dev/merge-graph.py +tools/dev/mergegraph --- subversion-1.8.8.orig/debian/subversion.install +++ subversion-1.8.8/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.8.8.orig/debian/subversion.postinst +++ subversion-1.8.8/debian/subversion.postinst @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +dpkg-maintscript-helper rm_conffile /etc/emacs/site-start.d/50psvn.el 1.7.13-1~ -- "$@" + +#DEBHELPER# --- subversion-1.8.8.orig/debian/subversion.preinst +++ subversion-1.8.8/debian/subversion.preinst @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +dpkg-maintscript-helper rm_conffile /etc/emacs/site-start.d/50psvn.el 1.7.13-1~ -- "$@" + +#DEBHELPER# --- subversion-1.8.8.orig/debian/subversion.prerm +++ subversion-1.8.8/debian/subversion.prerm @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +dpkg-maintscript-helper rm_conffile /etc/emacs/site-start.d/50psvn.el 1.7.13-1~ -- "$@" + +#DEBHELPER# --- subversion-1.8.8.orig/debian/svn_1.6_releasenotes.html +++ subversion-1.8.8/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.8.8.orig/debian/svn_1.7_releasenotes.html +++ subversion-1.8.8/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.8.8.orig/debian/svn_1.8_releasenotes.html +++ subversion-1.8.8/debian/svn_1.8_releasenotes.html @@ -0,0 +1,2640 @@ + + + +Apache Subversion 1.8 Release Notes + + + + + + + +
+
+ + + +
+ + + +

Apache Subversion 1.8 Release Notes

+ +
+

What's New in Apache Subversion 1.8 + +

+ + + +

Apache Subversion 1.8 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.7.x is also +in 1.8, but 1.8 contains features and bugfixes not present in any +earlier release. The new features will eventually be documented in a +1.8 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.8 section of the CHANGES +file.

+ +
+ +
+

Compatibility Concerns + +

+ +

Older clients and servers interoperate transparently with 1.8 +servers and clients. However, some of the new 1.8 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.8 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.8 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.8 libraries. However, a program written for 1.8 +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.

+ +
+

New Feature Compatibility Table + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New FeatureMinimum Client1Minimum ServerMinimum RepositoryNotes
working copy records moves1.8anyany
Automatic reintegration merge1.81.51.5
neon support removed1.8anyanyServer-side configuration changes + might be required for optimal performance with 1.8 clients which + access the repository via HTTP.
Inheritable properties1.8anyanyA 1.8 server isn't required but will deliver superior performance + when asked for inherited properties.
Repos dictated config props1.8anyany
Password caching with gpg-agent1.8anyany
FSFS enhancementsany1.81.8Repository size reduction + requires dump/load.
Authz file in repositoryany1.8any
1Reminder: when using the file:// + repository access method, the Subversion program is both the client + and the server.
+ +
+ +
+

Upgrading the Working Copy + +

+ +

Subversion 1.8 introduces changes to the working copy format. +In previous releases of Subversion (1.6 and earlier), Subversion would +automatically upgrade the working copy to the new format when a write +operation was performed. Subversion 1.8, however, requires an upgrade for +both read and write operations on the working copy, and makes the upgrade +a manual step.

+ +

Before using Subversion 1.8 with existing working copies, users will be +required to run the svn upgrade command to upgrade working copy +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.

+ +

Subversion 1.8 can only upgrade working copies created with Subversion 1.6 +and Subversion 1.7.

+ +

Note: Subversion 1.8 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.8, a 1.6 +client must be used to run svn cleanup on all 1.6 working copies that +require cleanup. Likewise, Subversion 1.8 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.

+ +

If your working copy does not upgrade cleanly, please check out a new one.

+ +
+ +
+

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 mergeinfo + +

+ +

The default output of svn mergeinfo has been changed. Instead +of being equivalent to svn mergeinfo --show-revs=merged, it now +shows a diagrammatic summary of some information about merges between the +two specified branches:

+
+$ svn mergeinfo ^/subversion/branches/moves-scan-log
+    youngest common ancestor
+    |         last full merge
+    |         |        tip of branch
+    |         |        |         repository path
+
+    1186287            1445648 
+    |                  |       
+       --| |------------         subversion/branches/moves-scan-log
+      /         /              
+     /         /               
+  -------| |------------         subversion/trunk
+              |        |       
+              1241413  1445640 
+$ 
+
+ +

Scripts using svn mergeinfo without a --show-revs= +option should be updated to add --show-revs=merged.

+ +
+ +
+

New options for svn proplist and svn propget + +

+ +

The default output for these commands remains the same, but both +support the new option --show-inherited-props which may produce +output changes from 1.7.x. See inheritable properties +for more information.

+ +
+ +
+

Improved output and new options for svnlook proplist and + svnlook propget + +

+ +

The output of svnlook proplist and +svnlook proplist --verbose has changed and now mimics the output +of svn proplist and svn proplist --verbose respectively. +svnlook propget now supports the --verbose option, which +produces output similar to svn propget --verbose.

+ +

Both svnlook proplist and svnlook propget now support the +new option --show-inherited-props which may produce output changes +from 1.7.x. See inheritable properties +for more information.

+ +
+ +
+

svn status and svn info now show local moves + +

+ +

svn status now shows moves in its output. +See the section about local moves for more information.

+ +

svn status shows an extra line for each item involved in a move:

+
$ svn move epsilon/zeta zeta-moved
+$ svn status
+D       epsilon/zeta
+        > moved to zeta-moved
+A  +    zeta-moved
+        > moved from epsilon/zeta
+$ 
+
+ +

svn info shows extra lines for locally moved items, too. +For example, if the file beta was moved to beta-new, +svn info beta will show the following (some unrelated output +has been omitted in this example):

+
+$ svn info beta      
+Path: beta
+[...]
+Schedule: delete
+Moved To: beta-new
+[...]
+
+ +
+ +
+

svn info now shows repository-relative URLs + +

+ +svn info now includes repository-relative URLs of items +in the working copy in its output. +The command line client has been +accepting this URL notation since Subversion 1.6. + +
$ svn info README                                       
+Path: README
+Name: README
+Working Copy Root Path: /tmp/svn-trunk
+URL: https://svn.apache.org/repos/asf/subversion/trunk/README
+Relative URL: ^/subversion/trunk/README
+Repository Root: https://svn.apache.org/repos/asf
+Repository UUID: 13f79535-47bb-0310-9956-ffa450edef68
+Revision: 1467597
+Node Kind: file
+Schedule: normal
+Last Changed Author: danielsh
+Last Changed Rev: 1242804
+Last Changed Date: 2012-02-10 15:58:53 +0100 (Fri, 10 Feb 2012)
+Text Last Updated: 2012-09-20 01:33:22 +0200 (Thu, 20 Sep 2012)
+Checksum: a27c71319a591c4eebe2bb81129413947336a7c6
+
+ +
+ +
+ +
+

HTTP client support based on neon has been removed + +

+ +

HTTP client support based on neon +has been removed in favor of HTTP client support based on +serf.

+ +

serf is a high-performance HTTP client library which has formed the basis +of an alternative HTTP repository access method for many years. +In an effort to decrease the development burden of maintaining multiple +HTTP client interfaces (and sets of bugs!) serf is now the only HTTP +client provider for Subversion.

+ +
+

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.

+
+ +
+

Skelta style updates are now the default + +

+ +

The svn 1.8 client with serf defaults to skelta mode for update +operations (checkout, update, merge and export) instead of the bulk update mode +used by previous versions. Skelta mode was introduced in Subversion 1.6.0 and +improved in 1.8.0. It uses one HTTP request and response per resource that needs +to be fetched from the server, whereas bulk update mode fetches all resources in +one massive reponse.

+ +

The main benefit of skelta mode is that it allows a correctly set up Apache +server or intermediate proxy server to cache mod_dav_svn’s responses to +handle later requests from the cache. This results in improved performance of +svn client operations and reduced CPU usage on the server side. It also allows +a more detailed audit of clients accessing resources in a Subversion +repository.

+ +

Skelta mode has some disadvantages:

+
    +
  • Apache server access log files will grow more quickly due to the larger +number of requests and responses. As of 1.7.3, the httpd error logs may also +grow more rapidly with serf clients than with neon clients; see +r1239697.
  • +
  • Network traffic can increase drastically when Kerberos or NTLM +authentication is used, as these add a 2 - 4 KB header per HTTP request and +response.
  • +
+ +

This release introduces two options to control if the svn client will use +skelta or bulk update mode.

+

+

    +
  • For the server administrator: The SVNAllowBulkUpdates directive for +mod_dav_svn now accepts Prefer. This will advise the svn +client to always use bulk update mode. All svn client versions with a default +configuration (see table) will respect this preference.
  • + +
  • For the user: Set the new option http-bulk-updates in the servers +runtime configuration file to yes to force the use of bulk updates, +no to never use bulk updates. The default option auto makes +svn use skelta mode with a 1.8 server (unless it has SVNAllowBulkUpdates +set to Prefer), and bulk updates mode with +older servers and 1.8 servers which prefer bulk updates.
  • +
+

+ +

Table explaining the mode used between each combination of svn client and +server version and relevant configuration directives:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.8 Server
with SVNAllowBulkUpdates:
1.7 and older Server
with SVNAllowBulkUpdates:
Subversion ClientOffOn*PreferOffOn*
1.8, http-bulk-updates: auto*Skelta modeSkelta modeBulk modeSkelta modeBulk mode
1.8, http-bulk-updates: yesSkelta modeBulk modeBulk modeSkelta modeBulk mode
1.8, http-bulk-updates: noSkelta modeSkelta modeSkelta modeSkelta modeSkelta mode
1.7 and older with neon*Skelta modeBulk modeBulk modeSkelta modeBulk mode
1.7 and older with serfSkelta modeSkelta modeSkelta modeSkelta modeSkelta mode
+

*Default configuration

+ +
+ +
+ +
+

The Berkeley DB-based repository back-end has been deprecated + +

+ +

The Subversion developers have decided to deprecate the +repository back-end based on Berkeley DB. We simply do not have the +necessary resources to continue developing two distinct repository +back-ends. Instead, we will concentrate our efforts on improving FSFS +with new features, robustness and performance and architectural +enhancements.

+ +
+

What this means: + +

+
    +
  • New repository features that may appear in future versions of +Subversion will not be implemented for the BDB back-end, +nor will we make any effort to improve its performance.
  • +
  • We will fix bugs and +security issues that may be found.
  • +
  • At some point, support for the BDB back-end will be completely +removed. We will announce such removal well in advance of its +happening.
  • +
+
+ +
+

What this does not mean: + +

+
    +
  • Users do not have to immediately migrate their repositories to +FSFS. The BDB back-end will continue to work, and will receive as +much test coverage as it has until now.
  • +
+
+ +

This being a volunteer project, we are of course always happy +to accept contributions towards maintaining the Berkeley DB +back-end.

+ +
+

User-visible changes + +

+

The only visible effect of the deprecation is that the +svnadmin utility will print a warning when it +creates a new Berkeley DB-based repository.

+
+ +
+ +
+

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.

+ +
+

FS paths syntax in authz access rules + +

+ +

Prior to this release, the section headers in Subversion's authz +access files—which contain repository names and repository +filesystem paths—accepted section headers that would never be +looked up, because the repository filesystem path (such as +/trunk/secretdir) embedded in the section header is formatted +differently from how Subversion formats those paths when it looks them +up in the file. Subversion 1.7 and earlier would silently ignore +those sections of the authz file; directives in those sections would +never apply.

+ +

That's been fixed in this release: Subversion will now +error out if a section header contains a repository filesystem path that +either does not begin with a slash or contains two consecutive slashes. +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 all access to items in your repositories being unexpectedly + +denied as a result of upgrading to Subversion +1.8. The svnauthz tool, when linked to Subversion 1.8 +libraries, can be used to test an authz file for validity using the validate +subcommand. (The tool will error out on a file that the Subversion server will +error out on.)

+ +
+ +
+

Repository listing now honors authz configuration + +

+ +

When Apache is configured with the SVNParentPath +directive, the "Collection of Repositories" list will now be filtered +based on read access to the root of each repository. Previously, all +repositories were included in the list even if navigating to a +repository would be forbidden. The "Collection of Repositories" will +now be consistent with the directory lists within repositories.

+ +

NOTE: Access to "Collection of Repositories" is not +restricted by mod_authz_svn, but is instead managed by mod_dav_svn +itself. In order to require authentication on this location, the +location should have "Satisfy All" (which is the default value of this +directive). See examples in mod_authz_svn's INSTALL document for additional details.

+ +
+ +
+

FSFS 'svnadmin verify' finds mergeinfo-count and predecessor-count discrepancies + +

+ +

Up to 1.7.0, Subversion could create erroneous metadata on nodes in a +FSFS-backed repository in certain situations involving concurrent commit +attempts. (Only metadata was affected; file contents and properties +was not.) As of 1.7.1 Subversion + +prevents new instances of the corruption, but +only as of 1.8.0 does 'svnadmin verify' + +detect instances of that corruption in the history of a repository.

+ +

The fix to these issues is simple: perform a dump/load cycle. (As usual, svnsync can be used instead of dump/load.) +The cycle can be done with any version of Subversion, and after the cycle the +repository should be served exclusively by Subversion 1.7.5 or newer to prevent +further instances of the bug from entering the repository.

+ +

See this summary of issue #4129 for more information +about these problems.

+ +
+ +
+

Client prompting for SSL client certificates + +

+ +

Subversion has long supported the use of SSL client certificates +for authentication against a server which accepts such. Users +typically employ the ssl-client-cert-file option in their +'servers' runtime configuration file to inform the client regarding +the location of the relevant certificate file. In interactive +scenarios, Subversion can also prompt the user for the location of the +certificate file when that runtime-configured value isn't set or +otherwise suitable.

+ +

Prior to 1.8.0, this prompting was enabled by default. +Unfortunately, not every server which accepts client certificates +also requires them. Some users were being prompted for +client certificate file locations in scenarios where no certificate +was required (or perhaps even available). So in Subversion 1.8.0, the +Subversion client defaults to not prompting for the location +of an SSL client certificate file unless the user has set the new +ssl-client-cert-file-prompt runtime configuration +option (found in the [auth] section of the 'config' file) +to "yes".

+ +

See issue +#2410 for discussion and details.

+ +
+ +
+

Star-imports in the SWIG-Python bindings + +

+ +

The swig-py bindings have been changed to make *-imports +of submodules to do the right thing: +from svn.client import * will now import only symbols beginning with +svn_ or SVN_. (Most of these symbols will be +svn_client_* symbols, of course.) Star-imports of from svn have +not changed (they import just the bare submodule names: 'fs', 'ra', etc), and +star imports of from svn.core currently imports some select symbols +(notably 'Pool' and 'SubversionException').

+ +

This change is incompatible: code that expected symbols such as 'commit_txn' +(in 'fs') and 'apr_initialize' to be pulled by a star-import will have to change.

+ +
+ +
+

svnserve --config-file behavior with password and authz dbs + +

+ +

The behavior of the --config-file option to svnserve has changed. +The password db and authz db files will be reloaded on each connection. In past +versions these files were cached on startup when --config-file was +used.

+ +

The svnserve.conf file directly passed to --config-file will still +be cached. Provided that the locations you wish to use for the authz and +password dbs have not changed, you will not need to restart svnserve in order to +have the changes you make to these files applied. This makes the behavior of +--config-file more consistent with configurations that do not use this +option.

+ +

If you were depending on the configuration changes not being applied until +you restarted svnserve you will need to adjust accordingly.

+ +
+ +
+

svnauthz-validate renamed to svnauthz + +

+ +

The svnauthz-validate command has been renamed to svnauthz and now has +a 'validate' subcommand. Meaning the equivalent to svnauthz-validate +file in 1.8 is svnauthz validate file. To maintain command +line compatibility, if the svnauthz command is run with the command name of +svnauthz-validate then it emulates the behavior of the +svnauthz-validate command from 1.7. make install-tools +installs a symlink svnauthz-validate to provide this compatibility +functionality.

+ +

svnauthz also provides new functionality. +See this section for details.

+ +
+ +
+ +
+ +
+

New Features + +

+ +
+

Working copy records moves as first-class operation + +

+ +

The effect of the svn move command is now different +from running svn copy followed by svn delete. +Moves are represented within the working copy as a copy and a delete which +are linked to one another. +These links are shown by svn status and svn info.

+ +

Some Subversion operations will now treat locally moved files and directories +specially. Behavioural changes include:

+
    +
  • svn move now refuses to move a + mixed-revision working copy.

  • +
  • svn commit will only commit a moved file or directory + if both sides of the move are part of the same commit. This ensures + that moves are an atomic operation upon future updates and merges.

  • +
  • svn update, svn switch, and svn resolve + can now resolve tree conflicts involving locally moved files or + directories. By picking the 'mine-conflict' option at the conflict + prompt, the update or switch operation can be applied to the new location + of the moved file or directory, which resolves the tree conflict and + allows the move to be committed. It is also possible to break a move + instead of updating it, in which case the move becomes a copy which + is no longer linked to a deletion.

  • +
+ +

Limitations:

+
    +
  • Moves are recorded as such only within the working copy. The link + between the copy and the delete is established only when a local move + operation is performed, and is lost upon commit. The committed revision + will show a copy and a delete, instead of a move.

  • +
+ +

Known issues:

+
    +
  • Tree conflicts involving replacements are currently + not detected when updating a moved file or directory (see issue #4318).

  • +
  • Tree conflicts flagged by svn merge cannot be automatically + resolved yet. This will be addressed in a future release.

  • +
+ +
+ +
+

Automatic reintegration merge (--reintegrate option deprecated) + +

+ +

During merges which merge all eligible revisions from another +branch, Subversion 1.8 will automatically decide whether or not +the merge is reintegrating a branch. +Therefore, reintegrating a branch does no longer require the +--reintegrate option for correct operation.

+ +

The --reintegrate option of svn merge is now +deprecated and its use is discouraged. To reintegrate a branch, +have a clean working copy of trunk and run the following command +in its top-level directory:

+ +
$ svn merge ^/branches/my-branch
+ +

This merge will still perform similar sanity checks which +svn merge --reintegrate performed in earlier releases: +

    +
  • The working copy must not be a mixed-revision working copy.
  • +
  • The working copy must not have switched subtrees.
  • +
  • There must be no gaps in revision ranges merged from the reintegration +target (e.g. the trunk) to the reintegration source (i.e. the branch to be +reintegrated).
  • +

+ +

If any of these conditions are detected, the merge is aborted and +the necessary steps must be taken to fix the problem before the +branch can be reintegrated. +In contrast to a --reintegrate merge, an automatic reintegration +merge into a working copy with local modifications is allowed.

+ +

Merging to-and-fro between two branches in any order is possible +using the automatic reintegration merge (the "keep-alive dance" is no longer necessary). + +For best results, it is recommended to +always merge all eligible revisions, i.e. not using the +-r or -c options of svn merge. +Merging just a subset of eligible revisions increases the +likelihood of problems during future merges.

+ +

Using --reintegrate in Subversion 1.8 will force a +reintegration merge, whether or not that's the right merge to perform +in the given situation.

+ +
+ +
+

Inherited Properties + +

+ +

Property inheritance provides a mechanism to find the versioned +properties set on the parents of a given working copy or +URL path. Conversely it can be viewed as a mechanism by which a +versioned property set on a path also applies to that path's +children.

+ +

It is important to note that this change does not introduce +any such thing as an "inheritable" property. Any versioned property, +explicitly set on a path, can be interpreted as inheritable by that +path's children. No changes have been made to the ways in which +properties are set or what valid property names and values are permitted. +Nor does this change grant access to parent paths which a user doesn't +have read access to. If a user has no read access to a parent path, he +cannot inherit properties from that parent.

+ +

Other than the changes detailed below, the only user visible changes resulting from inheritable +properties are to the svn proplist, svn propget, +svnlook proplist, and svnlook propget subcommands +when used with the new --show-inherited-props option.

+ +

This new option finds the explicit properties set on a given path's +parent(s) lists them prior to the explicit properties on the target path +itself. For example:

+ +
+   > svn propget -vR --show-inherited-props tsvn:logwidthmarker ^/subversion/trunk/subversion/po
+   Inherited properties on 'https://svn.apache.org/repos/asf/subversion/trunk/subversion/po',
+   from 'https://svn.apache.org/repos/asf/subversion/trunk':
+     tsvn:logwidthmarker
+       78
+   Properties on 'https://svn.apache.org/repos/asf/subversion/trunk/subversion/po':
+     tsvn:logwidthmarker
+       80
+
+ +

If a working copy is the target, some properties may be inherited +from the working copy and some may be inherited from repository parent +paths not present in the working copy. These are shown as inherited +from a URL:

+ +
+   > svn propget -vR --show-inherited-props tsvn:logwidthmarker po-wc\de.po
+   Inherited properties on 'po-wc\de.po',
+   from 'https://svn.apache.org/repos/asf/subversion/trunk':
+     tsvn:logwidthmarker
+       78
+   Inherited properties on 'po-wc\de.po',
+   from 'po-wc':
+     tsvn:logwidthmarker
+       80
+
+ +

The output with the --xml option also returns inherited +properties, wrapping them in inherited_property rather than +property tags:

+ +
+   > svn propget --show-inherited-props --xml tsvn:logwidthmarker ^/subversion/trunk/subversion/po
+   <?xml version="1.0" encoding="UTF-8"?>
+   <properties>
+   <target
+      path="https://svn.apache.org/repos/asf/subversion/trunk">
+   <inherited_property
+      name="tsvn:logwidthmarker">78</inherited_property>
+   </target>
+   <target
+      path="https://svn.apache.org/repos/asf/subversion/trunk/subversion/po">
+   <property
+      name="tsvn:logwidthmarker">80</property>
+   </target>
+   </properties>
+
+ +

The svnlook proplist and svnlook propget subcommands +also support the new --show-inherited-props option. The output +is similar to svn proplist --show-inherited-props and +svn propget --show-inherited-props except that the paths are not +working copy paths or URLs, but absolute repository paths:

+ +
+   > svnlook propget asf-repos-mirror tsvn:logwidthmarker /subversion/trunk/subversion/po \
+       --show-inherited-props -v
+   Inherited properties on '/subversion/trunk/subversion/po',
+   from '/subversion/trunk':
+     tsvn:logwidthmarker
+       78
+   Properties on '/subversion/trunk/subversion/po':
+     tsvn:logwidthmarker
+       80
+
+ +

Subversion working copies maintain a cache of the properties that the +root of the working copy inherits from its parent(s) in the repository. +This cache is updated each time you checkout, update, or switch a working +copy. This cache allows the working copy to access properties inherited +from the repository without contacting the repository.

+ +

For the full details about inheritable properties see the +design wiki. Some of this wiki is intended for Subversion developers +and will be of little interest to most users. If you fall into the latter +group you can focus on these particular sections:

+ + + +
+ +
+

Repository Dictated Configuration (For auto-props and ignores) + +

+ +

Two new Subversion reserved properties, svn:auto-props +and svn:global-ignores make use of the new +inherited properties feature to provide additional +configuration information that overrides/extends some of the settings +found in the user's runtime configuration. The svn:auto-props +property overrides/extends the auto-props configuration setting. +The svn:global-ignores property extends the +global-ignores configuration setting as well as the +svn:ignore property.

+ +

The format of svn:auto-props property values +are the same as for the auto-props runtime configuration. +The format of svn:global-ignores property values are the +same as for the global-ignores runtime configuration.

+ +

Both properties work just like their analogs in the runtime +configuration with two exceptions:

+ +
    +
  • The new properties only effect the subtrees rooted at the path + on which the property is set. Thus a given path may be affected + by multiple svn:auto-props or svn:global-ignores + properties set on different parents of that path.
  • +
  • The svn:auto-props property is not tied to the + enable-auto-props runtime configuration option. So even + if you have enable-auto-props=no set in your configuration + or via the --config-option option, svn:auto-props + are still applicable. Note however, that exactly like the runtime + configuration and svn:ignore property, both the + svn:auto-props and svn:global-ignores properties + can be disregarded with the --no-ignore and + --no-auto-props options respectively.
  • +
+ +

When multiple svn:global-ignores properties apply to a +path, then the different values are appended to any runtime +global-ignores in effect and the value of any svn:ignore +property that applies to the path.

+ +

Patterns defined in svn:auto-props property +override any identical patterns in the auto-props runtime +config. When multiple svn:auto-props properties +apply to a file, the pattern from the nearest inheritable property takes +precedence. See this section of design wiki for a full explanation.

+ +

The design wiki for the repository dictated configuration feature was +originally written for developers, but will prove useful to any repository +administrator who wants to use the feature.

+ +
+ +
+

In-memory password caching via GnuPG Agent (Unix client) + +

+ +

Subversion 1.8 allows the use of the GnuPG Agent (gpg-agent) daemon +to temporarily store Subversion passwords in memory.

+ +

This feature does not use PGP to encrypt passwords on disk! +Rather, it caches passwords in memory (in plaintext) instead of saving +them to disk.

+ +

To take advantage of this password cache, you'll need Subversion binaries +built with gpg-agent support (which is the default on UNIX-like systems), +the gpg-agent itself, and a suitable pinentry program which the gpg-agent +will use to ask the user for the password. +The gpg-agent must be running, and the Subversion client will +need the GPG_AGENT_INFO and GPG_TTY environment +variables set up correctly. +See this page for more information about +running the gpg-agent.

+ +

Cached passwords will persist in memory until the agent process +is terminated, its configured time-to-live threshold is reached, or a +HUP signal is sent to the daemon using the UNIX kill(1) utility.

+ +

Communication to the gpg-agent happens over a UNIX socket, which is +located in a directory which only the user running Subversion can access. +However, any program the user runs could access this socket and get +the Subversion password if the program knows the "cache ID" Subversion +uses for the password.

+ +

The cache ID is very easy to obtain for programs running as the same user. +Subversion uses the MD5 of the realmstring as cache ID, and these checksums +are also used as filenames within ~/.subversion/auth/svn.simple. +Unlike with GNOME Keyring or KDE Wallet, the user is not prompted for +permission if another program attempts to access the password.

+ +
+

WARNING: Therefore, while the +gpg-agent is running and has the password cached, the password cache +is no more secure than a file storing the password in plaintext.

+
+ +
+ +
+

FSFS size and performance enhancements + +

+ +

Subversion 1.8 introduces a number of improvements that can reduce +the size of FSFS repositories, the total number of files on disk, the +I/O overhead and gives the user fine-grained control over all of that. +Some of these changes require a format bump, others are backward-compatible. +

+ +
+

FSFS format bump + +

+ +

The default repository format created by svnadmin create is +now FSFS version 6 which is not accessible by Subversion 1.7 or older. +Older repository formats remain fully supported by Subversion 1.8 but +will not support revprop packing. +To create FSFS repositories compatible with Subversion 1.6 and 1.7, use +the --compatible-version 1.6 parameter.

+ +

You may use svnadmin upgrade to upgrade existing repositories. +However, to fully benefit from the latest repository size reductions, +it is recommended to create a new repository, adjust its settings and then +dump/load or svnsync the contents into it. +

+ +
+ +
+

Packing revision properties + +

+ +

Format 6 repositories will not only +pack the revision files but also the revision property files. Upgrading +existing packed repositories will automatically pack existing revision +properties. Using default settings, this will reduce the number of +revprop files to less than 10 per 1000 revisions in typical usage +scenarios.

+ +

The db/fsfs.conf file allows you to fine-tune the +revprop packing strategy. See the comments in that file for a +detailed description of the available options. Please note that no +change in this configuration file will affect any existing data. +Moreover, upgrading repositories will not extend the existing +configuration file, i.e. the server will use the default settings +unless the new options are added explicitly.

+ +

It is recommended to also activate revprop caching when you use revprop packing. Otherwise, access +to timestamps etc. will suffer significant processing overhead.

+ +
+ +
+

Caching revision properties + +

+ +

Many operations will access revision properties to e.g. retrieve +the commit time stamp. Therefore, thousands of revision property files +may need to be read during a checkout. The UI to enable the revprop +cache is similar to that for the other caches: svnserve +now accepts the --cache-revprops yes parameter. For +mod_dav_svn, the same looks like this in httpd.conf +

+ +
+<IfModule dav_svn_module>
+    SVNCacheRevProps on
+</IfModule>
+
+ +

With revision property packing +enabled, revprop caching allows you to read hundreds of revprops +at once from a single file. This can give a significant performance +boost to e.g. svn log .

+ +
+ +
+

Directory and property storage reduction + +

+ +

For each changed node in a FSFS repository, new versions of +all parent directories will be created. Larger repositories tend +to have relatively deep directory structures with at least one +level (branches, modules or projects) having tens of entries. +The total size of that data may well exceed the size of the actual +change. Subversion 1.8 now supports directory deltification +which eliminates most of that overhead.

+ +

In db/fsfs.conf, you may now enable and disable +directory deltification at any time and these settings will be +applied in new revisions. For completeness, node properties may +now be deltified as well although the reductions in repository +size will usually be minimal.

+ +
+

By default, directory and property deltification are disabled. + You must edit db/fsfs.conf to enable these features. The reason + is that deltification may amplify I/O in certain situations. To minimize + that effect, enable the txdelta cache.

+
+ +

Also, db/fsfs.conf now allows for fine-grained control over +how deltification will be applied. +See the comments in that file for a detailed description of the +individual options. +

+ +

Another optimization in 1.8 is that node properties with the +same contents will only be stored once and then merely referenced. +This not only slightly reduces the size of the repository but greatly +improves cache effectiveness and may reduce I/O significantly. +

+ +

It's backward compatible! Please note that the mechanism +to read deltified data is the same for file contents as for directories +and properties. Hence, Subversion 1.6 and 1.7 will be able to read +them but will always write new revisions without that optimization. +It is therefore perfectly legal to create a pre-1.8-compatible +repository in 1.8, to enable various deltification options, to dump/load into that new repository using 1.8 tooling and to +finally use the repository with a 1.6 or 1.7 server. +

+ +
+ +
+

Rep-sharing within revisions + +

+ +

When representation sharing has been enabled, Subversion 1.8 +will now be able to detect files and properties with identical contents +within the same revision and only store them once. This is a common +situation when you for instance import a non-incremental dump file or +when users apply the same change to multiple branches in a single commit. +

+ +
+ +
+ +
+

In repository authz + +

+ +

Subversion 1.8 allows authz files to be stored inside a Subversion +repository. This allows you to employ the versioning features of +Subversion for the configuration of the path-based authorization +feature. You need not store the authz file in the same repository as +the one to which its rules are being applied. However, the server +which uses the authz file does require filesystem access to the +repository in which that file is stored. Administrators should +consider that one benefit of having the authz file stored in the same +repository as the one to which its rules are being applied allows the +authz file to be replicated by svnsync along with the rest +of the data in the repository, simplifying administration of mirrored +repositories.

+ +

When specifying the location of the authz file to Apache HTTP +Server or svnserve, there are now four formats an administrator may +use:

+ +
    +
  1. Absolute path to a file (outside of a repository): + /path/to/file or C:\path\to\file
  2. +
  3. Relative path to a file (outside of a repository): + path/to/file or path\to\file
  4. +
  5. Absolute URL to file in repository: + file:///path/to/repo/file
  6. +
  7. Relative URL to file in a repository: + ^/file
  8. +
+ +

The first two formats are those that were already supported in +versions prior to 1.8; the latter two are the new formats.

+ +

The new absolute URL format is similar to what you might use +with svn cat to list the contents of a file versioned in a +local repository. (Note that at this time, support exists +for file:// URLs only, not for other Subversion URL flavors +such as http://, svn://, and so on.)

+ +

The relative URL syntax should also look familiar, as it mimics +the relative URL syntax that the command-line client recognizes. +When parsing path specifications in this format, Subversion simply +ignores the leading ^/ and looks for authz file at the +remaining path in the repository which is being accessed.

+ +

Apache HTTP Server accepts all four formats for both the +AuthzSVNAccessFile and AuthzSVNReposRelativeAccessFile +configuration directives. The only difference between these two +directives is the root path for the "relative path to a file outside a +repository" format.

+ +
+

WARNING: Unlike authz files +stored on the server's local disk, authz files stored in the repository +are accessible via Subversion clients just like any other file in the +repository. If you wish to protect the contents of the authz file you +should configure appropriate access restrictions for it in the +applicable authz file (which could potentially be the same file!).

+
+ +
+

WARNING: As with other +versioned files, Subversion servers do not validate the internal +syntax of a versioned authz file in any way. Administrators may wish +to set up a pre-commit hook script to validate that the authz file is +well-formed and/or the committing user has not removed all permissions +to edit the file. If permissions have been removed to edit it via the +network server(s) you can of course always edit it via a local +(file://) checkout since ra_local does not observe path based +permissions. See the validate-files.py hook script and its +related configuration files in Subversion's tools/hook-scripts +for examples of how to validate a versioned authz file's syntax and +specific permissions.

+
+ +
+ +
+

New tools and utilities + +

+ +
+

svn-bench benchmarking client + +

+ +

Identifying bottlenecks in your Subversion infrastructure may be +difficult because client-side influences (virus scanners, slow disks +etc.) tend to mask other limitations. Therefore, Subversion 1.8 +introduces a very lightweight client that skips most of that local +processing.

+ +

svn-bench provides commands similar to the standard +command line interface, adding a null- prefix to them. +Currently implemented are null-export, null-list +and null-log. They support most of the parameters of their +standard command counterparts.

+ +
+$ time svn-bench null-export svn://localhost/tsvn_repos/trunk
+            179 directories
+          3,661 files
+     84,902,674 bytes in files
+         20,560 properties
+        315,031 bytes in properties
+
+real  0m0.185s
+user  0m0.128s
+sys   0m0.040s
+
+ +

By running the client close to or directly on the server machine, +you will be able to determine the raw server speed and compare that +to what the client-side is seeing.

+ +
+ +
+

fsfs-stats repository statistics + +

+ +

This server-side tool will read a whole format 4 (Subversion 1.6) +or newer repository and print out various statistics on the contents +of the rev and pack files in it. It starts of with very general +information and then breaks it down into various sub-demographics. +The statistics include: + +

    +
  • Total repository size bytes
  • +
  • Number of revisions and changes
  • +
  • Sum of original and deltified file sizes
  • +
  • Sum of original and deltified directory sizes
  • +
  • Structural overhead due to node revisions, change lists etc.
  • +
  • Effectiveness of representation sharing
  • +
  • Paths and revisions of the 64 largest single changes
  • +
  • By file extension: Number of changes, total file size and total + internal representation size
  • +
  • Histograms on the above
  • +
+

+ +

Administrators may use this information to decide whether directory +deltification should be enabled (ratio of directory representation +vs. file representation sizes) or whether commit policies might to +be revised (e.g. large .zip files accout for most of the repository). +Some of the data, however, is useful for performance analysis by SVN +developers only.

+ +
+$ fsfs-stats /repositories/wesnoth_org 500 | gedit &
+
+ +

fsfs-stats takes a local path to the repository root and +an optional cache size parameter. The latter is in MBytes and speeds +up the analysis of large repositories. Because the tool's output may +be up to a 1000 lines of text, you may want to redirect it to some file +or application.

+ +
+

Note that the 32 bit version of this tool may fail on repositories +with millions of changes or with revision / pack files larger than 4 GB. +Use a 64 bit executable instead for those repositories.

+
+ +
+ +
+ +
+ +
+

Enhancements and Bugfixes + +

+ + + +
+

Improved conflict resolution + +

+ +
+

Conflicts are now always postponed during updates and merges + +

+ +

The svn update, svn switch, and svn merge +commands line client now always postpone conflicts. Once the operation has +completed, the interactive conflict resolver is automatically run on paths +which received conflicts during the operation, which will either run in +interactive mode or perform conflict resolution based on the value of +the --accept option, if given.

+ +

This approach has the advantage that the connection to the server +is not held open while interactive conflict resolution is performed. +In Subversion 1.7, the connection could time out if the user spent +too much time resolving a conflict (see +issue #3846).

+ +
+ +
+

'svn resolve' can resolve conflicts interactively + +

+ +

The svn resolve command does not require the --accept +option anymore. If invoked without any arguments, svn resolve +will now perform interactive conflict resolution for any conflicted +paths within the current working directory.

+ +
+ +
+

Built-in file merge tool for interactive conflict resolution + +

+ +

The command-line client now has a built-in file merge tool which +merges any non-conflicting changes automatically and asks the user +what to do about each individual merge conflict.

+ +

The built-in file merge tool can be invoked from the interactive +conflict resolution prompt by choosing the (m) merge option. +It displays conflicting file sections in a side-by-side view and +offers various ways of resolving the conflict, as shown below:

+ +
+$ svn update
+Updating '.':
+C    subversion/svn/file-merge.c
+Updated to revision 1358165.
+Summary of conflicts:
+  Text conflicts: 1
+Conflict discovered in file 'subversion/svn/file-merge.c'.
+Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
+        (mc) mine-conflict, (tc) theirs-conflict,
+        (s) show all options: m
+Merging 'subversion/svn/file-merge.c'.
+Conflicting section found during merge.
+(1) their version (at line 298)       |(2) your version (at line 391)        
+--------------------------------------+--------------------------------------
+  if (buf->len >= 2 &&                |  if (buf->len > 1)                   
+      buf->data[buf->len - 2] == '\r' |    {                                 
+      buf->data[buf->len - 1] == '\n')|      if (buf->data[buf->len - 2] == '
+    svn_stringbuf_chop(buf, 2);       |        svn_stringbuf_chop(buf, 2);   
+  else if (buf->len >= 1 &&           |    }                                 
+           (buf->data[buf->len - 1] ==|  else if (buf->len > 0)              
+            buf->data[buf->len - 1] ==|    {                                 
+    svn_stringbuf_chop(buf, 1);       |      if (buf->data[buf->len - 1] == '
+                                      |        svn_stringbuf_chop(buf, 1);   
+                                      |    }                                 
+--------------------------------------+--------------------------------------
+Select: (1) use their version, (2) use your version,
+        (e1) edit their version and use the result,
+        (e2) edit your version and use the result,
+        (eb) edit both versions and use the result,
+        (p) postpone this conflicting section leaving conflict markers,
+        (a) abort file merge and return to main menu: 
+
+
+ +
+ +
+

Checkout and update download pristine file data just once + +

+ +

Subversion keeps a cache of pristine copies of files in the +working copy's meta data area inside the .svn directory. +Before Subversion 1.8, pristine data was always downloaded from +the server even if the same data already existed in the cache.

+ +

Subversion 1.8 avoids downloading pristine content that is already +present in the cache, based on the content's SHA1 or MD5 checksum. +This results in more efficient use of network throughput in cases where +a lot of files in the working copy share the same content (for example, +if a single working copy contains multiple branches).

+ +
+ +
+

Administration command-line tools improvements (server) + +

+ +
+

'svnadmin hotcopy' can now operate incrementally (FSFS only) + +

+ +

The svnadmin hotcopy command now supports incremental +operation, triggered by the new --incremental option.

+ +

In prior releases of Subversion, svnadmin hotcopy refused +to copy over an existing destination repository, and always copied +the entire repository. For large repositories, performing a hotcopy +could take several hours, preventing an efficient backup process.

+ +

In incremental hotcopy mode, revision data which has already been +copied from the source to the destination repository will not be +copied again. svnadmin hotcopy --incremental will only copy +new revisions, and revisions which have changed in size or had their +modification time stamp changed since the previous hotcopy operation.

+ +

Up to now, svnsync or svnadmin dump --incremental +were the only alternatives for incremental repository backup. However, +these commands need to perform additional processing while transforming +revision data into an intermediate format before creating revision +files in the destination repository. Performance of svnadmin +hotcopy is only limited by disk I/O.

+ +

Incremental hotcopy is not supported for BDB repositories. +See issue 4081 for more information.

+ +
+

Using general-purpose incremental backup tools, such as +rsync, with Subversion repositories +is dangerous if the repository can receive commits while the backup +tool is running. The resulting copy might end up being corrupt because +general-purpose backup tools do not know anything about consistency +requirements of Subversion repositories. It is recommended to use +incremental hotcopy instead. Alternatively, if network support is +required for the backup procedure, svnsync should be used. +There is also a new svnadmin freeze command +which allows third-party tools to access a live repository safely.

+
+ +
+ +
+

'svnadmin load' now supports the --revision option + +

+ +

svnadmin load now supports the --revision +(-r) option, which causes it to only load revisions from +the dump stream within the specified revision number range.

+ +
+ +
+

New 'svnadmin lock' and 'svnadmin unlock' commands + +

+ +

The new svnadmin lock and svnadmin unlock commands +can be used to lock and unlock paths in the repository directly, +without requiring a working copy for use with svn lock or +svn unlock.

+ +
+ +
+

New 'svnadmin freeze' command + +

+ +

The new svnadmin freeze command can be used to run an arbitrary +program while preventing concurrent commits to the repository. The program +is invoked by svnadmin with a provided parameter list. This can +be used to safely use third-party backup tools on a live repository:

+
+$ svnadmin freeze /svn/my-repos rsync -av /svn/my-repos /backup/my-repos
+
+ +

The above will obtain a write lock on the my-repos repository +to prevent concurrent commits, and run +rsync to back up the repository. +Clients trying to commit concurrently will wait until the write lock +becomes available again. If the command takes too much time clients +trying to commit might time out. It is recommended to run commands +which complete very quickly, such as a command to trigger creation +of a filesystem snapshot.

+ +
+ +
+

'svndumpfilter' now supports dump files with deltas + +

+ +

svndumpfilter can now filter dump files containing +deltas, as generated by svnadmin dump --deltas.

+ +
+ +
+

svnauthz can print user's access to a path in a repository + +

+ +

svnauthz (formerly known as svnauthz-validate) +has an 'accessof' subcommand that can print or test what the +permissions would be in a given circumstance, allowing you to validate that +your changes have effected the permissions that you intended.

+ +

svnauthz accessof supports --username, +--repository, and --path arguments. +When these are passed, it prints no, r, +or rw depending on what access the given username has: +none, read-only, or read-write.

+ +
+ +
+

'svnlook diff' improvements + +

+ +

svnlook diff now supports the following new options +(analogous to svn diff): +

    +
  • --ignore-properties suppresses output of property changes
  • +
  • --properties-only shows only property changes
  • +
  • --diff-cmd ARG use ARG as diff command
  • +
+

+ +
+ +
+ +
+

Support for high-speed networks in 'svnserve' + +

+ +

If your server has a 10 Gbit/s or faster network connection, the +multi-stage data copying from Subversion's caches to the network stack +plus frequent status checks become a bottleneck. Today, most clients +won't be able to generate enough aggregated traffic to make this an +issue and an 8-core server should be able to send about 40Gb/s at 100% +CPU load. Future clients may be able, however, to process 1Gb or even +10Gb per second and to create significant server loads. +

+ +

When the server is given the --client-speed N parameter, +it will assume that most clients are able to process data at rates of +N Mbit/s; N being a non-negative integer. Future server releases may +apply different strategies for different ranges of client bandwidth +to optimize the network performance. In 1.8 and if N>=1000, the +server will take various shortcuts to reduce internal processing overhead. +On the downside, a very slow or hanging client may degrade the server +performance for other clients as well. Setting N to values above 100.000 +is legal but will often result in a net throughput loss. +

+ +

Note: This option will have little effect in 1.8 +without configuring large fulltext caches. +

+ +
+ +
+

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.8.0 section in the CHANGES file +for a complete list.

+ + + +
+

'svn commit' can now recurse into externals + +

+ +

The svn commit command supports a new --include-externals +option, which causes it to commit changes within externals in the current +working copy, in addition to the changes in the current working copy. +This works by implicitly adding all externals within the commit target +to the list of commit targets.

+ +
+ +
+

'svn diff' improvements + +

+ +

The svn diff command can compare arbitrary files with one +another, using the invocation:

+
+$ svn diff --old foo.c --new bar.c 
+Index: bar.c
+===================================================================
+--- bar.c       (.../foo.c)     (working copy)
++++ bar.c       (.../bar.c)     (working copy)
+@@ -1,6 +1,6 @@
+ #include <stdio.h>
+ int main()
+ {
+-       printf("Hello world!\n");
++       printf("Good bye world!\n");
+        return 0;
+ }
+
+ +

This works with any combination of versioned and unversioned files. +Comparing arbitrary directories is also supported, in which case the +directories are walked recursively and files within them are compared.

+ +

svn diff also supports the following new options: +

    +
  • --ignore-properties suppresses output of property changes
  • +
  • --properties-only shows only property changes
  • +
  • --patch-compatible produces output compatible with third party patch programs
  • +
+

+ +

svn diff --summarize is extended to match all scenarios that +svn diff supports, including the new arbitrary file diff.

+ +
+ + + + + +
+ +
+

Custom keyword definitions + +

+ +

Subversion now supports the definition of custom keywords, which can be +defined using a special syntax within the svn:keywords property.

+ +

For example, MyKeyword=%r%_%a%_%P defines a keyword called +"MyKeyword" which contains the number of the last-changed +revision, the author of that revision, and the file's path in the +repository, each separated by one space character. +Once a custom keyword has been defined it can be used within the +file like any other keyword: $MyKeyword$

+ +

The svn help propset command lists the known format codes +which can be used in custom keyword definitions, which are also shown +in the table below. Any characters in the keyword definition which are +not format codes are expanded literally, i.e. a keyword such as +MyAuthor=Author:%_%a will expand to Author: joe +if the last-changed revision's author is "joe".

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
%aThe author of the revision given by %r.
%bThe basename of the URL of the file.
%dShort format of the date of the revision given by %r.
%DLong format of the date of the revision given by %r.
%PThe file's path, relative to the repository root.
%rThe number of the revision which last changed the file.
%RThe URL to the root of the repository.
%uThe URL of the file.
%_A space (keyword definitions cannot contain a literal space).
%%A literal '%'.
%HEquivalent to %P%_%r%_%d%_%a.
%IEquivalent to %b%_%r%_%d%_%a.
+ +

Note that keyword expansions which exceed 255 bytes in length are +truncated, and keywords with names that exceed 255 bytes are not expanded.

+ +
+ +
+

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

+ +

There are too many new and revised APIs in Subversion 1.8.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.

+ +

A small number of APIs 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.

+ +
+ +
+

Bug fixes (client and server) + +

+ +

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

+ +
+ + +
+

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.8.0 section in the CHANGES +file for a complete list.

+ +
+

'svn mergeinfo' now honors the -r option + +

+ +

The svn mergeinfo command now honors the -r option. +While the option has always been accepted and documented, it was silently +ignored, such that svn mergeinfo always operated on the entire +history of the repository.

+ +

In Subversion 1.8, the -r option restricts the output of +svn mergeinfo to the specified revision range, which is useful +when determining whether or not a given revision, or range of revisions, +is eligible for merging, or whether it has already been merged. +In the following example, r682012 has not been merged from trunk yet, +while r26112011 has already been merged:

+
+  $ svn mergeinfo --show-revs=eligible -r 682012 ^/trunk
+  r682012
+  $ svn mergeinfo --show-revs=merged -r 26112011 ^/trunk
+  r26112011
+  $
+
+ +
+ +
+ +
+

Hook scripts improvements (server) + +

+ +
+

Hook script environment variables are now configurable + +

+ +

In Subversion 1.7 and earlier, hook scripts always run in an empty +environment. If environment variables are needed hook scripts had to +configure them manually. Subversion 1.8 supports configuration of hook +script environment variables on a per-server or per-repository basis.

+ +

The hook script environment is configured via a new configuration file +located either at conf/hooks-env in a repository, or at a +server-wide location specified in svnserve.conf (using the +new hooks-env option) or httpd.conf (using the +new SVNHooksEnv option).

+ +

The hook script environment configuration file uses a format similar +to that of other Subversion configuration files:

+
+### This file is an example hook script environment configuration file.
+### Hook scripts run in an empty environment by default.
+### As shown below each section defines environment variables for a
+### particular hook script. The [default] section defines environment
+### variables for all hook scripts, unless overridden by a hook-specific
+### section.
+
+### This example configures a UTF-8 locale for all hook scripts, so that 
+### special characters, such as umlauts, may be printed to stderr.
+### If UTF-8 is used with a mod_dav_svn server, the SVNUseUTF8 option must
+### also be set to 'yes' in httpd.conf.
+### With svnserve, the LANG environment variable of the svnserve process
+### must be set to the same value as given here.
+[default]
+# LANG = en_US.UTF-8
+
+### This sets the PATH environment variable for the pre-commit hook.
+# [pre-commit]
+# PATH = /usr/local/bin:/usr/bin:/usr/sbin
+
+ +
+ +
+

mod_dav_svn now supports hook script UTF-8 input/output + +

+ +

As documented in issue #2487, hook scripts run on a mod_dav_svn-based +Subversion server previously had problems with non-ASCII input and output. +Because Apache HTTPD modules always run in the "C" locale, +which is restricted to ASCII, mod_dav_svn usually failed +trying to process non-ASCII characters.

+ +

Among other problems, this prevented pre-lock and +post-unlock hook scripts from operating on paths containing +non-ASCII characters, and prevented non-ASCII error output from +start-commit and pre-commit hooks from reaching +SVN clients.

+ +

Subversion 1.8 addresses these problems with a new SVNUseUTF8 +option for mod_dav_svn. If this option is set, mod_dav_svn +assumes that all hook script input/output is encoded in UTF-8. +This is always the case for paths passed to hook scripts, since Subversion +uses UTF-8 internally for all paths. If this option is set, hook scripts +must write error messages to stderr in UTF-8. Because ASCII is a +subset of UTF-8 existing hook scripts will continue to work unmodified.

+ +

For best results, hook scripts should use a UTF-8 locale if the +SVNUseUTF8 option is active. It is recommended to configure +a UTF-8 locale using the hook script environment configuration file.

+ +
+ +
+

start-commit hook invocation point changed + +

+ +

Prior to this release, the start-commit hook script was +invoked by Subversion just prior to the creation of the commit +transaction. An errorful return from the hook would be marshaled back +to the client without the commit transaction having ever been created. +A successful return would permit the creation of the commit +transaction, and allow the commit process to proceed as expected. +Administrators generally employed the start-commit hook to +immediately deny all commits to a repository, as the amount +of information available to the hook by which to do so +conditionally was pretty slim.

+ +

Beginning with Subversion 1.8, the start-commit hook is +invoked immediately after Subversion creates the commit +transaction and sets its initial properties. This +allows start-commit implementations to examine the commit +transaction's properties (such as the revision log message and the new +ephemeral transaction properties) +when deciding whether or not to allow the commit to proceed. +Subversion will abort the created transaction upon detecting an +errorful return from the hook and will, of course, still marshal that +error condition back to the client.

+ +

This change empowers administrators to disallow certain commits via +the start-commit hook rather than doing so much later — +after the client's changes are transmitted across the network — +in the pre-commit hook. Imagine the frustration of a user +who has endured the lengthy upload of 2 Gb of commit data only to have +his or her commit bounced because of an insufficiently formatted log +message! These changes to start-commit allow the go/no-go +decision on such a commit to be made before that large commit payload +is transmitted across the wire.

+ +

Note: Subversion does not require that commit +transaction properties (such as the revision log message) be attached +to the transaction as part of its initialization. As such, some +clients will still not provide that information to the server until +after the start-commit hook has been invoked. Here is a list +of such clients we are aware of:

+ +
    +
  • Pre-1.8 clients communicating via HTTP
  • +
  • Clients communicating via HTTP when mod_dav_svn's + "SVNAdvertiseV2Protocol" option has been set to "off"
  • +
+ +

Administrators should consider modularizing the tests that their +hooks perform on transaction properties, invoke those tests from both +the start-commit and pre-commit hook scripts.

+ +
+ +
+

post-commit hook grows txn-name argument + +

+ +

The post-commit hook has grown a txn-name argument as the +third positional argument (argv[3]). This argument is the name of the +transaction that has become the revision triggering the post-commit +hook; it is the same as the second positional argument to the +pre-commit, and thus enables the pre-commit and +post-commit hooks to easily transfer state between them.

+ +

Generically, if the pre-commit hook makes an expensive computation +against the would-be-revision, it can store the result of that computation in a +persistent hash keyed by the transaction name, which the post-commit +hook will use to avoid re-doing the computation. One concrete usage of this +would be to implement a pre-commit hook that tests compilability only, while +a post-commit hook or a continuous integration tool runs more thorough tests +--- on the binaries built at pre-commit, without having to rebuild them +itself.

+ +
+ +
+

Commit transactions now carry client information + +

+ +

Subversion 1.8 clients communicating to 1.8 servers +(via http[s]: or svn:) will now attach "ephemeral +transaction properties" to commit transactions which carry metadata +considered useful to server-side hook scripts. These special +properties are set on the commit transaction as early as possible +(generally prior to the invocation of +the start-commit hook, but +certainly prior to the invocation of the pre-commit hook), +and then automatically removed by Subversion just prior to the commit +transaction being promoted to a new revision.

+ +

Currently, the following ephemeral transaction properties are +available to hook scripts for examination:

+ +
    +
  • svn:txn-user-agent - carries the "user agent" + string which describes the committing client program. (Developers + of third-party clients which link against the Subversion libraries + may modify the customizable portion of this string by implementing + the get_client_string() RA callback API which was + introduced in Subversion 1.5.)
  • +
  • svn:txn-client-compat-version - carries the + Subversion library version string with which the connecting client + claims compatibility. (For Subversion clients which use the + Apache Subversion C API and libraries, this version is precisely + the version of those libraries.)
  • +
+ +

Note: Administrators who deem the information +carried in these properties to be of long-term value may of course log +the information as they see fit. For example, such an administrator +may wish to use a pre-commit hook script +to copy the values of those +properties to new, custom transaction properties (which +do not have names within the reserved svn: +namespace, of course!) for long-term storage associated with the +commit. An example hook script that renames the revision properties from +svn:txn-* to svn:revision-* is +distributed with Subversion itself.

+ +
+ +
+ +
+

New svnpubsub framework for pushing post-commit notifications + (server) + +

+ +

svnpubsub is a daemon that pushes post-commit notifications to +clients in streaming JSON over HTTP. The notifications are typically +pushed to the daemon by a post-commit hook. The code lives in +the tools/server-side/svnpubsub directory of the source tree.

+ +

A typical notification looks like this (newlines added for readability):

+ +
+% curl -i http://svn.foo.org:2069/commits
+{"commit": {
+   "type": "svn",
+   "format": 1,
+   "id": 1334845,
+   "repository": "13f79535-47bb-0310-9956-ffa450edef68",
+   "changed": {"httpd/site/trunk/content/dev/": {"flags": " U "}},
+   "committer": "joes",
+   "log": "spacing",
+   "date": "2012-05-07 00:30:25 +0000 (Mon, 07 May 2012)"}}
+^@
+...
+
+ +

svnpubsub was written by Paul Querna for the ASF Infrastructure Team.

+ +
+ +
+

New SVNMasterVersion Apache HTTP Server configuration directive + +

+ +

Subversion's HTTP protocol continues to mature and expand over time +to support new features or better ways to accomplish things. +Fortunately, Subversion servers and clients happily negotiate which +bits of that protocol they both understand. Unfortunately, WebDAV +proxy configurations can throw this negotiation for a loop, as the +slave server does the negotiating but not necessarily all the +operating. Thus, a Subversion 1.7 WebDAV proxy slave will by default +tell the client that it's okay to use the HTTPv2 protocol, and a Subversion 1.7 or better client will do +so, even if the master server behind the proxy is running +Subversion 1.6 and unable to understand the new protocol.

+ +

When Subversion 1.7 was released, this specific problem was +addressed by providing an Apache HTTP Server configuration +directive — SVNAdvertiseV2Protocol — which allowed +administrators in such a scenario to "dumb down" the communications of +the Subversion 1.7 slave server so that connecting clients would use +the older protocol and, in doing so, not confuse the Subversion 1.6 +master server when requests were proxied to it. As development +continued toward 1.8, though, there where several new features and +protocol changes made which would likewise require a toggle switch +to avoid confusing pre-1.8 WebDAV proxy master servers.

+ +

Rather than exposing a suite of such toggles — some of which +were for behaviors that are entirely specific to the protocol itself +and not tied to any user-visible feature — Subversion 1.8 allows +administrators to simply declare to the slave servers the version of +Subversion which is powering the master server, allowing the slave +servers to enable and disable features as makes sense for that +scenario. Administrators of Subversion deployments which use the +WebDAV write-through proxy feature are strongly encouraged to use the +new SVNMasterVersion httpd.conf directive in all slave server +configurations running Subversion 1.8 or better.

+ +

For example, if your master server is running Subversion 1.7.7, your +Subversion 1.8 slave server's Apache HTTP Server configuration might +contain something like this:

+ +
<Location /svn>
+DAV svn
+…
+SVNMasterURI http://master.svn.company.com/svn
+SVNMasterVersion 1.7.7
+…
+</Location>
+
+ +
+

In the general case, the new SVNMasterVersion directive +supercedes the need for SVNAdvertiseV2Protocol. By declaring +the version of the master server, the slave will assume the default +level of feature support for that server. However, if you have a +master server which can support the HTTPv2 protocol but for +which you've disabled this intentionally, you will need to also +explicitly disable the feature (again, via +the SVNAdvertiseV2Protocol off directive) in your slave +servers as well.

+
+ +
+ +
+

Keyword expansion via DAV repository browser + +

+ +

One of the earliest features of the mod_dav_svn Subversion server +was the ability for users to browse their repositories directly with a +web browser. GET requests issued by browser and aimed at +Subversion directory URLs return a directory listing; those aimed at +file URLs return the file's current contents.

+ +

In Subversion 1.6, we expanded that feature to allow browsing of +historical artifacts in your repository via +new p=PEGREV and r=REV CGI +parameters.

+ +

Now in Subversion 1.8, we've added still another CGI +parameter: kw=1.

+ +
http://host/repos/path?kw=1
+ +

Users who include kw=1 in the query string portion +of GET requests aimed at a versioned file will now be +delivered that file's contents with any Subversion keywords expanded +therein. Because keyword substitution is typically performed by the +Subversion client as part of its working copy administration and +management, this is handy way to get the server to deliver a +keyword-expanded form of your versioned file without the use of a +working copy. Omitting the kw parameter or using something +other than "1" for its value will cause Subversion to use its default +behavior, which is to deliver the file's contents without any keywords +expanded. (NOTE: We reserve the right to recognize new meaningful +values for the kw flag in the future, so please avoid +specifying any value other than "1" when using the parameter at +all.)

+ +

As with client-side keyword expansion, only those keywords which +are explicitly designated for expansion via the svn:keywords +property set on the file itself will be expanded.

+ +
+ +
+

Exclusive SQLite locking of working copies + +

+ +

In the root of every Subversion working copy there is an +SQLite database in the .svn +directory and Subversion clients use this database when accessing the +working copy. By default Subversion uses shared SQLite locking and +this allows simultaneous access to the working copy by multiple +clients with exclusive locks only being held for short periods. The +1.8 command line client can be configured to use exclusive SQLite +locking by setting the following in the .subversion/config +file:

+
+[working-copy]
+exclusive-locking-clients = svn
+
+ +

or by using the command line option --config-option config:working-copy:exclusive-locking-clients=svn.

+ +

This reduces the locking overhead but does mean that only one +Subversion client will be able to access the working copy at a time. A +second client attempting to access a locked working copy will block +for 10 seconds and then get an error. In most cases shared locking is +preferred but if the working copy is on a network disk rather than a +local disk the locking overhead is more significant. When dealing +with large working copies on network disks exclusive locking may give +a significant performance gain, two or three times faster in some +cases.

+ +
+ +
+ +
+

Known issues in the release + +

+ +

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

+ +
+

1.8.0 and chunked Transfer-Encoding + +

+ +

Subversion 1.8.0 has switched from neon +to serf for HTTP access. The Serf-based HTTP access library would +use chunked transfer encoding for most requests. When the +mod_dav_svn Subversion server is fronted by a proxy or reverse proxy +(such as Nginx +prior to 1.3.9) which responds with a 411 Length Required, Subversion +would sometimes either treat this as a fatal error, such as:

+ +
+% svn commit <arguments>
+POST of '/svn/[project name]/!svn/me': 411 Length Required
+
+ +

or

+ +
+svn: E175009: XML parsing failed: (411 Length Required)
+
+ +

and sometimes would fail to notice the failure of the request and issue an +unrelated error, such as:

+ +
+svn: E175004: The PROPFIND response did not include the requested properties
+
+ +

Subversion 1.8.1 fixes this issue by detecting automatically +whether chunked +requests are supported at the set up of a session. This is done +by issuing one additional request at the start of the session.

+ + +
+

Technical details: +A session is often equivalent to calling one svn subcommand (or +one svn_client_* function, for API users). +However several subcommands currently open multiple sessions. The extra +request cost is incurred for each session. A single session may make numerous +TCP connections (usually 2 and never more than 8) and the extra request will +only be made once for all the connections in a session.

+ +

The net effect is that the cost of the additional request may be incurred +multiple times, and thus be more noticeable. For example svn log --diff +ends up opening 2 sessions for every revision in order to request the diff.

+
+ +

We expect that the default configuration of Subversion 1.8.1+ will work well +out of the box for most users. A http-chunked-requests option has been +added to the ~/.subversion/servers (Windows: +%APPDATA%\Subversion\servers file. Users who wish to avoid the +additional request may set that option to yes or no in order +to short-circuit the additional request and avoid making it. We recommend not +to set that option (or to set it to its default value, auto) unless +you have special circumstances which require it (such as an unusually high +latency), and even then to set it only in the config sections of specific +groups and not in the [global] section. See this dev@ list post for an example.

+ + +
+ +
+

mod_dav_svn Maps Requests to Local Filesystem + +

+ +

Prior to Subversion 1.7.12 and 1.8.2 all previous versions of +mod_dav_svn would allow Apache httpd to map requests handled by +mod_dav_svn to the local file system. When this happened httpd would +believe that it was serving a file or directory located at the path that +comprises the URI path appended to the DocumentRoot of the server but +ending at the first path component that does not actually exist on the local +disk. For example if your DocumentRoot was /var/www and you +were accessing /svn/repo/README and /var/www/svn did not +exist then httpd would believe it was serving /var/www/svn, but if +/var/www/svn existed while /var/www/svn/repo did not then +it would believe it was serving /var/www/svn/repo. This had several +undesired side effects.

+ +
    +
  • <Directory> blocks could match requests being served by + mod_dav_svn. This would allow directives applied in these configuration + blocks (most notably access control directives) to be applied.
  • +
  • When using Apache httpd 2.4.x and mod_dir, if a file from the + DirectoryIndex directive existed at the path Apache httpd believed + it was serving then the request would be rewritten to access that file, + which may or may not exist. If the path was the SVNParentPath + then SVN would try to access a repository with the name of the + DirectoryIndex file that was found.
  • +
  • When using the %f variable in your log directives you would log + the path constructed as described above. This was confusing since it was + not the content that was actually served.
  • +
+ +

Starting with Subversion 1.7.12 and 1.8.2 the requests being served by +mod_dav_svn will not be mapped to the local file system and when +logging with the %f variable you will see a "-" +logged. <Directory> blocks will no longer apply to such requests. +Subversion 1.7.14 and 1.8.5 changed this further and the filename for the request +will now be set as svn:/path/to/repo/path/in/repo (e.g. if your repo is at +/var/svn/repo and the request is accessing /trunk/myfile in +the repo then the filename for the request will be set to +svn:/var/svn/repo/trunk/myfile. Note that the svn: prefix will +prevent the filename from matching an actual path on disk since it isn't a +valid path and as such <Directory> blocks will still not apply. +

+ +
+

WARNING:Therefore, if you were +using <Directory> blocks to restrict access to paths served +by mod_dav_svn you will need to adjust your configuration. Since +the local filesystem path was not complete this never would have been very +useful for path based authorization, but it could be misused for simple +things like blocking an IP. These directives must be moved inside the +appropriate <Location> blocks.

+
+ +
+

WARNING:This change may cause checksum +errors with misconfigured httpd servers. Since 1.7.14 and 1.8.5 the filename +in the request record now includes the filename in the repository, there have +been cases of mod_mime interfering with Subversion. Users will see a +svn: E200014: Checksum mismatch error when working with files that +end in .gz if a configuration setting like AddEncoding x-gzip .gz is +in their configuration file and applies to the locations that Subversion is +being served from. This happens because the setting now matches on the +Subversion traffic and sets the Content-Encoding header to specify that the +file has been gziped for transmport without changing the file content. Since +the Subversion client supports gzip content-encoding it decompresses the file +and ends up with the decompressed file which does not match the checksum of the +file it expected. It is possible that this change may cause other filters to +match Subversion requests that would not have in the past and trigger other +similar errors with other httpd configurations.

+
+ +
+ +
+ +
+

Subversion 1.6.x series no longer supported + +

+ +

The Subversion 1.6.x line is no longer supported. This doesn't +mean that your 1.6 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.6.x versions, and will not make any +more 1.6.x bugfix releases.

+ +
+ + +
+ + --- subversion-1.8.8.orig/debian/test.sh +++ subversion-1.8.8/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.8.8.orig/debian/tests/control +++ subversion-1.8.8/debian/tests/control @@ -0,0 +1,3 @@ +Tests: libapache2-mod-svn +Depends: libapache2-mod-svn, apache2, subversion, wget +Restrictions: needs-root allow-stderr --- subversion-1.8.8.orig/debian/tests/libapache2-mod-svn +++ subversion-1.8.8/debian/tests/libapache2-mod-svn @@ -0,0 +1,22 @@ +#!/bin/sh +set -ex + +svnadmin create /var/lib/svn +chown -R www-data: /var/lib/svn +cat > /etc/apache2/mods-available/dav_svn.conf < + DAV svn + SVNPath /var/lib/svn + +EOT +service apache2 restart + +cd $ADTTMP +svn checkout http://localhost/svn +cd svn +echo "Hello, world!" > hello +svn add hello +svn commit -mdep8 + +result=`wget -qO- http://localhost/svn/hello` +test "$result" = "Hello, world!" --- subversion-1.8.8.orig/debian/watch +++ subversion-1.8.8/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