You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/11/27 12:52:46 UTC

svn commit: r1546002 [38/39] - in /subversion/branches/verify-keep-going: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/ contrib/server-side/svnc...

Modified: subversion/branches/verify-keep-going/tools/dev/unix-build/Makefile.svn
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/dev/unix-build/Makefile.svn?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/dev/unix-build/Makefile.svn (original)
+++ subversion/branches/verify-keep-going/tools/dev/unix-build/Makefile.svn Wed Nov 27 11:52:35 2013
@@ -70,9 +70,9 @@ APR_VER		= 1.4.6
 APR_ICONV_VER	= 1.2.1
 GNU_ICONV_VER	= 1.14
 APR_UTIL_VER	= 1.4.1
-HTTPD_VER	= 2.2.22
+HTTPD_VER	= 2.2.26
 NEON_VER	= 0.29.6
-SERF_VER	= 1.2.1
+SERF_VER	= 1.3.2
 SERF_OLD_VER	= 0.3.1
 CYRUS_SASL_VER	= 2.1.25
 SQLITE_VER	= 3071600
@@ -249,7 +249,7 @@ bdb-reset:
 		rm -f $(BDB_OBJDIR)/$(f);)
 
 bdb-clean:
-	-(cd $(BDB_SRCDIR)/build_unix/ && make clean)
+	-(cd $(BDB_SRCDIR)/build_unix/ && env MAKEFLAGS= make clean)
 
 # fetch distfile for bdb
 $(DISTDIR)/$(BDB_DIST):
@@ -272,12 +272,12 @@ $(BDB_OBJDIR)/.configured: $(BDB_OBJDIR)
 
 # compile bdb
 $(BDB_OBJDIR)/.compiled: $(BDB_OBJDIR)/.configured
-	(cd $(BDB_SRCDIR)/build_unix && make)
+	(cd $(BDB_SRCDIR)/build_unix && env MAKEFLAGS= make)
 	touch $@
 
 # install bdb
 $(BDB_OBJDIR)/.installed: $(BDB_OBJDIR)/.compiled
-	(cd $(BDB_SRCDIR)/build_unix && make install)
+	(cd $(BDB_SRCDIR)/build_unix && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -293,7 +293,7 @@ apr-reset:
 		rm -f $(APR_OBJDIR)/$(f);)
 
 apr-clean:
-	-(cd $(APR_OBJDIR) && make clean)
+	-(cd $(APR_OBJDIR) && env MAKEFLAGS= make clean)
 
 # retrieve apr if not present yet
 $(APR_OBJDIR)/.retrieved:
@@ -314,7 +314,7 @@ POOL_DEBUG_FLAG=--enable-pool-debug=all
 endif
 
 # configure apr
-$(APR_OBJDIR)/.configured: $(APR_OBJDIR)/.retrieved
+$(APR_OBJDIR)/.configured: $(APR_OBJDIR)/.retrieved $(BDB_OBJDIR)/.installed
 	cd $(APR_SRCDIR) && ./buildconf
 	cd $(APR_OBJDIR) \
 		&& env CFLAGS="-O0 -g $(PROFILE_CFLAGS)" GREP="`which grep`" \
@@ -327,12 +327,12 @@ $(APR_OBJDIR)/.configured: $(APR_OBJDIR)
 
 # compile apr
 $(APR_OBJDIR)/.compiled: $(APR_OBJDIR)/.configured
-	(cd $(APR_OBJDIR) && make)
+	(cd $(APR_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install apr
 $(APR_OBJDIR)/.installed: $(APR_OBJDIR)/.compiled
-	(cd $(APR_OBJDIR) && make install)
+	(cd $(APR_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -348,7 +348,7 @@ apr-iconv-reset:
 		rm -f $(APR_ICONV_OBJDIR)/$(f);)
 
 apr-iconv-clean:
-	-(cd $(APR_ICONV_OBJDIR) && make clean)
+	-(cd $(APR_ICONV_OBJDIR) && env MAKEFLAGS= make clean)
 
 # fetch distfile for apr-iconv
 $(DISTDIR)/$(APR_ICONV_DIST):
@@ -361,7 +361,8 @@ $(APR_ICONV_OBJDIR)/.retrieved: $(DISTDI
 	touch $@
 
 # configure apr-iconv
-$(APR_ICONV_OBJDIR)/.configured: $(APR_ICONV_OBJDIR)/.retrieved
+$(APR_ICONV_OBJDIR)/.configured: $(APR_ICONV_OBJDIR)/.retrieved \
+	$(APR_OBJDIR)/.installed
 	cd $(APR_ICONV_OBJDIR) \
 		&& env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \
 		$(APR_ICONV_SRCDIR)/configure \
@@ -372,12 +373,12 @@ $(APR_ICONV_OBJDIR)/.configured: $(APR_I
 # compile apr-iconv
 $(APR_ICONV_OBJDIR)/.compiled: $(APR_ICONV_OBJDIR)/.configured
 	(cd $(APR_ICONV_OBJDIR) \
-		&& make CPPFLAGS="-D_OSD_POSIX" CFLAGS="-g -O0 $(PROFILE_CFLAGS)")
+		&& env MAKEFLAGS= make CPPFLAGS="-D_OSD_POSIX" CFLAGS="-g -O0 $(PROFILE_CFLAGS)")
 	touch $@
 
 # install apr-iconv
 $(APR_ICONV_OBJDIR)/.installed: $(APR_ICONV_OBJDIR)/.compiled
-	(cd $(APR_ICONV_OBJDIR) && make install)
+	(cd $(APR_ICONV_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -393,7 +394,7 @@ gnu-iconv-reset:
 		rm -f $(GNU_ICONV_OBJDIR)/$(f);)
 
 gnu-iconv-clean:
-	-(cd $(GNU_ICONV_OBJDIR) && make clean)
+	-(cd $(GNU_ICONV_OBJDIR) && env MAKEFLAGS= make clean)
 	rm -f $(GNU_ICONV_OBJDIR)/lib_encodings.def.diff
 	rm -f $(GNU_ICONV_OBJDIR)/lib_aliases.gperf.diff
 
@@ -453,12 +454,12 @@ $(GNU_ICONV_OBJDIR)/.configured: $(GNU_I
 
 # compile gnu-iconv
 $(GNU_ICONV_OBJDIR)/.compiled: $(GNU_ICONV_OBJDIR)/.configured
-	(cd $(GNU_ICONV_OBJDIR) && make)
+	(cd $(GNU_ICONV_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install gnu-iconv
 $(GNU_ICONV_OBJDIR)/.installed: $(GNU_ICONV_OBJDIR)/.compiled
-	(cd $(GNU_ICONV_OBJDIR) && make install)
+	(cd $(GNU_ICONV_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -490,7 +491,7 @@ apr-util-reset:
 		rm -f $(APR_UTIL_OBJDIR)/$(f);)
 
 apr-util-clean:
-	-(cd $(APR_UTIL_OBJDIR) && make clean)
+	-(cd $(APR_UTIL_OBJDIR) && env MAKEFLAGS= make clean)
 
 
 # retrieve apr-util if not present yet
@@ -504,12 +505,15 @@ $(APR_UTIL_OBJDIR)/.retrieved:
 
 ifeq ($(USE_APR_ICONV),yes)
 ICONV_FLAG=--with-iconv=$(PREFIX)/apr
+ICONV_OBJDIR=$(APR_ICONV_OBJDIR)
 else
 ICONV_FLAG=--with-iconv=$(PREFIX)/iconv
+ICONV_OBJDIR=$(GNU_ICONV_OBJDIR)
 endif
 
 # configure apr-util
-$(APR_UTIL_OBJDIR)/.configured: $(APR_UTIL_OBJDIR)/.retrieved
+$(APR_UTIL_OBJDIR)/.configured: $(APR_UTIL_OBJDIR)/.retrieved \
+	$(APR_OBJDIR)/.installed $(ICONV_OBJDIR)/.installed
 	cd $(APR_UTIL_SRCDIR) && ./buildconf --with-apr=$(APR_SRCDIR)
 	cd $(APR_UTIL_OBJDIR) \
 		&& env LD_LIBRARY_PATH=$(PREFIX)/bdb/lib \
@@ -525,12 +529,12 @@ $(APR_UTIL_OBJDIR)/.configured: $(APR_UT
 
 # compile apr-util
 $(APR_UTIL_OBJDIR)/.compiled: $(APR_UTIL_OBJDIR)/.configured
-	(cd $(APR_UTIL_OBJDIR) && make)
+	(cd $(APR_UTIL_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install apr-util
 $(APR_UTIL_OBJDIR)/.installed: $(APR_UTIL_OBJDIR)/.compiled
-	(cd $(APR_UTIL_OBJDIR) && make install)
+	(cd $(APR_UTIL_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -547,7 +551,7 @@ httpd-reset:
 		rm -f $(HTTPD_OBJDIR)/$(f);)
 
 httpd-clean:
-	-(cd $(HTTPD_OBJDIR) && make clean)
+	-(cd $(HTTPD_OBJDIR) && env MAKEFLAGS= make clean)
 
 # fetch distfile for httpd
 $(DISTDIR)/$(HTTPD_DIST):
@@ -560,7 +564,8 @@ $(HTTPD_OBJDIR)/.retrieved: $(DISTDIR)/$
 	touch $@
 
 # configure httpd
-$(HTTPD_OBJDIR)/.configured: $(HTTPD_OBJDIR)/.retrieved
+$(HTTPD_OBJDIR)/.configured: $(HTTPD_OBJDIR)/.retrieved \
+	$(APR_UTIL_OBJDIR)/.installed
 	cd $(HTTPD_OBJDIR) \
 		&& env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \
 		$(HTTPD_SRCDIR)/configure \
@@ -575,12 +580,12 @@ $(HTTPD_OBJDIR)/.configured: $(HTTPD_OBJ
 
 # compile httpd
 $(HTTPD_OBJDIR)/.compiled: $(HTTPD_OBJDIR)/.configured
-	(cd $(HTTPD_OBJDIR) && make)
+	(cd $(HTTPD_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install httpd
 $(HTTPD_OBJDIR)/.installed: $(HTTPD_OBJDIR)/.compiled
-	(cd $(HTTPD_OBJDIR) && make install)
+	(cd $(HTTPD_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 # create a httpd.conf for mod_dav_svn
@@ -618,7 +623,7 @@ neon-reset:
 		rm -f $(NEON_OBJDIR)/$(f);)
 
 neon-clean:
-	-(cd $(NEON_OBJDIR) && make clean)
+	-(cd $(NEON_OBJDIR) && env MAKEFLAGS= make clean)
 
 # fetch distfile for neon
 $(DISTDIR)/$(NEON_DIST):
@@ -665,12 +670,12 @@ $(NEON_OBJDIR)/.configured: $(NEON_OBJDI
 
 # compile neon
 $(NEON_OBJDIR)/.compiled: $(NEON_OBJDIR)/.configured
-	(cd $(NEON_OBJDIR) && make)
+	(cd $(NEON_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install neon
 $(NEON_OBJDIR)/.installed: $(NEON_OBJDIR)/.compiled
-	(cd $(NEON_OBJDIR) && make install)
+	(cd $(NEON_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 
@@ -687,7 +692,7 @@ serf-reset:
 		rm -f $(SERF_OBJDIR)/$(f);)
 
 serf-clean:
-	-(cd $(SERF_SRCDIR) && ./serfmake clean)
+	-(cd $(SERF_SRCDIR) && scons -c)
 
 
 # fetch distfile for serf
@@ -711,21 +716,23 @@ $(SERF_OBJDIR)/.retrieved:
 	touch $@
 
 # compile serf (serf won't compile outside its source tree)
-$(SERF_OBJDIR)/.compiled: $(SERF_OBJDIR)/.retrieved
+$(SERF_OBJDIR)/.compiled: $(SERF_OBJDIR)/.retrieved \
+	$(APR_UTIL_OBJDIR)/.installed
 	cd $(SERF_SRCDIR) && \
-		env CFLAGS="-O0 -g $(PROFILE_CFLAGS)" \
-			./serfmake --with-apr=$(PREFIX)/apr \
-			--prefix=$(PREFIX)/serf \
-			build
+		scons DEBUG=1 CFLAGS="-O0 -g $(PROFILE_CFLAGS)" \
+			APR=$(PREFIX)/apr \
+			APU=$(PREFIX)/apr \
+			PREFIX=$(PREFIX)/serf
 	touch $@
 
 # install serf
 $(SERF_OBJDIR)/.installed: $(SERF_OBJDIR)/.compiled
+	rm -rf $(PREFIX)/serf # XXX scons cannot reinstall :(
 	cd $(SERF_SRCDIR) && \
-		./serfmake --with-apr=$(PREFIX)/apr \
-			--with-apr-util=$(PREFIX)/apr \
-			--prefix=$(PREFIX)/serf \
-			install
+		scons install
+	# work around unportable scons shared lib support
+	-ln -s libserf-1.so.$(shell echo $(SERF_VER) | sed -e 's/[0-9]$$/0/') \
+		$(PREFIX)/serf/lib/libserf-1.so
 	touch $@
 
 #######################################################################
@@ -752,7 +759,8 @@ $(SERF_OLD_OBJDIR)/.retrieved:
 	touch $@
 
 # compile serf (serf won't compile outside its source tree)
-$(SERF_OLD_OBJDIR)/.compiled: $(SERF_OLD_OBJDIR)/.retrieved
+$(SERF_OLD_OBJDIR)/.compiled: $(SERF_OLD_OBJDIR)/.retrieved \
+	$(APR_UTIL_OBJDIR)/.installed
 	cd $(SERF_OLD_SRCDIR) && \
 		env CFLAGS="-O0 -g $(PROFILE_CFLAGS)" \
 			./serfmake --with-apr=$(PREFIX)/apr \
@@ -783,7 +791,7 @@ sqlite-reset:
 		rm -f $(SQLITE_OBJDIR)/$(f);)
 
 sqlite-clean:
-	-cd $(SQLITE_OBJDIR) && make clean
+	-cd $(SQLITE_OBJDIR) && env MAKEFLAGS= make clean
 
 # fetch distfile for sqlite
 $(DISTDIR)/$(SQLITE_DIST):
@@ -812,12 +820,12 @@ $(SQLITE_OBJDIR)/.configured: $(SQLITE_O
 
 # compile sqlite
 $(SQLITE_OBJDIR)/.compiled: $(SQLITE_OBJDIR)/.configured
-	(cd $(SQLITE_OBJDIR) && make)
+	(cd $(SQLITE_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install sqlite
 $(SQLITE_OBJDIR)/.installed: $(SQLITE_OBJDIR)/.compiled
-	(cd $(SQLITE_OBJDIR) && make install)
+	(cd $(SQLITE_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -833,7 +841,7 @@ cyrus-sasl-reset:
 		rm -f $(CYRUS_SASL_OBJDIR)/$(f);)
 
 cyrus-sasl-clean:
-	-(cd $(CYRUS_SASL_OBJDIR) && make distclean)
+	-(cd $(CYRUS_SASL_OBJDIR) && env MAKEFLAGS= make distclean)
 
 # fetch distfile for cyrus-sasl
 $(DISTDIR)/$(CYRUS_SASL_DIST):
@@ -868,7 +876,8 @@ endif
 	touch $@
 
 # configure cyrus-sasl
-$(CYRUS_SASL_OBJDIR)/.configured: $(CYRUS_SASL_OBJDIR)/.retrieved
+$(CYRUS_SASL_OBJDIR)/.configured: $(CYRUS_SASL_OBJDIR)/.retrieved \
+	$(BDB_OBJDIR)/.installed $(SQLITE_OBJDIR)/.installed
 	cd $(CYRUS_SASL_OBJDIR) \
 		&& env CFLAGS="-g $(PROFILE_CFLAGS)" \
 		CPPFLAGS="-I/usr/include/kerberosV" \
@@ -886,12 +895,12 @@ $(CYRUS_SASL_OBJDIR)/.configured: $(CYRU
 
 # compile cyrus-sasl
 $(CYRUS_SASL_OBJDIR)/.compiled: $(CYRUS_SASL_OBJDIR)/.configured
-	(cd $(CYRUS_SASL_OBJDIR) && make)
+	(cd $(CYRUS_SASL_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install cyrus-sasl
 $(CYRUS_SASL_OBJDIR)/.installed: $(CYRUS_SASL_OBJDIR)/.compiled
-	(cd $(CYRUS_SASL_OBJDIR) && make install)
+	(cd $(CYRUS_SASL_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -907,7 +916,7 @@ libmagic-reset:
 		rm -f $(LIBMAGIC_OBJDIR)/$(f);)
 
 libmagic-clean:
-	-(cd $(LIBMAGIC_OBJDIR) && make distclean)
+	-(cd $(LIBMAGIC_OBJDIR) && env MAKEFLAGS= make distclean)
 
 # fetch distfile for libmagic
 $(DISTDIR)/$(LIBMAGIC_DIST):
@@ -930,12 +939,12 @@ $(LIBMAGIC_OBJDIR)/.configured: $(LIBMAG
 
 # compile libmagic
 $(LIBMAGIC_OBJDIR)/.compiled: $(LIBMAGIC_OBJDIR)/.configured
-	(cd $(LIBMAGIC_OBJDIR) && make)
+	(cd $(LIBMAGIC_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install libmagic
 $(LIBMAGIC_OBJDIR)/.installed: $(LIBMAGIC_OBJDIR)/.compiled
-	(cd $(LIBMAGIC_OBJDIR) && make install)
+	(cd $(LIBMAGIC_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -951,7 +960,7 @@ ruby-reset:
 		rm -f $(RUBY_OBJDIR)/$(f);)
 
 ruby-clean:
-	-(cd $(RUBY_OBJDIR) && make distclean)
+	-(cd $(RUBY_OBJDIR) && env MAKEFLAGS= make distclean)
 
 # fetch distfile for ruby
 $(DISTDIR)/$(RUBY_DIST):
@@ -982,12 +991,12 @@ $(RUBY_OBJDIR)/.configured: $(RUBY_OBJDI
 
 # compile ruby
 $(RUBY_OBJDIR)/.compiled: $(RUBY_OBJDIR)/.configured
-	(cd $(RUBY_OBJDIR) && make)
+	(cd $(RUBY_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install ruby
 $(RUBY_OBJDIR)/.installed: $(RUBY_OBJDIR)/.compiled
-	(cd $(RUBY_OBJDIR) && make install)
+	(cd $(RUBY_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 #######################################################################
@@ -1002,7 +1011,7 @@ bz2-reset:
 		rm -f $(BZ2_OBJDIR)/$(f);)
 
 bz2-clean:
-	-(cd $(BZ2_SRCDIR) && make distclean)
+	-(cd $(BZ2_SRCDIR) && env MAKEFLAGS= make distclean)
 
 # fetch distfile for bz2
 $(DISTDIR)/$(BZ2_DIST):
@@ -1016,12 +1025,12 @@ $(BZ2_OBJDIR)/.retrieved: $(DISTDIR)/$(B
 
 # compile bz2
 $(BZ2_OBJDIR)/.compiled: $(BZ2_OBJDIR)/.retrieved
-	(cd $(BZ2_SRCDIR) && make CFLAGS="-g $(PROFILE_CFLAGS) -fPIC")
+	(cd $(BZ2_SRCDIR) && env MAKEFLAGS= make CFLAGS="-g $(PROFILE_CFLAGS) -fPIC")
 	touch $@
 
 # install bz2
 $(BZ2_OBJDIR)/.installed: $(BZ2_OBJDIR)/.compiled
-	(cd $(BZ2_SRCDIR) && make install PREFIX=$(PREFIX)/bz2)
+	(cd $(BZ2_SRCDIR) && env MAKEFLAGS= make install PREFIX=$(PREFIX)/bz2)
 	touch $@
 
 
@@ -1038,7 +1047,7 @@ python-reset:
 		rm -f $(PYTHON_OBJDIR)/$(f);)
 
 python-clean:
-	-(cd $(PYTHON_OBJDIR) && make distclean)
+	-(cd $(PYTHON_OBJDIR) && env MAKEFLAGS= make distclean)
 
 # fetch distfile for python
 $(DISTDIR)/$(PYTHON_DIST):
@@ -1075,7 +1084,8 @@ $(PYTHON_OBJDIR)/.retrieved: $(DISTDIR)/
 ifdef PROFILE
 PYTHON_PROFILING=--enable-profiling
 endif
-$(PYTHON_OBJDIR)/.configured: $(PYTHON_OBJDIR)/.retrieved
+$(PYTHON_OBJDIR)/.configured: $(PYTHON_OBJDIR)/.retrieved \
+	$(BZ2_OBJDIR)/.installed
 	cd $(PYTHON_OBJDIR) \
 		&& env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \
 		CPPFLAGS="-I$(PREFIX)/bz2/include" \
@@ -1090,12 +1100,12 @@ $(PYTHON_OBJDIR)/.configured: $(PYTHON_O
 
 # compile python
 $(PYTHON_OBJDIR)/.compiled: $(PYTHON_OBJDIR)/.configured
-	(cd $(PYTHON_OBJDIR) && make)
+	(cd $(PYTHON_OBJDIR) && env MAKEFLAGS= make)
 	touch $@
 
 # install python
 $(PYTHON_OBJDIR)/.installed: $(PYTHON_OBJDIR)/.compiled
-	(cd $(PYTHON_OBJDIR) && make install)
+	(cd $(PYTHON_OBJDIR) && env MAKEFLAGS= make install)
 	touch $@
 
 
@@ -1130,7 +1140,7 @@ svn-reset: svn-bindings-reset
 		rm -f $(SVN_OBJDIR)/$(f);)
 
 svn-clean:
-	-(cd $(svn_builddir) && make distclean)
+	-(cd $(svn_builddir) && env MAKEFLAGS= make distclean)
 
 # retrieve svn if not present yet
 $(SVN_OBJDIR)/.retrieved:
@@ -1154,6 +1164,7 @@ $(SVN_OBJDIR)/.retrieved:
 ifeq ($(BRANCH_MAJOR),1.7)
 BDB_FLAG=db.h:$(PREFIX)/bdb/include:$(PREFIX)/bdb/lib:db-$(BDB_MAJOR_VER)
 SERF_FLAG=--with-serf="$(PREFIX)/serf"
+SERF_LDFLAG=-Wl,-rpath,$(PREFIX)/serf/lib -Wl,-rpath,$(PREFIX)/bdb/lib
 MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_svn.so
 MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so
 LIBMAGIC_FLAG=--with-libmagic=$(PREFIX)/libmagic
@@ -1162,6 +1173,7 @@ JAVAHL_CHECK_TARGET=check-javahl
 else ifeq ($(BRANCH_MAJOR),1.6)
 BDB_FLAG=db.h:$(PREFIX)/bdb/include:$(PREFIX)/bdb/lib:db-$(BDB_MAJOR_VER)
 SERF_FLAG=--with-serf="$(PREFIX)/serf"
+SERF_LDFLAG=-Wl,-rpath,$(PREFIX)/serf/lib -Wl,-rpath,$(PREFIX)/bdb/lib
 MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_svn.so
 MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so
 W_NO_SYSTEM_HEADERS=-Wno-system-headers
@@ -1179,6 +1191,9 @@ JAVAHL_CHECK_TARGET=check-javahl
 else # 1.8
 BDB_FLAG=db.h:$(PREFIX)/bdb/include:$(PREFIX)/bdb/lib:db-$(BDB_MAJOR_VER)
 SERF_FLAG=--with-serf="$(PREFIX)/serf"
+# serf >= 1.3.0 is built with scons and no longer sets up rpath linker flags,
+# so we have to do that ourselves :(
+SERF_LDFLAG=-Wl,-rpath,$(PREFIX)/serf/lib -Wl,-rpath,$(PREFIX)/bdb/lib
 MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_svn.so
 MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so
 LIBMAGIC_FLAG=--with-libmagic=$(PREFIX)/libmagic
@@ -1201,11 +1216,16 @@ SVN_WITH_HTTPD=--with-apxs="$(PREFIX)/ht
 SVN_WITH_SASL=--with-sasl="$(PREFIX)/cyrus-sasl"
 endif
 
-# configure svn
-$(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)/.retrieved $(DISTDIR)/$(JUNIT_DIST)
+$(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)/.retrieved $(DISTDIR)/$(JUNIT_DIST) \
+	$(APR_OBJDIR)/.installed $(APR_UTIL_OBJDIR)/.installed \
+	$(BDB_OBJDIR)/.installed $(SQLITE_OBJDIR)/.installed \
+	$(HTTPD_OBJDIR)/.installed $(CYRUS_SASL_OBJDIR)/.installed \
+	$(LIBMAGIC_OBJDIR)/.installed $(NEON_OBJDIR)/.installed \
+	$(SERF_OBJDIR)/.installed $(SERF_OLD_OBJDIR)/.installed \
+	$(RUBY_OBJDIR)/.installed $(PYTHON_OBJDIR)/.installed
 	cd $(SVN_SRCDIR) && ./autogen.sh
 	cd $(svn_builddir) && \
-		env LDFLAGS="-L$(PREFIX)/neon/lib -L$(PREFIX)/apr/lib" \
+		env LDFLAGS="-L$(PREFIX)/neon/lib -L$(PREFIX)/apr/lib $(SERF_LDFLAG)" \
 			LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$$LD_LIBRARY_PATH" \
 			GREP="`which grep`" \
 			PATH=$(PREFIX)/ruby/bin:$(PREFIX)/python/bin:$$PATH \
@@ -1232,13 +1252,13 @@ $(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)
 # compile svn
 $(SVN_OBJDIR)/.compiled: $(SVN_OBJDIR)/.configured
 	cd $(svn_builddir) \
-		&& make EXTRA_CFLAGS="$(PROFILE_CFLAGS) $(W_NO_SYSTEM_HEADERS)"
+		&& env MAKEFLAGS= make EXTRA_CFLAGS="$(PROFILE_CFLAGS) $(W_NO_SYSTEM_HEADERS)"
 	touch $@
 
 # install svn
 $(SVN_OBJDIR)/.installed: $(SVN_OBJDIR)/.compiled
 	cd $(svn_builddir) \
-		&& make install
+		&& env MAKEFLAGS= make install
 	touch $@
 
 # SWIG 1.x and 2.x are not compatible. If SWIG 2.x is used to generated .swg
@@ -1248,44 +1268,44 @@ $(SVN_OBJDIR)/.installed: $(SVN_OBJDIR)/
 # by the same version of SWIG.
 $(SVN_OBJDIR)/.pre-generated-swig-cleaned:
 	-cd $(svn_builddir) \
-		&& make clean-swig
+		&& env MAKEFLAGS= make clean-swig
 	touch $@
 
 $(SVN_OBJDIR)/.bindings-compiled: $(SVN_OBJDIR)/.installed $(SVN_OBJDIR)/.pre-generated-swig-cleaned
 	cd $(svn_builddir) \
 		&& env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
-			make swig-py
+			env MAKEFLAGS= make swig-py
 	cd $(svn_builddir) && \
 		env PATH=$(PREFIX)/ruby/bin:$$PATH \
-		LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) make swig-rb
+		LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) env MAKEFLAGS= make swig-rb
 	if [ $(ENABLE_PERL_BINDINGS) = yes ]; then \
 		cd $(svn_builddir) \
 			&& env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
-				make swig-pl; \
+				env MAKEFLAGS= make swig-pl; \
 	fi
 	if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \
 		cd $(svn_builddir) \
-			&& make javahl; \
+			&& env MAKEFLAGS= make javahl; \
 	fi
 	touch $@
 
 $(SVN_OBJDIR)/.bindings-installed: $(SVN_OBJDIR)/.bindings-compiled
 	cd $(svn_builddir) \
 	  && env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
-		make install-swig-py
+		env MAKEFLAGS= make install-swig-py
 	cd $(svn_builddir) && \
 		env PATH=$(PREFIX)/ruby/bin:$$PATH \
-		LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) make install-swig-rb
+		LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) env MAKEFLAGS= make install-swig-rb
 	if [ $(ENABLE_PERL_BINDINGS) = yes ]; then \
 		cd $(svn_builddir) \
-	    && make install-swig-pl-lib; \
+	    && env MAKEFLAGS= make install-swig-pl-lib; \
 	  cd subversion/bindings/swig/perl/native \
 		  && perl Makefile.PL PREFIX="$(SVN_PREFIX)" \
-		  && make install; \
+		  && env MAKEFLAGS= make install; \
 	fi
 	if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \
 		cd $(svn_builddir) \
-			&& make install-javahl; \
+			&& env MAKEFLAGS= make install-javahl; \
 	fi
 	touch $@
 
@@ -1423,7 +1443,7 @@ define do_check
     echo "Begin test: $(subst svn-check-,,$@) x $$fs"; \
     test -d "$(RAMDISK)/tmp" && export TMPDIR="$(RAMDISK)/tmp"; \
     env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(LIB_PTHREAD_HACK) \
-        make check PARALLEL=$(PARALLEL) CLEANUP=$(CLEANUP) \
+        env MAKEFLAGS= make check PARALLEL=$(PARALLEL) CLEANUP=$(CLEANUP) \
 	  EXCLUSIVE_WC_LOCKS=$(EXCLUSIVE_WC_LOCKS) $1 FS_TYPE=$$fs; \
     for log in tests.log fails.log; do \
         test -f $$log && mv -f $$log $$log.$@-$$fs; \
@@ -1480,14 +1500,14 @@ svn-check-swig-pl:
 		(cd $(svn_builddir) && \
 			env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
 			$(LIB_PTHREAD_HACK) \
-			make check-swig-pl 2>&1) | \
+			env MAKEFLAGS= make check-swig-pl 2>&1) | \
 				tee $(svn_builddir)/tests.log.bindings.pl; \
 	fi
 
 svn-check-swig-py:
 	-(cd $(svn_builddir) && \
 		env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
-		make check-swig-py 2>&1) | \
+		env MAKEFLAGS= make check-swig-py 2>&1) | \
 			tee $(svn_builddir)/tests.log.bindings.py
 
 # We add the svn prefix to PATH here because the ruby tests
@@ -1498,14 +1518,14 @@ svn-check-swig-rb:
 		LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
 		PATH=$(SVN_PREFIX)/bin:$$PATH \
 		$(LIB_PTHREAD_HACK) \
-			make check-swig-rb 2>&1) | \
+			env MAKEFLAGS= make check-swig-rb 2>&1) | \
 			tee $(svn_builddir)/tests.log.bindings.rb
 
 svn-check-javahl:
 	-if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \
 		(cd $(svn_builddir) && \
 			env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
-			make $(JAVAHL_CHECK_TARGET) 2>&1) | \
+			env MAKEFLAGS= make $(JAVAHL_CHECK_TARGET) 2>&1) | \
 				tee $(svn_builddir)/tests.log.bindings.javahl; \
 	fi
 

Modified: subversion/branches/verify-keep-going/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/dist/backport.pl?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/dist/backport.pl (original)
+++ subversion/branches/verify-keep-going/tools/dist/backport.pl Wed Nov 27 11:52:35 2013
@@ -22,13 +22,17 @@ use feature qw/switch say/;
 
 use Digest ();
 use Term::ReadKey qw/ReadMode ReadKey/;
+use File::Basename qw/basename dirname/;
 use File::Copy qw/copy move/;
 use File::Temp qw/tempfile/;
-use POSIX qw/ctermid/;
+use POSIX qw/ctermid strftime/;
+use Text::Wrap qw/wrap/;
+use Tie::File ();
 
 ############### Start of reading values from environment ###############
 
 # Programs we use.
+my $SVNAUTH = $ENV{SVNAUTH} // 'svnauth'; # optional dependency
 my $SVN = $ENV{SVN} || 'svn'; # passed unquoted to sh
 my $SHELL = $ENV{SHELL} // '/bin/sh';
 my $VIM = 'vim';
@@ -39,7 +43,7 @@ my $PAGER = $ENV{PAGER} // 'less -F' // 
 #    svn-role:      YES=1 MAY_COMMIT=1
 #    conflicts-bot: YES=1 MAY_COMMIT=0
 #    interactive:   YES=0 MAY_COMMIT=0      (default)
-my $YES = ($ENV{YES} // 0) ? 1 : 0; # batch mode: eliminate prompts, add sleeps
+my $YES = exists $ENV{YES}; # batch mode: eliminate prompts, add sleeps
 my $MAY_COMMIT = 'false';
 $MAY_COMMIT = 'true' if ($ENV{MAY_COMMIT} // "false") =~ /^(1|yes|true)$/i;
 
@@ -48,14 +52,15 @@ my $VERBOSE = 0;
 my $DEBUG = (exists $ENV{DEBUG}) ? 'true' : 'false'; # 'set -x', etc
 
 # Username for entering votes.
+my $SVN_A_O_REALM = '<https://svn.apache.org:443> ASF Committers';            
 my ($AVAILID) = $ENV{AVAILID} // do {
-  my $SVN_A_O_REALM = 'd3c8a345b14f6a1b42251aef8027ab57';
-  open USERNAME, '<', "$ENV{HOME}/.subversion/auth/svn.simple/$SVN_A_O_REALM";
-  1 until <USERNAME> eq "username\n";
-  <USERNAME>;
-  local $_ = <USERNAME>;
-  chomp;
-  $_
+  local $_ = `$SVNAUTH list 2>/dev/null`;
+  ($? == 0 && /Auth.*realm: \Q$SVN_A_O_REALM\E\nUsername: (.*)/) ? $1 : undef
+} // do {
+  local $/; # slurp mode
+  my $filename = Digest->new("MD5")->add($SVN_A_O_REALM)->hexdigest;
+  `cat $ENV{HOME}/.subversion/auth/svn.simple/$filename`
+  =~ /K 8\nusername\nV \d+\n(.*)/ and $1 or undef
 }
 // warn "Username for commits (of votes/merges) not found";
 
@@ -81,13 +86,31 @@ $SVNq = "$SVN -q ";
 $SVNq =~ s/-q// if $DEBUG eq 'true';
 
 
-sub usage {
-  my $basename = $0;
-  $basename =~ s#.*/##;
+sub backport_usage {
+  my $basename = basename $0;
   print <<EOF;
-backport.pl: a tool for reviewing and merging STATUS entries.  Run this with
-CWD being the root of the stable branch (e.g., 1.8.x).  The ./STATUS file
-should be at HEAD.
+backport.pl: a tool for reviewing, merging, and voting on STATUS entries.
+
+Normally, invoke this with CWD being the root of the stable branch (e.g.,
+1.8.x):
+
+    Usage: test -e \$d/STATUS && cd \$d && \\
+           backport.pl [PATTERN]
+    (where \$d is a working copy of branches/1.8.x)
+
+Alternatively, invoke this via a symlink named "b" placed at the same directory
+as the STATUS file, in which case the CWD doesn't matter (the script will cd):
+
+    Usage: ln -s /path/to/backport.pl \$d/b && \\
+           \$d/b [PATTERN]
+    (where \$d is a working copy of branches/1.8.x)
+
+In either case, the ./STATUS file should be at HEAD.  If it has local mods,
+they will be preserved through 'revert' operations but included in 'commit'
+operations.
+
+If PATTERN is provided, only entries which match PATTERN are considered.  The
+sense of "match" is either substring (fgrep) or Perl regexp (with /msi).
 
 In interactive mode (the default), you will be prompted once per STATUS entry.
 At a prompt, you have the following options:
@@ -116,29 +139,66 @@ y:   Open a shell.
 d:   View a diff.
 N:   Move to the next entry.
 
-There is also a batch mode: when \$YES and \$MAY_COMMIT are defined to '1' i
+There is also a batch mode (normally used only by cron jobs and buildbot tasks,
+rather than interactively): when \$YES and \$MAY_COMMIT are defined to '1' in
 the environment, this script will iterate the "Approved:" section, and merge
 and commit each entry therein.  If only \$YES is defined, the script will
 merge every nomination (including unapproved and vetoed ones), and complain
-to stderr if it notices any conflicts.  These mode are normally used by the
-'svn-role' cron job and/or buildbot, not by human users.
+to stderr if it notices any conflicts.
 
 The 'svn' binary defined by the environment variable \$SVN, or otherwise the
 'svn' found in \$PATH, will be used to manage the working copy.
 EOF
 }
 
+sub nominate_usage {
+  my $basename = basename $0;
+  print <<EOF;
+nominate.pl: a tool for adding entries to STATUS.
+
+Usage: $0 "foo r42 bar r43 qux 45." "\$Some_justification"
+
+Will add:
+ * r42, r43, r45
+   (log message of r42)
+   Justification:
+     \$Some_justification
+   Votes:
+     +1: $AVAILID
+to STATUS.  Backport branches are detected automatically.
+
+The STATUS file in the current directory is used (unless argv[0] is "n", in
+which case the STATUS file in the directory of argv[0] is used; the intent
+is to create a symlink named "n" in the branch wc root).
+
+EOF
+# TODO: Optionally add a "Notes" section.
+# TODO: Look for backport branches named after issues.
+# TODO: Do a dry-run merge on added entries.
+# TODO: Do a dry-run merge on interactively-edited entries in backport.pl
+}
+
 sub digest_string {
   Digest->new("MD5")->add(@_)->hexdigest
 }
 
+sub digest_entry($) {
+  # Canonicalize the number of trailing EOLs to two.  This matters when there's
+  # on empty line after the last entry in Approved, for example.
+  local $_ = shift;
+  s/\n*\z// and $_ .= "\n\n";
+  digest_string($_)
+}
+
 sub prompt {
   print $_[0]; shift;
   my %args = @_;
   my $getchar = sub {
+    my $answer;
     ReadMode 'cbreak';
-    my $answer = (ReadKey 0);
+    eval { $answer = (ReadKey 0) };
     ReadMode 'normal';
+    die $@ if $@;
     print $answer;
     return $answer;
   };
@@ -160,29 +220,38 @@ sub merge {
   my ($logmsg_fh, $logmsg_filename) = tempfile();
   my ($mergeargs, $pattern);
 
-  my $backupfile = "backport_pl.$$.tmp";
+  # Include the time so it's easier to find the interesting backups.
+  my $backupfile = strftime "backport_pl.%Y%m%d-%H%M%S.$$.tmp", localtime;
+  die if -s $backupfile;
 
   if ($entry{branch}) {
-    # NOTE: This doesn't escape the branch into the pattern.
-    $pattern = sprintf '\V\(%s branch(es)?\|branches\/%s\|Branch\(es\)\?: \*\n\? \*%s\)', $entry{branch}, $entry{branch}, $entry{branch};
+    my $vim_escaped_branch = 
+      join "",
+      map { sprintf '\[%s%s]', $_, ($_ x ($_ eq '\\')) }
+      split //,
+      $entry{branch};
+    $pattern = sprintf '\VBranch: \*\n\? \*\(\.\*\/branches\/\)\?%s',
+                 $vim_escaped_branch;
     if ($SVNvsn >= 1_008_000) {
       $mergeargs = "$BRANCHES/$entry{branch}";
-      say $logmsg_fh "Merge the $entry{header}:";
+      say $logmsg_fh "Merge $entry{header}:";
     } else {
       $mergeargs = "--reintegrate $BRANCHES/$entry{branch}";
-      say $logmsg_fh "Reintegrate the $entry{header}:";
+      say $logmsg_fh "Reintegrate $entry{header}:";
     }
     say $logmsg_fh "";
   } elsif (@{$entry{revisions}}) {
     $pattern = '^ [*] \V' . 'r' . $entry{revisions}->[0];
-    $mergeargs = join " ", (map { "-c$_" } @{$entry{revisions}}), '^/subversion/trunk';
-    if (@{$entry{revisions}} > 1) {
-      say $logmsg_fh "Merge the $entry{header} from trunk:";
-      say $logmsg_fh "";
-    } else {
-      say $logmsg_fh "Merge r$entry{revisions}->[0] from trunk:";
-      say $logmsg_fh "";
-    }
+    $mergeargs = join " ",
+      ($entry{accept} ? "--accept=$entry{accept}" : ()),
+      (map { "-c$_" } @{$entry{revisions}}),
+      '--',
+      '^/subversion/trunk';
+    say $logmsg_fh
+      "Merge $entry{header} from trunk",
+      $entry{accept} ? ", with --accept=$entry{accept}" : "",
+      ":";
+    say $logmsg_fh "";
   } else {
     die "Don't know how to call $entry{header}";
   }
@@ -219,7 +288,7 @@ fi
 if $MAY_COMMIT; then
   $VIM -e -s -n -N -i NONE -u NONE -c '/$pattern/normal! dap' -c wq $STATUS
   $SVNq commit -F $logmsg_filename
-elif test 1 -ne $YES; then
+elif test -z "\$YES"; then
   echo "Would have committed:"
   echo '[[['
   $SVN status -q
@@ -236,7 +305,7 @@ if $MAY_COMMIT; then
   if [ -n "\$YES" ]; then sleep 15; fi
   $SVNq rm $BRANCHES/$entry{branch} -m "Remove the '$entry{branch}' branch, $reintegrated_word in r\$reinteg_rev."
   if [ -n "\$YES" ]; then sleep 1; fi
-elif test 1 -ne $YES; then
+elif test -z "\$YES"; then
   echo "Would remove $reintegrated_word '$entry{branch}' branch"
 fi
 EOF
@@ -244,7 +313,7 @@ EOF
   open SHELL, '|-', qw#/bin/sh# or die "$! (in '$entry{header}')";
   print SHELL $script;
   close SHELL or warn "$0: sh($?): $! (in '$entry{header}')";
-  $ERRORS{$entry{id}} = "sh($?): $!" if $?;
+  $ERRORS{$entry{id}} = [\%entry, "sh($?): $!"] if $?;
 
   if (-z $backupfile) {
     unlink $backupfile;
@@ -257,17 +326,25 @@ EOF
 
 sub sanitize_branch {
   local $_ = shift;
-  s#.*/##;
+  my $branches_re = quotemeta $BRANCHES;
+  s#.*$branches_re/##;
   s/^\s*//;
   s/\s*$//;
   return $_;
 }
 
+sub logsummarysummary {
+  my $entry = shift;
+  join "",
+    $entry->{logsummary}->[0], ('[...]' x (0 < $#{$entry->{logsummary}}))
+}
+
 # TODO: may need to parse other headers too?
 sub parse_entry {
   my $raw = shift;
   my @lines = @_;
   my $depends;
+  my $accept;
   my (@revisions, @logsummary, $branch, @votes);
   # @lines = @_;
 
@@ -277,6 +354,7 @@ sub parse_entry {
 
   # revisions
   $branch = sanitize_branch $1
+    and shift
     if $_[0] =~ /^(\S*) branch$/ or $_[0] =~ m#branches/(\S+)#;
   while ($_[0] =~ /^r/) {
     my $sawrevnum = 0;
@@ -290,41 +368,71 @@ sub parse_entry {
   # summary
   do {
     push @logsummary, shift
-  } until $_[0] =~ /^\s*\w+:/ or not defined $_[0];
+  } until $_[0] =~ /^\s*[][\w]+:/ or not defined $_[0];
 
   # votes
   unshift @votes, pop until $_[-1] =~ /^\s*Votes:/ or not defined $_[-1];
   pop;
 
-  # depends
-  # TODO: parse the value of this.
-  $depends = grep /^Depends:/, @_;
-
-  # branch
+  # depends, branch, notes
+  # Ignored headers: Changes[*]
   while (@_) {
-    shift and next unless $_[0] =~ s/^\s*Branch(es)?:\s*//;
-    $branch = sanitize_branch (shift || shift || die "Branch header found without value");
+    given (shift) {
+      when (/^Depends:/) {
+        $depends++;
+      }
+      if (s/^Branch:\s*//) {
+        $branch = sanitize_branch ($_ || shift || die "Branch header found without value");
+      }
+      if (s/^Notes:\s*//) {
+        my $notes = $_;
+        $notes .= shift while @_ and $_[0] !~ /^\w/;
+        my %accepts = map { $_ => 1 } ($notes =~ /--accept[ =]([a-z-]+)/g);
+        given (scalar keys %accepts) {
+          when (0) { } 
+          when (1) { $accept = [keys %accepts]->[0]; } 
+          default  {
+            warn "Too many --accept values at '",
+                 logsummarysummary({ logsummary => [@logsummary] }),
+                 "'";
+          }
+        }
+      }
+    }
   }
 
   # Compute a header.
   my ($header, $id);
-  $header = "r$revisions[0] group" if @revisions;
-  $id = "r$revisions[0]"           if @revisions;
-  $header = "$branch branch"       if $branch;
-  $id = $branch                    if $branch;
-  warn "No header for [@lines]" unless $header;
+  if ($branch) {
+    $header = "the $branch branch";
+    $id = $branch;
+  } elsif (@revisions == 1) {
+    $header = "r$revisions[0]";
+    $id = "r$revisions[0]";
+  } elsif (@revisions) {
+    $header = "the r$revisions[0] group";
+    $id = "r$revisions[0]";
+  } else {
+    die "Entry '$raw' has neither revisions nor branch";
+  }
+  my $header_start = ($header =~ /^the/ ? ucfirst($header) : $header);
+
+  warn "Entry has both branch '$branch' and --accept=$accept specified\n"
+    if $branch and $accept;
 
   return (
     revisions => [@revisions],
     logsummary => [@logsummary],
     branch => $branch,
     header => $header,
+    header_start => $header_start,
     depends => $depends,
     id => $id,
     votes => [@votes],
     entry => [@lines],
+    accept => $accept,
     raw => $raw,
-    digest => digest_string($raw),
+    digest => digest_entry($raw),
   );
 }
 
@@ -349,9 +457,10 @@ sub edit_string {
 
 sub vote {
   my ($state, $approved, $votes) = @_;
+  # TODO: use votesarray instead of votescheck
   my (%approvedcheck, %votescheck);
   my $raw_approved = "";
-  my @votes;
+  my @votesarray;
   return unless %$approved or %$votes;
 
   my $had_empty_line;
@@ -361,21 +470,39 @@ sub vote {
   open VOTES, ">", "$STATUS.$$.tmp";
   while (<STATUS>) {
     $had_empty_line = /\n\n\z/;
-    my $key = digest_string $_;
+    my $key = digest_entry $_;
 
     $approvedcheck{$key}++ if exists $approved->{$key};
     $votescheck{$key}++ if exists $votes->{$key};
 
+    unless (exists $votes->{$key} or exists $approved->{$key}) {
+      print VOTES;
+      next;
+    }
+
     unless (exists $votes->{$key}) {
-      (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
+      push @votesarray, {
+        entry => $approved->{$key},
+        approval => 1,
+        digest => $key,
+      };
+      $raw_approved .= $_;
       next;
     }
 
+    # We have a vote, and potentially an approval.
+
     my ($vote, $entry) = @{$votes->{$key}};
-    push @votes, [$vote, $entry, undef]; # ->[2] later set to $digest
+    push @votesarray, {
+      entry => $entry,
+      vote => $vote,
+      approval => (exists $approved->{$key}),
+      digest => $key,
+    };
 
     if ($vote eq 'edit') {
       local $_ = $entry->{raw};
+      $votesarray[-1]->{digest} = digest_entry $_;
       (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
       next;
     }
@@ -384,68 +511,86 @@ sub vote {
     or s/(.*\w.*?\n)/"$1     $vote: $AVAILID\n"/se;
     $_ = edit_string $_, $entry->{header}, trailing_eol => 2
         if $vote ne '+1';
-    $votes[$#votes]->[2] = digest_string $_;
+    $votesarray[-1]->{digest} = digest_entry $_;
     (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
   }
   close STATUS;
   print VOTES "\n" if $raw_approved and !$had_empty_line;
   print VOTES $raw_approved;
   close VOTES;
-  die "Some vote chunks weren't found: ",
+  warn "Some vote chunks weren't found: ",
+    join ',',
     map $votes->{$_}->[1]->{id},
     grep { !$votescheck{$_} } keys %$votes
     if scalar(keys %$votes) != scalar(keys %votescheck);
-  die "Some approval chunks weren't found: ",
+  warn "Some approval chunks weren't found: ",
+    join ',',
     map $approved->{$_}->{id},
     grep { !$approvedcheck{$_} } keys %$approved
     if scalar(keys %$approved) != scalar(keys %approvedcheck);
+  prompt "Press the 'any' key to continue...\n", dontprint => 1
+    if scalar(keys %$approved) != scalar(keys %approvedcheck) 
+    or scalar(keys %$votes) != scalar(keys %votescheck);
   move "$STATUS.$$.tmp", $STATUS;
 
   my $logmsg = do {
-    my %allkeys = map { $_ => 1 } keys(%$votes), keys(%$approved);
     my @sentences = map {
-       exists $votes->{$_}
+       my $words_vote = ", approving" x $_->{approval};
+       my $words_edit = " and approve" x $_->{approval};
+       exists $_->{vote}
        ? (
-         ( $votes->{$_}->[0] eq 'edit'
-           ? "Edit the $votes->{$_}->[1]->{id} entry"
-           : "Vote $votes->{$_}->[0] on the $votes->{$_}->[1]->{header}"
+         ( $_->{vote} eq 'edit'
+           ? "Edit$words_edit the $_->{entry}->{id} entry"
+           : "Vote $_->{vote} on $_->{entry}->{header}$words_vote"
          )
-         . (exists $approved->{$_} ? ", approving" : "")
          . "."
          )
       : # exists only in $approved
-        "Approve the $approved->{$_}->{header}."
-      } keys %allkeys;
+        "Approve $_->{entry}->{header}."
+      } @votesarray;
     (@sentences == 1)
     ? $sentences[0]
     : "* STATUS:\n" . join "", map "  $_\n", @sentences;
   };
 
   system "$SVN diff -- $STATUS";
-  say "Voting '$_->[0]' on $_->[1]->{id}." for @votes;
-  # say $logmsg;
+  printf "[[[\n%s%s]]]\n", $logmsg, ("\n" x ($logmsg !~ /\n\z/));
   if (prompt "Commit these votes? ") {
     my ($logmsg_fh, $logmsg_filename) = tempfile();
     print $logmsg_fh $logmsg;
     close $logmsg_fh;
-    warn "Tempfile name '$logmsg_filename' not shell-safe; "
-         ."refraining from commit.\n"
+    warn("Tempfile name '$logmsg_filename' not shell-safe; "
+         ."refraining from commit.\n") and return
         unless $logmsg_filename =~ /^([A-Z0-9._-]|\x2f)+$/i;
     system("$SVN commit -F $logmsg_filename -- $STATUS") == 0
         or warn("Committing the votes failed($?): $!") and return;
     unlink $logmsg_filename;
 
-    $state->{$approved->{$_}->{digest}}++ for keys %$approved;
-    $state->{$_->[2]}++ for @votes;
+    # Add to state votes that aren't '+0' or 'edit'
+    $state->{$_->{digest}}++ for grep
+                                   +{ qw/-1 t -0 t +1 t/ }->{$_->{vote}},
+                                 @votesarray;
   }
 }
 
+sub check_local_mods_to_STATUS {
+  if (`$SVN status -q $STATUS`) {
+    die  "Local mods to STATUS file $STATUS" if $YES;
+    warn "Local mods to STATUS file $STATUS";
+    system "$SVN diff -- $STATUS";
+    prompt "Press the 'any' key to continue...\n", dontprint => 1;
+    return 1;
+  }
+  return 0;
+}
+
 sub revert {
   copy $STATUS, "$STATUS.$$.tmp";
   system "$SVN revert -q $STATUS";
   system "$SVN revert -R ./" . ($YES && $MAY_COMMIT ne 'true'
                              ? " -q" : "");
   move "$STATUS.$$.tmp", $STATUS;
+  $MERGED_SOMETHING = 0;
 }
 
 sub maybe_revert {
@@ -456,14 +601,26 @@ sub maybe_revert {
   (@_ ? exit : return);
 }
 
+sub signal_handler {
+  my $sig = shift;
+
+  # Clean up after prompt()
+  ReadMode 'normal';
+
+  # Fall back to default action
+  delete $SIG{$sig};
+  kill $sig, $$;
+}
+
 sub warning_summary {
   return unless %ERRORS;
 
   warn "Warning summary\n";
   warn "===============\n";
   warn "\n";
-  for my $header (keys %ERRORS) {
-    warn "$header: $ERRORS{$header}\n";
+  for my $id (keys %ERRORS) {
+    my $title = logsummarysummary $ERRORS{$id}->[0];
+    warn "$id ($title): $ERRORS{$id}->[1]\n";
   }
 }
 
@@ -505,9 +662,13 @@ sub handle_entry {
   my $votes = shift;
   my $state = shift;
   my $raw = shift;
+  my $skip = shift;
   my %entry = parse_entry $raw, @_;
   my @vetoes = grep { /^  -1:/ } @{$entry{votes}};
 
+  my $match = defined($skip) ? ($raw =~ /\Q$skip\E/ or $raw =~ /$skip/msi) : 0
+              unless $YES;
+
   if ($YES) {
     # Run a merge if:
     unless (@vetoes) {
@@ -519,34 +680,46 @@ sub handle_entry {
         merge %entry;
 
         my $output = `$SVN status`;
-        my (@conflicts) = ($output =~ m#^(?:C|.C|...C).*/(.*)#mg);
+        my (@conflicts) = ($output =~ m#^(?:C...|.C..|...C)...\s(.*)#mg);
         if (@conflicts and !$entry{depends}) {
-          $ERRORS{$entry{id}} //= "Conflicts merging the $entry{header}: "
-                                  . (join ', ', @conflicts);
-          say STDERR "Conflicts merging the $entry{header}!";
+          $ERRORS{$entry{id}} //= [\%entry,
+                                   sprintf "Conflicts on %s%s%s",
+                                     '[' x !!$#conflicts,
+                                     (join ', ',
+                                      map { basename $_ }
+                                      @conflicts),
+                                     ']' x !!$#conflicts,
+                                  ];
+          say STDERR "Conflicts merging $entry{header}!";
           say STDERR "";
           say STDERR $output;
+          system "$SVN diff -- @conflicts";
         } elsif (!@conflicts and $entry{depends}) {
-          warn "No conflicts merging the $entry{header}, but conflicts were "
+          # Not a warning since svn-role may commit the dependency without
+          # also committing the dependent in the same pass.
+          print "No conflicts merging $entry{header}, but conflicts were "
               ."expected ('Depends:' header set)\n";
         } elsif (@conflicts) {
-          say "Conflicts found merging $entry{id}, as expected.";
+          say "Conflicts found merging $entry{header}, as expected.";
         }
         revert;
       }
     }
-  } elsif ($state->{$entry{digest}}) {
+  } elsif (defined($skip) ? not $match : $state->{$entry{digest}}) {
     print "\n\n";
-    say "Skipping the $entry{header} (remove $STATEFILE to reset):";
-    say $entry{logsummary}->[0], ('[...]' x (0 < $#{$entry{logsummary}}));
-  } else {
+    my $reason = defined($skip) ? "doesn't match pattern"
+                                : "remove $STATEFILE to reset";
+    say "Skipping $entry{header} ($reason):";
+    say logsummarysummary \%entry;
+  } elsif ($match or not defined $skip) {
     # This loop is just a hack because 'goto' panics.  The goto should be where
     # the "next PROMPT;" is; there's a "last;" at the end of the loop body.
     PROMPT: while (1) {
     say "";
-    say "\n>>> The $entry{header}:";
+    say "\n>>> $entry{header_start}:";
     say join ", ", map { "r$_" } @{$entry{revisions}} if @{$entry{revisions}};
     say "$BRANCHES/$entry{branch}" if $entry{branch};
+    say "--accept=$entry{accept}" if $entry{accept};
     say "";
     say for @{$entry{logsummary}};
     say "";
@@ -572,6 +745,12 @@ sub handle_entry {
                 or warn "diff failed ($?): $!";
               next;
             }
+            when (/^N/i) {
+              # fall through.
+            }
+            default {
+              next;
+            }
           }
           revert;
           next PROMPT;
@@ -580,7 +759,7 @@ sub handle_entry {
       }
       when (/^l/i) {
         if ($entry{branch}) {
-            system "$SVN log --stop-on-copy -v -r 0:HEAD -- "
+            system "$SVN log --stop-on-copy -v -g -r 0:HEAD -- "
                    ."$BRANCHES/$entry{branch} "
                    ."| $PAGER";
         } elsif (@{$entry{revisions}}) {
@@ -602,6 +781,7 @@ sub handle_entry {
       when (/^([+-][01])\s*$/i) {
         $votes->{$key} = [$1, \%entry];
         say "Your '$1' vote has been recorded." if $VERBOSE;
+        last PROMPT;
       }
       when (/^e/i) {
         my $original = $entry{raw};
@@ -609,9 +789,11 @@ sub handle_entry {
                         trailing_eol => 2;
         $votes->{$key} = ['edit', \%entry] # marker for the 2nd pass
             if $original ne $entry{raw};
+        last PROMPT;
       }
       when (/^N/i) {
         $state->{$entry{digest}}++;
+        last PROMPT;
       }
       when (/^\x20/) {
         last PROMPT; # Fall off the end of the given/when block.
@@ -623,6 +805,9 @@ sub handle_entry {
     }
     last; } # QUESTION
     last; } # PROMPT
+  } else {
+    # NOTREACHED
+    die "Unreachable code reached.";
   }
 
   # TODO: merge() changes ./STATUS, which we're reading below, but
@@ -632,14 +817,17 @@ sub handle_entry {
 }
 
 
-sub main {
+sub backport_main {
   my %approved;
   my %votes;
   my $state = read_state;
 
-  usage, exit 0 if @ARGV;
+  backport_usage, exit 0 if @ARGV > ($YES ? 0 : 1) or grep /^--help$/, @ARGV;
+  backport_usage, exit 0 if grep /^(?:-h|-\?|--help|help)$/, @ARGV;
+  my $skip = shift; # maybe undef
+  # assert not defined $skip if $YES;
 
-  open STATUS, "<", $STATUS or (usage, exit 1);
+  open STATUS, "<", $STATUS or (backport_usage, exit 1);
 
   # Because we use the ':normal' command in Vim...
   die "A vim with the +ex_extra feature is required for \$MAY_COMMIT mode"
@@ -652,12 +840,7 @@ sub main {
   system("$SVN info $STATUS >/dev/null") == 0
     or die "$0: svn error; point \$SVN to an appropriate binary";
 
-  if (`$SVN status -q $STATUS`) {
-    die  "Local mods to STATUS file $STATUS" if $YES;
-    warn "Local mods to STATUS file $STATUS";
-    system "$SVN diff -- $STATUS";
-    prompt "Press the 'any' key to continue...\n", dontprint => 1;
-  }
+  check_local_mods_to_STATUS;
 
   # Skip most of the file
   $/ = ""; # paragraph mode
@@ -666,6 +849,7 @@ sub main {
   }
 
   $SIG{INT} = \&maybe_revert unless $YES;
+  $SIG{TERM} = \&signal_handler unless $YES;
 
   my $in_approved = 0;
   while (<STATUS>) {
@@ -690,7 +874,8 @@ sub main {
       when (/^ \*/) {
         warn "Too many bullets in $lines[0]" and next
           if grep /^ \*/, @lines[1..$#lines];
-        handle_entry $in_approved, \%approved, \%votes, $state, $lines, @lines;
+        handle_entry $in_approved, \%approved, \%votes, $state, $lines, $skip,
+                     @lines;
       }
       default {
         warn "Unknown entry '$lines[0]'";
@@ -701,4 +886,100 @@ sub main {
   exit_stage_left $state, \%approved, \%votes;
 }
 
-&main
+sub nominate_main {
+  my $had_local_mods;
+
+  local $Text::Wrap::columns = 79;
+
+  $had_local_mods = check_local_mods_to_STATUS;
+
+  # Argument parsing.
+  nominate_usage, exit 0 if @ARGV != 2;
+  my (@revnums) = (+shift) =~ /(\d+)/g;
+  my $justification = shift;
+
+  @revnums = sort { $a <=> $b } keys %{{ map { $_ => 1 } @revnums }};
+  die "No revision numbers specified" unless @revnums;
+
+  # Determine whether a backport branch exists
+  my ($URL) = `$SVN info` =~ /^URL: (.*)$/m;
+  die "Can't retrieve URL of cwd" unless $URL;
+
+  die if $URL !~ m%^[A-Za-z0-9:_.+/][A-Za-z0-9:_.+/-]*$%;
+  system "$SVN info -- $URL-r$revnums[0] 2>/dev/null";
+  my $branch = ($? == 0) ? basename("$URL-r$revnums[0]") : undef;
+
+  # Construct entry.
+  my $logmsg = `$SVN propget --revprop -r $revnums[0] --strict svn:log '^/'`;
+  die "Can't fetch log message of r$revnums[0]: $!" unless $logmsg;
+  
+  unless ($logmsg =~ s/^(.*?)\n\n.*/$1/s) {
+    # "* file\n  (symbol): Log message."
+
+    # Strip before and after the first symbol's log message.
+    $logmsg =~ s/^.*?: //s;
+    $logmsg =~ s/^  \x28.*//ms;
+
+    # Undo line wrapping.  (We'll re-do it later.)
+    $logmsg =~ s/\s*\n\s+/ /g;
+  }
+
+  my @lines;
+  warn "Wrapping [$logmsg]\n";
+  push @lines, wrap " * ", ' 'x3, join ', ', map "r$_", @revnums;
+  push @lines, wrap ' 'x3, ' 'x3, split /\n/, $logmsg;
+  push @lines, "   Justification:";
+  push @lines, wrap ' 'x5, ' 'x5, $justification;
+  push @lines, "   Branch: $branch" if defined $branch;
+  push @lines, "   Votes:";
+  push @lines, "     +1: $AVAILID";
+  push @lines, "";
+  my $raw = join "", map "$_\n", @lines;
+
+  # Open the file in line-mode (not paragraph-mode).
+  my @STATUS;
+  tie @STATUS, "Tie::File", $STATUS, recsep => "\n";
+  my ($index) = grep { $STATUS[$_] =~ /^Veto/ } (0..$#STATUS);
+  die "Couldn't find where to add an entry" unless $index;
+
+  # Add an empty line if needed.
+  if ($STATUS[$index-1] =~ /\S/) {
+    splice @STATUS, $index, 0, "";
+    $index++;
+  }
+
+  # Add the entry.
+  splice @STATUS, $index, 0, @lines;
+
+  # Save.
+  untie @STATUS;
+
+  # Done!
+  system "$SVN diff -- $STATUS";
+  if (prompt "Commit this nomination? ") {
+    system "$SVN commit -m 'Nominate r$revnums[0].' -- $STATUS";
+    exit $?;
+  }
+  elsif (!$had_local_mods or prompt "Revert STATUS (destroying local mods)? ") {
+    # TODO: we could be smarter and just un-splice the lines we'd added.
+    system "$SVN revert -- $STATUS";
+    exit $?;
+  }
+
+  exit 0;
+}
+
+# Dispatch to the appropriate main().
+given (basename($0)) {
+  when (/^b$|backport/) {
+    chdir dirname $0 or die "Can't chdir: $!" if /^b$/;
+    &backport_main(@ARGV);
+  }
+  when (/^n$|nominate/) {
+    chdir dirname $0 or die "Can't chdir: $!" if /^n$/;
+    &nominate_main(@ARGV);
+  }
+  default {
+    &backport_main(@ARGV);
+  }
+}

Modified: subversion/branches/verify-keep-going/tools/dist/release.py
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/dist/release.py?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/dist/release.py (original)
+++ subversion/branches/verify-keep-going/tools/dist/release.py Wed Nov 27 11:52:35 2013
@@ -87,7 +87,12 @@ tool_versions = {
   'trunk' : {
             'autoconf' : '2.69',
             'libtool'  : '2.4.2',
-            'swig'     : '2.0.9',
+            'swig'     : '2.0.11',
+  },
+  '1.9' : {
+            'autoconf' : '2.69',
+            'libtool'  : '2.4.2',
+            'swig'     : '2.0.11'
   },
   '1.8' : {
             'autoconf' : '2.69',

Modified: subversion/branches/verify-keep-going/tools/dist/templates/download.ezt
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/dist/templates/download.ezt?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/dist/templates/download.ezt (original)
+++ subversion/branches/verify-keep-going/tools/dist/templates/download.ezt Wed Nov 27 11:52:35 2013
@@ -1,4 +1,4 @@
-<p style="font-size: 150%; text-align: center;">Subversion [version]</p>
+<p style="font-size: 150%; text-align: center;">Apache Subversion [version]</p>
 <table class="centered">
 <tr>
   <th>File</th>

Modified: subversion/branches/verify-keep-going/tools/examples/blame.py
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/examples/blame.py?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/examples/blame.py (original)
+++ subversion/branches/verify-keep-going/tools/examples/blame.py Wed Nov 27 11:52:35 2013
@@ -91,9 +91,9 @@ def blame(path, filename, rev=None):
 #    print ''.join(diffresult)
 #  print annotresult
   for x in range(len(annotresult.keys())):
-     sys.stdout.write("Line %d (rev %d):%s" % (x,
-                                               annotresult[x][0],
-                                               annotresult[x][1]))
+     sys.stdout.write("Line %d (r%d):%s" % (x,
+                                            annotresult[x][0],
+                                            annotresult[x][1]))
 
 def usage():
   print("USAGE: blame.py [-r REV] repos-path file")

Modified: subversion/branches/verify-keep-going/tools/examples/svnlook.py
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/examples/svnlook.py?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/examples/svnlook.py (original)
+++ subversion/branches/verify-keep-going/tools/examples/svnlook.py Wed Nov 27 11:52:35 2013
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# svnlook.py : a Python-based replacement for svnlook
+# svnlook.py : alternative svnlook in Python with library API
 #
 ######################################################################
 #    Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +21,34 @@
 #    under the License.
 ######################################################################
 #
+# $HeadURL$
+# $LastChangedDate$
+# $LastChangedRevision$
+
+"""
+svnlook.py can also be used as a Python module::
+
+  >>> import svnlook
+  >>> svnlook = svnlook.SVNLook("/testrepo")
+  >>> svnlook.get_author()
+  'randomjoe'
+
+
+Accessible API::
+
+[x] author
+[x] changed
+[x] date
+[ ] diff
+[x] dirs-changed
+[ ] ids
+[x] info
+[x] log
+[ ] tree
+---
+[ ] generator API to avoid passing lists
+"""
+
 
 import sys
 import time
@@ -28,86 +56,155 @@ import os
 
 from svn import core, fs, delta, repos
 
-class SVNLook:
-  def __init__(self, path, cmd, rev, txn):
+class SVNLook(object):
+  def __init__(self, path, rev=None, txn=None, cmd=None):
+    """
+    path  - path to repository
+    rev   - revision number
+    txn   - name of transaction (usually the one about to be committed)
+    cmd   - if set, specifies cmd_* method to execute
+
+    txn takes precedence over rev; if both are None, inspect the head revision
+    """
     path = core.svn_path_canonicalize(path)
     repos_ptr = repos.open(path)
     self.fs_ptr = repos.fs(repos_ptr)
 
+    # if set, txn takes precendence
     if txn:
       self.txn_ptr = fs.open_txn(self.fs_ptr, txn)
     else:
       self.txn_ptr = None
       if rev is None:
         rev = fs.youngest_rev(self.fs_ptr)
+      else:
+        rev = int(rev)
     self.rev = rev
 
-    getattr(self, 'cmd_' + cmd)()
+    if cmd != None:
+      getattr(self, 'cmd_' + cmd)()
 
   def cmd_default(self):
     self.cmd_info()
     self.cmd_tree()
 
   def cmd_author(self):
-    # get the author property, or empty string if the property is not present
-    author = self._get_property(core.SVN_PROP_REVISION_AUTHOR) or ''
-    print(author)
+    print(self.get_author() or '')
 
   def cmd_changed(self):
-    self._print_tree(ChangedEditor, pass_root=1)
+    for status, path in self.get_changed():
+      print("%-3s %s" % (status, path))
 
   def cmd_date(self):
-    if self.txn_ptr:
+    # duplicate original svnlook format, which is
+    # 2010-02-08 21:53:15 +0200 (Mon, 08 Feb 2010)
+    secs = self.get_date(unixtime=True)
+    if secs is None:
       print("")
     else:
-      date = self._get_property(core.SVN_PROP_REVISION_DATE)
-      if date:
-        aprtime = core.svn_time_from_cstring(date)
-        # ### convert to a time_t; this requires intimate knowledge of
-        # ### the apr_time_t type
-        secs = aprtime / 1000000  # aprtime is microseconds; make seconds
-
-        # assume secs in local TZ, convert to tuple, and format
-        ### we don't really know the TZ, do we?
-        print(time.strftime('%Y-%m-%d %H:%M', time.localtime(secs)))
-      else:
-        print("")
+      # convert to tuple, detect time zone and format
+      stamp = time.localtime(secs)
+      isdst = stamp.tm_isdst
+      utcoffset = -(time.altzone if (time.daylight and isdst) else time.timezone) // 60
+
+      suffix = "%+03d%02d" % (utcoffset // 60, abs(utcoffset) % 60)
+      outstr = time.strftime('%Y-%m-%d %H:%M:%S ', stamp) + suffix
+      outstr += time.strftime(' (%a, %d %b %Y)', stamp)
+      print(outstr)
+
 
   def cmd_diff(self):
     self._print_tree(DiffEditor, pass_root=1)
 
   def cmd_dirs_changed(self):
-    self._print_tree(DirsChangedEditor)
+    for dir in self.get_changed_dirs():
+      print(dir)
 
   def cmd_ids(self):
     self._print_tree(Editor, base_rev=0, pass_root=1)
 
   def cmd_info(self):
+    """print the author, data, log_size, and log message"""
     self.cmd_author()
     self.cmd_date()
-    self.cmd_log(1)
-
-  def cmd_log(self, print_size=0):
-    # get the log property, or empty string if the property is not present
-    log = self._get_property(core.SVN_PROP_REVISION_LOG) or ''
-    if print_size:
-      print(len(log))
+    log = self.get_log() or ''
+    print(len(log))
     print(log)
 
+  def cmd_log(self):
+    print(self.get_log() or '')
+
   def cmd_tree(self):
     self._print_tree(Editor, base_rev=0)
 
+
+  # --- API getters
+  def get_author(self):
+    """return string with the author name or None"""
+    return self._get_property(core.SVN_PROP_REVISION_AUTHOR)
+
+  def get_changed(self):
+    """return list of tuples (status, path)"""
+    ret = []
+    def list_callback(status, path):
+      ret.append( (status, path) )
+    self._walk_tree(ChangedEditor, pass_root=1, callback=list_callback)
+    return ret
+
+  def get_date(self, unixtime=False):
+    """return commit timestamp in RFC 3339 format (2010-02-08T20:37:25.195000Z)
+       if unixtime is True, return unix timestamp
+       return None for a txn, or if date property is not set
+    """
+    if self.txn_ptr:
+      return None
+
+    date = self._get_property(core.SVN_PROP_REVISION_DATE)
+    if not unixtime or date == None:
+      return date
+
+    # convert to unix time
+    aprtime = core.svn_time_from_cstring(date)
+    # ### convert to a time_t; this requires intimate knowledge of
+    # ### the apr_time_t type
+    secs = aprtime / 1000000  # aprtime is microseconds; make seconds
+    return secs
+
+  def get_changed_dirs(self):
+    """return list of changed dirs
+       dir names end with trailing forward slash even on windows
+    """
+    dirlist = []
+    def list_callback(item):
+      dirlist.append(item)
+    self._walk_tree(DirsChangedEditor, callback=list_callback)
+    return dirlist
+
+  def get_log(self):
+    """return log message string or None if not present"""
+    return self._get_property(core.SVN_PROP_REVISION_LOG)
+
+
+  # --- Internal helpers
   def _get_property(self, name):
     if self.txn_ptr:
       return fs.txn_prop(self.txn_ptr, name)
     return fs.revision_prop(self.fs_ptr, self.rev, name)
 
   def _print_tree(self, e_factory, base_rev=None, pass_root=0):
+    def print_callback(msg):
+       print(msg)
+    self._walk_tree(e_factory, base_rev, pass_root, callback=print_callback)
+
+  # svn fs, delta, repos calls needs review according to DeltaEditor documentation
+  def _walk_tree(self, e_factory, base_rev=None, pass_root=0, callback=None):
     if base_rev is None:
       # a specific base rev was not provided. use the transaction base,
       # or the previous revision
       if self.txn_ptr:
         base_rev = fs.txn_base_revision(self.txn_ptr)
+      elif self.rev == 0:
+        base_rev = 0
       else:
         base_rev = self.rev - 1
 
@@ -120,10 +217,13 @@ class SVNLook:
     # the base of the comparison
     base_root = fs.revision_root(self.fs_ptr, base_rev)
 
+    if callback == None:
+      callback = lambda msg: None
+
     if pass_root:
-      editor = e_factory(root, base_root)
+      editor = e_factory(root, base_root, callback)
     else:
-      editor = e_factory()
+      editor = e_factory(callback=callback)
 
     # construct the editor for printing these things out
     e_ptr, e_baton = delta.make_editor(editor)
@@ -135,8 +235,17 @@ class SVNLook:
 		    e_ptr, e_baton, authz_cb, 0, 1, 0, 0)
 
 
+# ---------------------------------------------------------
+# Delta Editors. For documentation see:
+# http://subversion.apache.org/docs/community-guide/#docs
+
+# this one doesn't process delete_entry, change_dir_prop, apply_text_delta,
+# change_file_prop, close_file, close_edit, abort_edit
+# ?set_target_revision
+# need review
 class Editor(delta.Editor):
-  def __init__(self, root=None, base_root=None):
+  def __init__(self, root=None, base_root=None, callback=None):
+    """callback argument is unused for this editor"""
     self.root = root
     # base_root ignored
 
@@ -172,7 +281,14 @@ class Editor(delta.Editor):
       return ' <%s>' % fs.unparse_id(id)
     return ''
 
+# doesn't process close_directory, apply_text_delta,
+# change_file_prop, close_file, close_edit, abort_edit
+# ?set_target_revision
 class DirsChangedEditor(delta.Editor):
+  """print names of changed dirs, callback(dir) is a printer function"""
+  def __init__(self, callback):
+    self.callback = callback
+
   def open_root(self, base_revision, dir_pool):
     return [ 1, '' ]
 
@@ -201,13 +317,15 @@ class DirsChangedEditor(delta.Editor):
   def _dir_changed(self, baton):
     if baton[0]:
       # the directory hasn't been printed yet. do it.
-      print(baton[1] + '/')
+      self.callback(baton[1] + '/')
       baton[0] = 0
 
 class ChangedEditor(delta.Editor):
-  def __init__(self, root, base_root):
+  def __init__(self, root, base_root, callback):
+    """callback(status, path) is a printer function"""
     self.root = root
     self.base_root = base_root
+    self.callback = callback
 
   def open_root(self, base_revision, dir_pool):
     return [ 1, '' ]
@@ -215,13 +333,13 @@ class ChangedEditor(delta.Editor):
   def delete_entry(self, path, revision, parent_baton, pool):
     ### need more logic to detect 'replace'
     if fs.is_dir(self.base_root, '/' + path):
-      print('D   ' + path + '/')
+      self.callback('D', path + '/')
     else:
-      print('D   ' + path)
+      self.callback('D', path)
 
   def add_directory(self, path, parent_baton,
                     copyfrom_path, copyfrom_revision, dir_pool):
-    print('A   ' + path + '/')
+    self.callback('A', path + '/')
     return [ 0, path ]
 
   def open_directory(self, path, parent_baton, base_revision, dir_pool):
@@ -230,12 +348,12 @@ class ChangedEditor(delta.Editor):
   def change_dir_prop(self, dir_baton, name, value, pool):
     if dir_baton[0]:
       # the directory hasn't been printed yet. do it.
-      print('_U  ' + dir_baton[1] + '/')
+      self.callback('_U', dir_baton[1] + '/')
       dir_baton[0] = 0
 
   def add_file(self, path, parent_baton,
                copyfrom_path, copyfrom_revision, file_pool):
-    print('A   ' + path)
+    self.callback('A', path)
     return [ '_', ' ', None ]
 
   def open_file(self, path, parent_baton, base_revision, file_pool):
@@ -257,11 +375,12 @@ class ChangedEditor(delta.Editor):
       status = text_mod + prop_mod
       # was there some kind of change?
       if status != '_ ':
-        print(status + '  ' + path)
+        self.callback(status.rstrip(), path)
 
 
 class DiffEditor(delta.Editor):
-  def __init__(self, root, base_root):
+  def __init__(self, root, base_root, callback=None):
+    """callback argument is unused for this editor"""
     self.root = root
     self.base_root = base_root
     self.target_revision = 0
@@ -435,7 +554,7 @@ def main():
   if not hasattr(SVNLook, 'cmd_' + cmd):
     usage(1)
 
-  SVNLook(sys.argv[1], cmd, rev, txn)
+  SVNLook(sys.argv[1], rev, txn, cmd)
 
 if __name__ == '__main__':
   main()

Propchange: subversion/branches/verify-keep-going/tools/examples/svnlook.py
------------------------------------------------------------------------------
    svn:keywords = URL Date Revision

Modified: subversion/branches/verify-keep-going/tools/server-side/fsfs-stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/server-side/fsfs-stats.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/server-side/fsfs-stats.c (original)
+++ subversion/branches/verify-keep-going/tools/server-side/fsfs-stats.c Wed Nov 27 11:52:35 2013
@@ -28,6 +28,7 @@
 #include <apr_file_io.h>
 #include <apr_poll.h>
 
+#include "svn_private_config.h"
 #include "svn_pools.h"
 #include "svn_diff.h"
 #include "svn_io.h"
@@ -270,6 +271,12 @@ typedef struct fs_fs_t
   /* history of sizes of changed nodes */
   histogram_t node_size_histogram;
 
+  /* history of representation sizes */
+  histogram_t added_rep_size_histogram;
+
+  /* history of sizes of changed nodes */
+  histogram_t added_node_size_histogram;
+
   /* history of unused representations */
   histogram_t unused_rep_histogram;
 
@@ -486,6 +493,7 @@ add_to_histogram(histogram_t *histogram,
 
 /* Update data aggregators in FS with this representation of type KIND, on-
  * disk REP_SIZE and expanded node size EXPANDED_SIZE for PATH in REVSION.
+ * PLAIN_ADDED indicates whether the node has a deltification predecessor.
  */
 static void
 add_change(fs_fs_t *fs,
@@ -493,7 +501,8 @@ add_change(fs_fs_t *fs,
            apr_int64_t expanded_size,
            svn_revnum_t revision,
            const char *path,
-           rep_kind_t kind)
+           rep_kind_t kind,
+           svn_boolean_t plain_added)
 {
   /* identify largest reps */
   if (rep_size >= fs->largest_changes->min_size)
@@ -522,6 +531,12 @@ add_change(fs_fs_t *fs,
   add_to_histogram(&fs->rep_size_histogram, rep_size);
   add_to_histogram(&fs->node_size_histogram, expanded_size);
 
+  if (plain_added)
+    {
+      add_to_histogram(&fs->added_rep_size_histogram, rep_size);
+      add_to_histogram(&fs->added_node_size_histogram, expanded_size);
+    }
+
   /* specific histograms by type */
   switch (kind)
     {
@@ -1120,8 +1135,8 @@ get_combined_window(svn_stringbuf_t **co
   apr_array_header_t *windows;
   svn_stringbuf_t *base_content, *result;
   const char *source;
-  apr_pool_t *sub_pool;
-  apr_pool_t *iter_pool;
+  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
 
   /* special case: no un-deltification necessary */
   if (representation->is_plain)
@@ -1138,16 +1153,16 @@ get_combined_window(svn_stringbuf_t **co
     return SVN_NO_ERROR;
 
   /* read the delta windows for this representation */
-  sub_pool = svn_pool_create(pool);
-  iter_pool = svn_pool_create(pool);
-  SVN_ERR(read_windows(&windows, fs, representation, file_content, sub_pool));
+  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(pool);
+  SVN_ERR(read_windows(&windows, fs, representation, file_content, subpool));
 
   /* fetch the / create a base content */
   if (representation->delta_base && representation->delta_base->revision)
     SVN_ERR(get_combined_window(&base_content, fs,
-                                representation->delta_base, NULL, sub_pool));
+                                representation->delta_base, NULL, subpool));
   else
-    base_content = svn_stringbuf_create_empty(sub_pool);
+    base_content = svn_stringbuf_create_empty(subpool);
 
   /* apply deltas */
   result = svn_stringbuf_create_empty(pool);
@@ -1158,7 +1173,7 @@ get_combined_window(svn_stringbuf_t **co
       svn_txdelta_window_t *window
         = APR_ARRAY_IDX(windows, i, svn_txdelta_window_t *);
       svn_stringbuf_t *buf
-        = svn_stringbuf_create_ensure(window->tview_len, iter_pool);
+        = svn_stringbuf_create_ensure(window->tview_len, iterpool);
 
       buf->len = window->tview_len;
       svn_txdelta_apply_instructions(window, window->src_ops ? source : NULL,
@@ -1167,15 +1182,15 @@ get_combined_window(svn_stringbuf_t **co
       svn_stringbuf_appendbytes(result, buf->data, buf->len);
       source += window->sview_len;
 
-      svn_pool_clear(iter_pool);
+      svn_pool_clear(iterpool);
     }
 
   /* cache result and return it */
-  SVN_ERR(set_cached_window(fs, representation, result, sub_pool));
+  SVN_ERR(set_cached_window(fs, representation, result, subpool));
   *content = result;
 
-  svn_pool_destroy(iter_pool);
-  svn_pool_destroy(sub_pool);
+  svn_pool_destroy(iterpool);
+  svn_pool_destroy(subpool);
 
   return SVN_NO_ERROR;
 }
@@ -1204,7 +1219,7 @@ parse_dir(fs_fs_t *fs,
           apr_pool_t *scratch_pool)
 {
   svn_stringbuf_t *text;
-  apr_pool_t *iter_pool;
+  apr_pool_t *iterpool;
   apr_pool_t *text_pool;
   const char *current;
   const char *revision_key;
@@ -1215,7 +1230,7 @@ parse_dir(fs_fs_t *fs,
     return SVN_NO_ERROR;
 
   /* get the directory as unparsed string */
-  iter_pool = svn_pool_create(scratch_pool);
+  iterpool = svn_pool_create(scratch_pool);
   text_pool = svn_pool_create(scratch_pool);
 
   SVN_ERR(get_combined_window(&text, fs, representation, file_content,
@@ -1240,7 +1255,7 @@ parse_dir(fs_fs_t *fs,
       next = current ? strchr(++current, '\n') : NULL;
       if (next == NULL)
         return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-           _("Corrupt directory representation in rev %ld at offset %ld"),
+           _("Corrupt directory representation in r%ld at offset %ld"),
                                  representation->revision,
                                  (long)representation->offset);
 
@@ -1256,14 +1271,14 @@ parse_dir(fs_fs_t *fs,
           SVN_ERR(svn_cstring_strtoui64(&offset, current + key_len, 0,
                                         APR_SIZE_MAX, 10));
           SVN_ERR(read_noderev(fs, file_content, (apr_size_t)offset,
-                               revision_info, pool, iter_pool));
+                               revision_info, pool, iterpool));
 
-          svn_pool_clear(iter_pool);
+          svn_pool_clear(iterpool);
         }
       current = next+1;
     }
 
-  svn_pool_destroy(iter_pool);
+  svn_pool_destroy(iterpool);
   svn_pool_destroy(text_pool);
   return SVN_NO_ERROR;
 }
@@ -1288,6 +1303,7 @@ read_noderev(fs_fs_t *fs,
   representation_t *props = NULL;
   apr_size_t start_offset = offset;
   svn_boolean_t is_dir = FALSE;
+  svn_boolean_t has_predecessor = FALSE;
   const char *path = "???";
 
   scratch_pool = svn_pool_create(scratch_pool);
@@ -1348,15 +1364,17 @@ read_noderev(fs_fs_t *fs,
         }
       else if (key_matches(&key, "cpath"))
         path = value.data;
+      else if (key_matches(&key, "pred"))
+        has_predecessor = TRUE;
     }
 
   /* record largest changes */
   if (text && text->ref_count == 1)
     add_change(fs, (apr_int64_t)text->size, (apr_int64_t)text->expanded_size,
-               text->revision, path, text->kind);
+               text->revision, path, text->kind, !has_predecessor);
   if (props && props->ref_count == 1)
     add_change(fs, (apr_int64_t)props->size, (apr_int64_t)props->expanded_size,
-               props->revision, path, props->kind);
+               props->revision, path, props->kind, !has_predecessor);
 
   /* if this is a directory and has not been processed, yet, read and
    * process it recursively */
@@ -1573,7 +1591,9 @@ read_revisions(fs_fs_t **fs,
                                             svn_cache__get_global_membuffer_cache(),
                                             NULL, NULL,
                                             sizeof(window_cache_key_t),
-                                            "", FALSE, pool));
+                                            "",
+                                            SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+                                            FALSE, pool));
 
   /* read all packed revs */
   for ( revision = start_revision
@@ -2043,6 +2063,7 @@ print_stats(fs_fs_t *fs,
   printf(_("%20s bytes in %12s representations total\n"
            "%20s bytes in %12s directory representations\n"
            "%20s bytes in %12s file representations\n"
+           "%20s bytes in %12s representations of added file nodes\n"
            "%20s bytes in %12s directory property representations\n"
            "%20s bytes in %12s file property representations\n"
            "%20s bytes in header & footer overhead\n"),
@@ -2052,6 +2073,8 @@ print_stats(fs_fs_t *fs,
          svn__i64toa_sep(dir_rep_stats.total.count, ',', pool),
          svn__i64toa_sep(file_rep_stats.total.packed_size, ',', pool),
          svn__i64toa_sep(file_rep_stats.total.count, ',', pool),
+         svn__i64toa_sep(fs->added_rep_size_histogram.total.sum, ',', pool),
+         svn__i64toa_sep(fs->added_rep_size_histogram.total.count, ',', pool),
          svn__i64toa_sep(dir_prop_rep_stats.total.packed_size, ',', pool),
          svn__i64toa_sep(dir_prop_rep_stats.total.count, ',', pool),
          svn__i64toa_sep(file_prop_rep_stats.total.packed_size, ',', pool),

Modified: subversion/branches/verify-keep-going/tools/server-side/mod_dontdothat/mod_dontdothat.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/server-side/mod_dontdothat/mod_dontdothat.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/server-side/mod_dontdothat/mod_dontdothat.c (original)
+++ subversion/branches/verify-keep-going/tools/server-side/mod_dontdothat/mod_dontdothat.c Wed Nov 27 11:52:35 2013
@@ -30,12 +30,15 @@
 #include <util_filter.h>
 #include <ap_config.h>
 #include <apr_strings.h>
+#include <apr_uri.h>
 
 #include <expat.h>
 
 #include "mod_dav_svn.h"
 #include "svn_string.h"
 #include "svn_config.h"
+#include "svn_path.h"
+#include "private/svn_fspath.h"
 
 module AP_MODULE_DECLARE_DATA dontdothat_module;
 
@@ -161,26 +164,71 @@ matches(const char *wc, const char *p)
     }
 }
 
+/* duplicate of dav_svn__log_err() from mod_dav_svn/util.c */
+static void
+log_dav_err(request_rec *r,
+            dav_error *err,
+            int level)
+{
+    dav_error *errscan;
+
+    /* Log the errors */
+    /* ### should have a directive to log the first or all */
+    for (errscan = err; errscan != NULL; errscan = errscan->prev) {
+        apr_status_t status;
+
+        if (errscan->desc == NULL)
+            continue;
+
+#if AP_MODULE_MAGIC_AT_LEAST(20091119,0)
+        status = errscan->aprerr;
+#else
+        status = errscan->save_errno;
+#endif
+
+        ap_log_rerror(APLOG_MARK, level, status, r,
+                      "%s  [%d, #%d]",
+                      errscan->desc, errscan->status, errscan->error_id);
+    }
+}
+
 static svn_boolean_t
 is_this_legal(dontdothat_filter_ctx *ctx, const char *uri)
 {
   const char *relative_path;
   const char *cleaned_uri;
   const char *repos_name;
+  const char *uri_path;
   int trailing_slash;
   dav_error *derr;
 
-  /* Ok, so we need to skip past the scheme, host, etc. */
-  uri = ap_strstr_c(uri, "://");
-  if (uri)
-    uri = ap_strchr_c(uri + 3, '/');
+  /* uri can be an absolute uri or just a path, we only want the path to match
+   * against */
+  if (uri && svn_path_is_url(uri))
+    {
+      apr_uri_t parsed_uri;
+      apr_status_t rv = apr_uri_parse(ctx->r->pool, uri, &parsed_uri);
+      if (APR_SUCCESS != rv)
+        {
+          /* Error parsing the URI, log and reject request. */
+          ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, ctx->r,
+                        "mod_dontdothat: blocked request after failing "
+                        "to parse uri: '%s'", uri);
+          return FALSE;
+        }
+      uri_path = parsed_uri.path;
+    }
+  else
+    {
+      uri_path = uri;
+    }
 
-  if (uri)
+  if (uri_path)
     {
       const char *repos_path;
 
       derr = dav_svn_split_uri(ctx->r,
-                               uri,
+                               uri_path,
                                ctx->cfg->base_path,
                                &cleaned_uri,
                                &trailing_slash,
@@ -194,7 +242,7 @@ is_this_legal(dontdothat_filter_ctx *ctx
           if (! repos_path)
             repos_path = "";
 
-          repos_path = apr_psprintf(ctx->r->pool, "/%s", repos_path);
+          repos_path = svn_fspath__canonicalize(repos_path, ctx->r->pool);
 
           /* First check the special cases that are always legal... */
           for (idx = 0; idx < ctx->allow_recursive_ops->nelts; ++idx)
@@ -228,6 +276,19 @@ is_this_legal(dontdothat_filter_ctx *ctx
                 }
             }
         }
+      else
+        {
+          log_dav_err(ctx->r, derr, APLOG_ERR);
+          return FALSE;
+        }
+
+    }
+  else
+    {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r,
+                    "mod_dontdothat: empty uri passed to is_this_legal(), "
+                    "module bug?");
+      return FALSE;
     }
 
   return TRUE;

Modified: subversion/branches/verify-keep-going/tools/server-side/svn-populate-node-origins-index.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/server-side/svn-populate-node-origins-index.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/server-side/svn-populate-node-origins-index.c (original)
+++ subversion/branches/verify-keep-going/tools/server-side/svn-populate-node-origins-index.c Wed Nov 27 11:52:35 2013
@@ -94,7 +94,9 @@ index_revision_adds(int *count, svn_fs_t
       apr_hash_this(hi, &path, NULL, &val);
       change = val;
       if ((change->change_kind == svn_fs_path_change_add)
-          || (change->change_kind == svn_fs_path_change_replace))
+          || (change->change_kind == svn_fs_path_change_replace)
+          || (change->change_kind == svn_fs_path_change_move)
+          || (change->change_kind == svn_fs_path_change_movereplace))
         {
           if (! (change->copyfrom_path
                             && SVN_IS_VALID_REVNUM(change->copyfrom_rev)))

Modified: subversion/branches/verify-keep-going/tools/server-side/svn-rep-sharing-stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/tools/server-side/svn-rep-sharing-stats.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/tools/server-side/svn-rep-sharing-stats.c (original)
+++ subversion/branches/verify-keep-going/tools/server-side/svn-rep-sharing-stats.c Wed Nov 27 11:52:35 2013
@@ -33,6 +33,7 @@
 #include "../../subversion/libsvn_fs_fs/fs_fs.h"
 /* for svn_fs_fs__id_* (used in assertions only) */
 #include "../../subversion/libsvn_fs_fs/id.h"
+#include "../../subversion/libsvn_fs_fs/cached_data.h"
 
 #include "private/svn_cmdline_private.h"
 
@@ -78,7 +79,6 @@ help(const apr_getopt_option_t *options,
       ++options;
     }
   svn_error_clear(svn_cmdline_fprintf(stdout, pool, "\n"));
-  exit(0);
 }
 
 
@@ -95,7 +95,8 @@ check_lib_versions(void)
     };
   SVN_VERSION_DEFINE(my_version);
 
-  return svn_error_trace(svn_ver_check_list(&my_version, checklist));
+  return svn_error_trace(svn_ver_check_list2(&my_version, checklist,
+                                             svn_ver_equal));
 }
 
 
@@ -182,7 +183,8 @@ struct key_t
 /* What we need to know about a rep. */
 struct value_t
 {
-  svn_checksum_t *sha1_checksum;
+  svn_checksum_t checksum;
+  unsigned char sha1_digest[APR_SHA1_DIGESTSIZE];
   apr_uint64_t refcount;
 };
 
@@ -200,7 +202,7 @@ static svn_error_t *record(apr_hash_t *r
    * exist or doesn't have the checksum we are after.  (The latter case
    * often corresponds to node_rev->kind == svn_node_dir.)
    */
-  if (records == NULL || rep == NULL || rep->sha1_checksum == NULL)
+  if (records == NULL || rep == NULL || !rep->has_sha1)
     return SVN_NO_ERROR;
 
   /* Construct the key.
@@ -215,17 +217,19 @@ static svn_error_t *record(apr_hash_t *r
   if ((value = apr_hash_get(records, key, sizeof(*key))))
     {
       /* Paranoia. */
-      SVN_ERR_ASSERT(value->sha1_checksum != NULL);
-      SVN_ERR_ASSERT(svn_checksum_match(value->sha1_checksum,
-                                        rep->sha1_checksum));
+      SVN_ERR_ASSERT(memcmp(value->sha1_digest,
+                            rep->sha1_digest,
+                            sizeof(value->sha1_digest)));
       /* Real work. */
       value->refcount++;
     }
   else
     {
       value = apr_palloc(result_pool, sizeof(*value));
-      value->sha1_checksum = svn_checksum_dup(rep->sha1_checksum, result_pool);
+      value->checksum.digest = value->sha1_digest;
+      value->checksum.kind = svn_checksum_sha1;
       value->refcount = 1;
+      memcpy(value->sha1_digest, rep->sha1_digest, sizeof(value->sha1_digest));
     }
 
   /* Store them. */
@@ -340,7 +344,7 @@ pretty_print(const char *name,
       SVN_ERR(svn_cmdline_printf(scratch_pool, "%s %" APR_UINT64_T_FMT " %s\n",
                                  name, value->refcount,
                                  svn_checksum_to_cstring_display(
-                                   value->sha1_checksum,
+                                   &value->checksum,
                                    scratch_pool)));
     }
 
@@ -419,14 +423,17 @@ static svn_error_t *process(const char *
   return SVN_NO_ERROR;
 }
 
-int
-main(int argc, const char *argv[])
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
 {
   const char *repos_path;
-  apr_pool_t *pool;
   svn_boolean_t prop = FALSE, data = FALSE;
   svn_boolean_t quiet = FALSE;
-  svn_error_t *err;
   apr_getopt_t *os;
   const apr_getopt_option_t options[] =
     {
@@ -440,25 +447,12 @@ main(int argc, const char *argv[])
       {0,             0,  0,  0}
     };
 
-  /* Initialize the app. */
-  if (svn_cmdline_init("svn-rep-sharing-stats", stderr) != EXIT_SUCCESS)
-    return EXIT_FAILURE;
-
-  /* Create our top-level pool.  Use a separate mutexless allocator,
-   * given this application is single threaded.
-   */
-  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
-
   /* Check library versions */
-  err = check_lib_versions();
-  if (err)
-    return svn_cmdline_handle_exit_error(err, pool, "svn-rep-sharing-stats: ");
+  SVN_ERR(check_lib_versions());
 
-  err = svn_cmdline__getopt_init(&os, argc, argv, pool);
-  if (err)
-    return svn_cmdline_handle_exit_error(err, pool, "svn-rep-sharing-stats: ");
+  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
 
-  SVN_INT_ERR(check_experimental());
+  SVN_ERR(check_experimental());
 
   os->interleave = 1;
   while (1)
@@ -471,7 +465,8 @@ main(int argc, const char *argv[])
       if (status != APR_SUCCESS)
         {
           usage(pool);
-          return EXIT_FAILURE;
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
       switch (opt)
         {
@@ -491,14 +486,14 @@ main(int argc, const char *argv[])
           break;
         case 'h':
           help(options, pool);
-          break;
+          return SVN_NO_ERROR;
         case OPT_VERSION:
-          SVN_INT_ERR(version(pool));
-          exit(0);
-          break;
+          SVN_ERR(version(pool));
+          return SVN_NO_ERROR;
         default:
           usage(pool);
-          return EXIT_FAILURE;
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
     }
 
@@ -508,23 +503,51 @@ main(int argc, const char *argv[])
   if (os->ind + 1 != argc || (!data && !prop))
     {
       usage(pool);
-      return EXIT_FAILURE;
+      *exit_code = EXIT_FAILURE;
+      return SVN_NO_ERROR;
     }
 
   /* Grab REPOS_PATH from argv. */
-  SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_path, os->argv[os->ind], pool));
+  SVN_ERR(svn_utf_cstring_to_utf8(&repos_path, os->argv[os->ind], pool));
   repos_path = svn_dirent_internal_style(repos_path, pool);
 
   set_up_cancellation();
 
   /* Do something. */
-  SVN_INT_ERR(process(repos_path, prop, data, quiet, pool));
+  SVN_ERR(process(repos_path, prop, data, quiet, pool));
 
   /* We're done. */
+  return SVN_NO_ERROR;
+}
 
-  svn_pool_destroy(pool);
-  /* Flush stdout to make sure that the user will see any printing errors. */
-  SVN_INT_ERR(svn_cmdline_fflush(stdout));
+int
+main(int argc, const char *argv[])
+{
+  apr_pool_t *pool;
+  int exit_code = EXIT_SUCCESS;
+  svn_error_t *err;
+
+  /* Initialize the app. */
+  if (svn_cmdline_init("svn-rep-sharing-stats", stderr) != EXIT_SUCCESS)
+    return EXIT_FAILURE;
+
+  /* Create our top-level pool.  Use a separate mutexless allocator,
+   * given this application is single threaded.
+   */
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+
+  err = sub_main(&exit_code, argc, argv, pool);
+
+  /* Flush stdout and report if it fails. It would be flushed on exit anyway
+     but this makes sure that output is not silently lost if it fails. */
+  err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
 
-  return EXIT_SUCCESS;
+  if (err)
+    {
+      exit_code = EXIT_FAILURE;
+      svn_cmdline_handle_exit_error(err, NULL, "svn-rep-sharing-stats: ");
+    }
+
+  svn_pool_destroy(pool);
+  return exit_code;
 }