You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2013/08/19 13:21:06 UTC

svn commit: r1515362 [13/13] - in /subversion/branches/move-tracking-1: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ notes/tree-conflicts/ subversion/bindings/cxxhl/include/ subversion/bindings/cxxhl/include/svncxxhl/ subversi...

Modified: subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.c (original)
+++ subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.c Mon Aug 19 11:21:01 2013
@@ -33,6 +33,7 @@
 #include "svn_fs.h"
 #include "svn_path.h"
 #include "svn_delta.h"
+#include "svn_hash.h"
 
 #include "svn_test_fs.h"
 
@@ -81,8 +82,8 @@ make_fs_config(const char *fs_type,
                fs_type);
   if (server_minor_version)
     {
-      if (server_minor_version == 6)
-        /* no SVN_FS_CONFIG_PRE_1_7_COMPATIBLE */;
+      if (server_minor_version == 6 || server_minor_version == 7)
+        svn_hash_sets(fs_config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE, "1");
       else if (server_minor_version == 5)
         apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
                      APR_HASH_KEY_STRING, "1");
@@ -354,6 +355,8 @@ get_dir_entries(apr_hash_t *tree_entries
 }
 
 
+/* Verify that PATH under ROOT is: a directory if contents is NULL;
+   a file with contents CONTENTS otherwise. */
 static svn_error_t *
 validate_tree_entry(svn_fs_root_t *root,
                     const char *path,
@@ -515,6 +518,42 @@ svn_test__validate_tree(svn_fs_root_t *r
 
 
 svn_error_t *
+svn_test__validate_changes(svn_fs_root_t *root,
+                           apr_hash_t *expected,
+                           apr_pool_t *pool)
+{
+  apr_hash_t *actual;
+  apr_hash_index_t *hi;
+
+  SVN_ERR(svn_fs_paths_changed2(&actual, root, pool));
+
+#if 0
+  /* Print ACTUAL and EXPECTED. */
+  {
+    int i;
+    for (i=0, hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
+      SVN_DBG(("expected[%d] = '%s'\n", i++, svn__apr_hash_index_key(hi)));
+    for (i=0, hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
+      SVN_DBG(("actual[%d] = '%s'\n", i++, svn__apr_hash_index_key(hi)));
+  }
+#endif
+
+  for (hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
+    if (NULL == svn_hash_gets(actual, svn__apr_hash_index_key(hi)))
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Path '%s' missing from actual changed-paths",
+                               svn__apr_hash_index_key(hi));
+
+  for (hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
+    if (NULL == svn_hash_gets(expected, svn__apr_hash_index_key(hi)))
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Path '%s' missing from expected changed-paths",
+                               svn__apr_hash_index_key(hi));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_test__txn_script_exec(svn_fs_root_t *txn_root,
                           svn_test__txn_script_command_t *script,
                           int num_edits,

Modified: subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.h?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.h (original)
+++ subversion/branches/move-tracking-1/subversion/tests/svn_test_fs.h Mon Aug 19 11:21:01 2013
@@ -112,6 +112,14 @@ svn_test__validate_tree(svn_fs_root_t *r
                         int num_entries,
                         apr_pool_t *pool);
 
+/* Verify that svn_fs_paths_changed2(ROOT) returns a hash with exactly
+   the same keys as EXPECTED_KEYS.  Values are not currently verified.
+ */
+svn_error_t *
+svn_test__validate_changes(svn_fs_root_t *root,
+                           apr_hash_t *expected_keys,
+                           apr_pool_t *pool);
+
 /* Structure for describing script-ish commands to perform on a
    transaction using svn_test__txn_script_exec().  */
 typedef struct svn_test__txn_script_command_t

Modified: subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd (original)
+++ subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd Mon Aug 19 11:21:01 2013
@@ -59,6 +59,7 @@ taskkill /im svnsync.exe /f 2> nul:
 taskkill /im httpd.exe /f 2> nul:
 taskkill /im fs-test.exe /f 2> nul:
 taskkill /im op-depth-test.exe /f 2> nul:
+taskkill /im atomic-ra-revprop-change.exe /f 2> nul:
 taskkill /im java.exe /f 2> nul:
 taskkill /im perl.exe /f 2> nul:
 taskkill /im mspdbsrv.exe /f 2> nul:

Modified: subversion/branches/move-tracking-1/tools/client-side/svn-bench/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/client-side/svn-bench/help-cmd.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/client-side/svn-bench/help-cmd.c (original)
+++ subversion/branches/move-tracking-1/tools/client-side/svn-bench/help-cmd.c Mon Aug 19 11:21:01 2013
@@ -80,7 +80,7 @@ svn_cl__help(apr_getopt_t *os,
   SVN_ERR(svn_ra_print_modules(version_footer, pool));
 
   return svn_opt_print_help4(os,
-                             "svn",   /* ### erm, derive somehow? */
+                             "svn-bench",   /* ### erm, derive somehow? */
                              opt_state ? opt_state->version : FALSE,
                              opt_state ? opt_state->quiet : FALSE,
                              opt_state ? opt_state->verbose : FALSE,

Modified: subversion/branches/move-tracking-1/tools/dev/po-merge.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/po-merge.py?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/po-merge.py (original)
+++ subversion/branches/move-tracking-1/tools/dev/po-merge.py Mon Aug 19 11:21:01 2013
@@ -146,6 +146,7 @@ def main(argv):
     string_count = 0
     update_count = 0
     untranslated = 0
+    fuzzy = 0
     while True:
         comments, msgid, msgid_plural, msgstr = parse_translation(infile)
         if not comments and msgid is None:
@@ -177,14 +178,19 @@ def main(argv):
                 for i in msgstr:
                     outfile.write('msgstr[%s] %s\n' % (n, msgstr[n]))
                     n += 1
-        for m in msgstr:
-            if m == '""':
-                untranslated += 1
+        if msgstr is not None:
+            for m in msgstr:
+                if m == '""':
+                    untranslated += 1
+        for c in comments:
+            if c.startswith('#,') and 'fuzzy' in c.split(', '):
+                fuzzy += 1
 
     # We're done.  Tell the user what we did.
     print(('%d strings updated. '
+          '%d fuzzy strings. ' 
           '%d of %d strings are still untranslated (%.0f%%).' %
-          (update_count, untranslated, string_count,
+          (update_count, fuzzy, untranslated, string_count,
            100.0 * untranslated / string_count)))
 
 if __name__ == '__main__':

Modified: subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn (original)
+++ subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn Mon Aug 19 11:21:01 2013
@@ -39,6 +39,7 @@ endif
 USE_APR_ICONV ?= no # set to yes to use APR iconv instead of GNU iconv
 PARALLEL ?= 1
 CLEANUP ?= 1
+EXCLUSIVE_WC_LOCKS ?= 1
 USE_HTTPV1 ?= no
 USE_AUTHZ_SHORT_CIRCUIT ?= no
 RAMDISK ?= /ramdisk
@@ -71,7 +72,7 @@ GNU_ICONV_VER	= 1.14
 APR_UTIL_VER	= 1.4.1
 HTTPD_VER	= 2.2.22
 NEON_VER	= 0.29.6
-SERF_VER	= 1.2.0
+SERF_VER	= 1.2.1
 SERF_OLD_VER	= 0.3.1
 CYRUS_SASL_VER	= 2.1.25
 SQLITE_VER	= 3071600
@@ -126,7 +127,7 @@ LIBMAGIC_URL	= ftp://ftp.astron.com/pub/
 RUBY_URL	= http://ftp.ruby-lang.org/pub/ruby/1.8/$(RUBY_DIST)
 BZ2_URL		= http://bzip.org/$(BZ2_VER)/$(BZ2_DIST)
 PYTHON_URL	= http://python.org/ftp/python/$(PYTHON_VER)/$(PYTHON_DIST)
-JUNIT_URL	= http://cloud.github.com/downloads/KentBeck/junit/$(JUNIT_DIST)
+JUNIT_URL	= http://downloads.sourceforge.net/project/junit/junit/$(JUNIT_VER)/$(JUNIT_DIST)
 
 
 BDB_SRCDIR	= $(SRCDIR)/db-$(BDB_VER)
@@ -1192,8 +1193,9 @@ else
 endif
 
 ifdef PROFILE
-SVN_ALL_STATIC=--enable-all-static
+SVN_STATIC_FLAG=--enable-all-static
 else
+SVN_STATIC_FLAG=--disable-static
 SVN_WITH_HTTPD=--with-apxs="$(PREFIX)/httpd/bin/apxs" \
 	--with-apache-libexecdir="$(PREFIX)/httpd/modules/svn-$(WC)"
 SVN_WITH_SASL=--with-sasl="$(PREFIX)/cyrus-sasl"
@@ -1223,7 +1225,7 @@ $(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)
 			--disable-mod-activation \
 			$(JAVAHL_FLAG) \
 			$(LIBMAGIC_FLAG) \
-			$(SVN_ALL_STATIC) \
+			$(SVN_STATIC_FLAG) \
 			$(DISABLE_NEON_VERSION_CHECK)
 	touch $@
 
@@ -1421,7 +1423,8 @@ 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) $1 FS_TYPE=$$fs; \
+        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; \
     done; \

Modified: subversion/branches/move-tracking-1/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dist/backport.pl?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dist/backport.pl (original)
+++ subversion/branches/move-tracking-1/tools/dist/backport.pl Mon Aug 19 11:21:01 2013
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -l
+#!/usr/bin/perl
 use warnings;
 use strict;
 use feature qw/switch say/;
@@ -21,6 +21,7 @@ use feature qw/switch say/;
 # under the License.
 
 use Term::ReadKey qw/ReadMode ReadKey/;
+use File::Copy qw/copy move/;
 use File::Temp qw/tempfile/;
 use POSIX qw/ctermid/;
 
@@ -28,10 +29,23 @@ my $SVN = $ENV{SVN} || 'svn'; # passed u
 my $VIM = 'vim';
 my $STATUS = './STATUS';
 my $BRANCHES = '^/subversion/branches';
+my %ERRORS = ();
 
-my $YES = $ENV{YES}; # batch mode: eliminate prompts, add sleeps
+my $YES = ($ENV{YES} // 0) ? 1 : 0; # batch mode: eliminate prompts, add sleeps
 my $MAY_COMMIT = qw[false true][0];
 my $DEBUG = qw[false true][0]; # 'set -x', etc
+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;
+  $_
+}
+// warn "Username for commits (of votes/merges) not found";
+my $EDITOR = $ENV{SVN_EDITOR} // $ENV{VISUAL} // $ENV{EDITOR} // 'ed';
+my $VERBOSE = 0;
 $DEBUG = 'true' if exists $ENV{DEBUG};
 $MAY_COMMIT = 'true' if ($ENV{MAY_COMMIT} // "false") =~ /^(1|yes|true)$/i;
 
@@ -50,13 +64,39 @@ sub usage {
   my $basename = $0;
   $basename =~ s#.*/##;
   print <<EOF;
-Run this from the root of your release branch (e.g., 1.6.x) working copy.
-
-For each entry in STATUS, you will be prompted whether to merge it.
-
-WARNING:
-If you accept the prompt, $basename will revert all local changes and will
-commit the merge immediately.
+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.
+
+In interactive mode (the default), you will be prompted once per STATUS entry.
+At a prompt, you have the following options:
+
+y:   Run a merge.  It will not be committed.
+     WARNING: This will run 'update' and 'revert -R ./'.
+q:   Quit the "for each nomination" loop.
+±1:  Enter a +1 or -1 vote
+     You will be prompted to commit your vote at the end.
+±0:  Enter a +0 or -0 vote
+     You will be prompted to commit your vote at the end.
+a:   Move the entry to the "Approved changes" section.
+     When both approving and voting on an entry, approve first: for example,
+     to enter a third +1 vote, type "a" "+" "1".
+e:   Edit the entry in $EDITOR.
+     You will be prompted to commit your edits at the end.
+N:   Move to the next entry.
+
+After running a merge, you have the following options:
+
+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
+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.
 
 The 'svn' binary defined by the environment variable \$SVN, or otherwise the
 'svn' found in \$PATH, will be used to manage the working copy.
@@ -64,15 +104,20 @@ EOF
 }
 
 sub prompt {
-  local $\; # disable 'perl -l' effects
   print "$_[0] "; shift;
   my %args = @_;
+  my $getchar = sub {
+    ReadMode 'cbreak';
+    my $answer = (ReadKey 0);
+    ReadMode 'cbreak';
+    print $answer;
+    return $answer;
+  };
 
   die "$0: called prompt() in non-interactive mode!" if $YES;
-  # TODO: this part was written by trial-and-error
-  ReadMode 'cbreak';
-  my $answer = (ReadKey 0);
-  print $answer, "\n";
+  my $answer = $getchar->();
+  $answer .= $getchar->() if exists $args{extra} and $answer =~ $args{extra};
+  say "";
   return $args{verbose}
          ? $answer
          : ($answer =~ /^y/i) ? 1 : 0;
@@ -91,26 +136,26 @@ sub merge {
     $pattern = sprintf '\V\(%s branch(es)?\|branches\/%s\|Branch\(es\)\?: \*\n\? \*%s\)', $entry{branch}, $entry{branch}, $entry{branch};
     if ($SVNvsn >= 1_008_000) {
       $mergeargs = "$BRANCHES/$entry{branch}";
-      print $logmsg_fh "Merge the $entry{header}:";
+      say $logmsg_fh "Merge the $entry{header}:";
     } else {
       $mergeargs = "--reintegrate $BRANCHES/$entry{branch}";
-      print $logmsg_fh "Reintegrate the $entry{header}:";
+      say $logmsg_fh "Reintegrate the $entry{header}:";
     }
-    print $logmsg_fh "";
+    say $logmsg_fh "";
   } elsif (@{$entry{revisions}}) {
     $pattern = '^ [*] \V' . 'r' . $entry{revisions}->[0];
     $mergeargs = join " ", (map { "-c$_" } @{$entry{revisions}}), '^/subversion/trunk';
     if (@{$entry{revisions}} > 1) {
-      print $logmsg_fh "Merge the $entry{header} from trunk:";
-      print $logmsg_fh "";
+      say $logmsg_fh "Merge the $entry{header} from trunk:";
+      say $logmsg_fh "";
     } else {
-      print $logmsg_fh "Merge r$entry{revisions}->[0] from trunk:";
-      print $logmsg_fh "";
+      say $logmsg_fh "Merge r$entry{revisions}->[0] from trunk:";
+      say $logmsg_fh "";
     }
   } else {
     die "Don't know how to call $entry{header}";
   }
-  print $logmsg_fh $_ for @{$entry{entry}};
+  say $logmsg_fh $_ for @{$entry{entry}};
   close $logmsg_fh or die "Can't close $logmsg_filename: $!";
 
   my $reintegrated_word = ($SVNvsn >= 1_008_000) ? "merged" : "reintegrated";
@@ -121,9 +166,11 @@ if $DEBUG; then
   set -x
 fi
 $SVN diff > $backupfile
-cp STATUS STATUS.$$
+if ! $MAY_COMMIT ; then
+  cp STATUS STATUS.$$
+fi
 $SVNq revert -R .
-if $MAY_COMMIT ; then
+if ! $MAY_COMMIT ; then
   mv STATUS.$$ STATUS
 fi
 $SVNq up
@@ -141,7 +188,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
-else
+elif test 1 -ne $YES; then
   echo "Would have committed:"
   echo '[[['
   $SVN status -q
@@ -158,16 +205,22 @@ 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
-else
-  echo "Removing $reintegrated_word '$entry{branch}' branch"
+elif test 1 -ne $YES; then
+  echo "Would remove $reintegrated_word '$entry{branch}' branch"
 fi
 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 $?;
+
+  if (-z $backupfile) {
+    unlink $backupfile;
+  } else {
+    warn "Local mods saved to '$backupfile'\n";
+  }
 
-  unlink $backupfile if -z $backupfile;
   unlink $logmsg_filename unless $? or $!;
 }
 
@@ -181,6 +234,7 @@ sub sanitize_branch {
 
 # TODO: may need to parse other headers too?
 sub parse_entry {
+  my $lines = shift;
   my @lines = @_;
   my (@revisions, @logsummary, $branch, @votes);
   # @lines = @_;
@@ -193,14 +247,18 @@ sub parse_entry {
   $branch = sanitize_branch $1
     if $_[0] =~ /^(\S*) branch$/ or $_[0] =~ m#branches/(\S+)#;
   while ($_[0] =~ /^r/) {
+    my $sawrevnum = 0;
     while ($_[0] =~ s/^r(\d+)(?:$|[,; ]+)//) {
       push @revisions, $1;
+      $sawrevnum++;
     }
-    shift;
+    $sawrevnum ? shift : last;
   }
 
   # summary
-  push @logsummary, shift until $_[0] =~ /^\s*\w+:/ or not defined $_[0];
+  do {
+    push @logsummary, shift
+  } until $_[0] =~ /^\s*\w+:/ or not defined $_[0];
 
   # votes
   unshift @votes, pop until $_[-1] =~ /^\s*Votes:/ or not defined $_[-1];
@@ -213,9 +271,11 @@ sub parse_entry {
   }
 
   # Compute a header.
-  my $header;
+  my ($header, $id);
   $header = "r$revisions[0] group" if @revisions;
-  $header = "$branch branch" if $branch;
+  $id = "r$revisions[0]"           if @revisions;
+  $header = "$branch branch"       if $branch;
+  $id = $branch                    if $branch;
   warn "No header for [@lines]" unless $header;
 
   return (
@@ -223,48 +283,207 @@ sub parse_entry {
     logsummary => [@logsummary],
     branch => $branch,
     header => $header,
+    id => $id,
     votes => [@votes],
     entry => [@lines],
+    raw => $lines,
   );
 }
 
+sub edit_string {
+  # Edits $_[0] in an editor.
+  # $_[1] is used in error messages.
+  die "$0: called edit_string() in non-interactive mode!" if $YES;
+  my $string = shift;
+  my $name = shift;
+  my ($fh, $fn) = tempfile;
+  print $fh $string;
+  $fh->flush or die $!;
+  system("$EDITOR -- $fn") == 0
+    or warn "\$EDITOR failed editing $name: $! ($?); "
+           ."edit results ($fn) ignored.";
+  return `cat $fn`;
+}
+
+sub vote {
+  my ($approved, $votes) = @_;
+  my $raw_approved = "";
+  my @votes;
+  return unless %$approved or %$votes;
+
+  $. = 0;
+  open STATUS, "<", $STATUS;
+  open VOTES, ">", "$STATUS.$$.tmp";
+  while (<STATUS>) {
+    unless (exists $votes->{$.}) {
+      (exists $approved->{$.}) ? ($raw_approved .= $_) : (print VOTES);
+      next;
+    }
+
+    my ($vote, $entry) = @{$votes->{$.}};
+    push @{$votes->{$.}}, 1;
+    push @votes, [$vote, $entry];
+
+    if ($vote eq 'edit') {
+      local $_ = $entry->{raw};
+      (exists $approved->{$.}) ? ($raw_approved .= $_) : (print VOTES);
+      next;
+    }
+    
+    s/^(\s*\Q$vote\E:.*)/"$1, $AVAILID"/me
+    or s/(.*\w.*?\n)/"$1     $vote: $AVAILID\n"/se;
+    $_ = edit_string $_, $entry->{header} if $vote ne '+1';
+    (exists $approved->{$.}) ? ($raw_approved .= $_) : (print VOTES);
+  }
+  close STATUS;
+  print VOTES $raw_approved;
+  close VOTES;
+  die "Some vote chunks weren't found: "
+    if grep scalar(@$_) != 3, values %$votes;
+  move "$STATUS.$$.tmp", $STATUS;
+
+  my $logmsg = do {
+    my %allkeys = map { $_ => 1 } keys(%$votes), keys(%$approved);
+    my @sentences = map {
+       exists $votes->{$_}
+       ? (
+         ( $votes->{$_}->[0] eq 'edit'
+           ? "Edit the $votes->{$_}->[1]->{id} entry"
+           : "Vote $votes->{$_}->[0] on the $votes->{$_}->[1]->{header}"
+         )
+         . (exists $approved->{$_} ? ", approving" : "")
+         . "."
+         )
+      : # exists only in $approved
+        "Approve the $approved->{$_}->{header}."
+      } keys %allkeys;
+    (@sentences == 1)
+    ? $sentences[0]
+    : "* STATUS:\n" . join "", map "  $_\n", @sentences;
+  };
+
+  system $SVN, qw/diff --/, $STATUS;
+  say "Voting '$_->[0]' on $_->[1]->{header}." for @votes;
+  # say $logmsg;
+  system $SVN, qw/commit -m/, $logmsg, qw/--/, $STATUS
+    if prompt "Commit these votes? ";
+}
+
+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;
+}
+
+sub maybe_revert {
+  # This is both a SIGINT handler, and the tail end of main() in normal runs.
+  # @_ is 'INT' in the former case and () in the latter.
+  delete $SIG{INT} unless @_;
+  revert if !$YES and prompt 'Revert? ';
+  (@_ ? exit : return);
+}
+
+sub warning_summary {
+  return unless %ERRORS;
+
+  warn "Warning summary\n";
+  warn "===============\n";
+  warn "\n";
+  for my $header (keys %ERRORS) {
+    warn "$header: $ERRORS{$header}\n";
+  }
+}
+
+sub exit_stage_left {
+  maybe_revert;
+  warning_summary if $YES;
+  vote @_;
+  exit scalar keys %ERRORS;
+}
+
 sub handle_entry {
   my $in_approved = shift;
-  my %entry = parse_entry @_;
+  my $votes = shift;
+  my $approved = shift;
+  my $lines = shift;
+  my %entry = parse_entry $lines, @_;
   my @vetoes = grep { /^  -1:/ } @{$entry{votes}};
 
   if ($YES) {
-    merge %entry if $in_approved and not @vetoes;
+    # Run a merge if:
+    unless (@vetoes) {
+      if ($MAY_COMMIT eq 'true' and $in_approved) {
+        # svn-role mode
+        merge %entry;
+      } elsif ($MAY_COMMIT ne 'true') {
+        # Scan-for-conflicts mode
+        merge %entry;
+
+        my $output;
+        if (($output = `$SVN status`) =~ /^(C|.C|...C)/m) {
+          $ERRORS{$entry{id}} //= "Conflicts merging the $entry{header}!";
+          say STDERR "Conflicts merging the $entry{header}!";
+          say STDERR "";
+          say STDERR $output;
+        }
+        revert;
+      }
+    }
   } else {
-    print "";
-    print "\n>>> The $entry{header}:";
-    print join ", ", map { "r$_" } @{$entry{revisions}};
-    print "$BRANCHES/$entry{branch}" if $entry{branch};
-    print "";
-    print for @{$entry{logsummary}};
-    print "";
-    print for @{$entry{votes}};
-    print "";
-    print "Vetoes found!" if @vetoes;
-
-    if (prompt 'Go ahead?') {
-      merge %entry;
-      MAYBE_DIFF: while (1) { 
-        given (prompt "Shall I open a subshell? [ydN]", verbose => 1) {
-          when (/^y/i) {
-            system($ENV{SHELL} // "/bin/sh") == 0
-              or warn "Creating an interactive subshell failed ($?): $!"
-          }
-          when (/^d/) {
-            system($SVN, 'diff') == 0
-              or warn "diff failed ($?): $!";
-            next;
+    # 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 join ", ", map { "r$_" } @{$entry{revisions}} if @{$entry{revisions}};
+    say "$BRANCHES/$entry{branch}" if $entry{branch};
+    say "";
+    say for @{$entry{logsummary}};
+    say "";
+    say for @{$entry{votes}};
+    say "";
+    say "Vetoes found!" if @vetoes;
+
+    given (prompt 'Go ahead? [y,±1,±0,q,e,a,N]',
+                   verbose => 1, extra => qr/[+-]/) {
+      when (/^y/i) {
+        merge %entry;
+        while (1) { 
+          given (prompt "Shall I open a subshell? [ydN]", verbose => 1) {
+            when (/^y/i) {
+              system($ENV{SHELL} // "/bin/sh") == 0
+                or warn "Creating an interactive subshell failed ($?): $!"
+            }
+            when (/^d/) {
+              system($SVN, 'diff') == 0
+                or warn "diff failed ($?): $!";
+              next;
+            }
           }
+          revert;
+          next PROMPT;
         }
-      last;
+        # NOTREACHED
       }
-      # Don't revert.  The next merge() call will do that anyway, or maybe the
-      # user did in his interactive shell.
+      when (/^q/i) {
+        exit_stage_left $approved, $votes;
+      }
+      when (/^a/i) {
+        $approved->{$.} = \%entry;
+        next PROMPT;
+      }
+      when (/^([+-][01])\s*$/i) {
+        $votes->{$.} = [$1, \%entry];
+        say "Your '$1' vote has been recorded." if $VERBOSE;
+      }
+      when (/^e/i) {
+        $entry{raw} = edit_string $entry{raw}, $entry{header};
+        $votes->{$.} = ['edit', \%entry]; # marker for the 2nd pass
+      }
+    }
+    last;
     }
   }
 
@@ -275,6 +494,9 @@ sub handle_entry {
 }
 
 sub main {
+  my %approved;
+  my %votes;
+
   usage, exit 0 if @ARGV;
 
   open STATUS, "<", $STATUS or (usage, exit 1);
@@ -290,19 +512,22 @@ sub main {
   die "Local mods to STATUS file $STATUS" if $YES and `$SVN status -q $STATUS`;
 
   # Skip most of the file
+  $/ = ""; # paragraph mode
   while (<STATUS>) {
     last if /^Status of \d+\.\d+/;
   }
-  $/ = ""; # paragraph mode
+
+  $SIG{INT} = \&maybe_revert unless $YES;
 
   my $in_approved = 0;
   while (<STATUS>) {
+    my $lines = $_;
     my @lines = split /\n/;
 
     given ($lines[0]) {
       # Section header
       when (/^[A-Z].*:$/i) {
-        print "\n\n=== $lines[0]" unless $YES;
+        say "\n\n=== $lines[0]" unless $YES;
         $in_approved = $lines[0] =~ /^Approved changes/;
       }
       # Comment
@@ -317,7 +542,7 @@ sub main {
       when (/^ \*/) {
         warn "Too many bullets in $lines[0]" and next
           if grep /^ \*/, @lines[1..$#lines];
-        handle_entry $in_approved, @lines;
+        handle_entry $in_approved, \%approved, \%votes, $lines, @lines;
       }
       default {
         warn "Unknown entry '$lines[0]' at line $.\n";
@@ -325,7 +550,7 @@ sub main {
     }
   }
 
-  system $SVN, qw/revert -R ./ if !$YES and prompt 'Revert? ';
+  exit_stage_left \%approved, \%votes;
 }
 
 &main

Propchange: subversion/branches/move-tracking-1/tools/dist/make-deps-tarball.sh
------------------------------------------------------------------------------
  Merged /subversion/branches/verify-keep-going/tools/dist/make-deps-tarball.sh:r1439280-1492639
  Merged /subversion/branches/javahl-ra/tools/dist/make-deps-tarball.sh:r1329209-1494640
  Merged /subversion/trunk/tools/dist/make-deps-tarball.sh:r1489601-1500000

Modified: subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c (original)
+++ subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c Mon Aug 19 11:21:01 2013
@@ -2169,13 +2169,13 @@ int main(int argc, const char *argv[])
   svn_err = read_revisions(&fs, repo_path, start_revision, memsize, pool);
   printf("\n");
 
-  print_stats(fs, pool);
-
   if (svn_err)
     {
       svn_handle_error2(svn_err, stdout, FALSE, ERROR_TAG);
       return 2;
     }
 
+  print_stats(fs, pool);
+
   return 0;
 }

Modified: subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnpubsub/server.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnpubsub/server.py?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnpubsub/server.py (original)
+++ subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnpubsub/server.py Mon Aug 19 11:21:01 2013
@@ -25,7 +25,7 @@
 # Instead of using a complicated XMPP/AMPQ/JMS/super messaging service,
 # we have simple HTTP GETs and PUTs to get data in and out.
 #
-# Currently supports both XML and JSON serialization.
+# Currently supports JSON serialization.
 #
 # Example Sub clients:
 #   curl -sN  http://127.0.0.1:2069/commits
@@ -183,10 +183,8 @@ class Client(object):
         self.r.write(str(input))
 
     def write_start(self):
-        # TODO: use application/x-* or vnd.* - see 
-        # Message-ID: <CA...@mail.gmail.com>
-        # on May 2013
-        self.r.setHeader('content-type', 'application/octet-stream')
+        self.r.setHeader('X-SVNPubSub-Version', '1')
+        self.r.setHeader('content-type', 'application/vnd.apache.vc-notify+json')
         self.write('{"svnpubsub": {"version": 1}}\n\0')
 
     def write_heartbeat(self):

Modified: subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnwcsub.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnwcsub.py?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnwcsub.py (original)
+++ subversion/branches/move-tracking-1/tools/server-side/svnpubsub/svnwcsub.py Mon Aug 19 11:21:01 2013
@@ -73,12 +73,18 @@ import svnpubsub.util
 
 assert hasattr(subprocess, 'check_call')
 def check_call(*args, **kwds):
-    """Wrapper around subprocess.check_call() that logs stderr upon failure."""
+    """Wrapper around subprocess.check_call() that logs stderr upon failure,
+    with an optional list of exit codes to consider non-failure."""
     assert 'stderr' not in kwds
+    if '__okayexits' in kwds:
+        __okayexits = kwds['__okayexits']
+        del kwds['__okayexits']
+    else:
+        __okayexits = set([0]) # EXIT_SUCCESS
     kwds.update(stderr=subprocess.PIPE)
     pipe = subprocess.Popen(*args, **kwds)
     output, errput = pipe.communicate()
-    if pipe.returncode:
+    if pipe.returncode not in __okayexits:
         cmd = args[0] if len(args) else kwds.get('args', '(no command)')
         # TODO: log stdout too?
         logging.error('Command failed: returncode=%d command=%r stderr=%r',
@@ -292,6 +298,21 @@ class BackgroundWorker(threading.Thread)
 
         logging.info("updating: %s", wc.path)
 
+        ## Run the hook
+        HEAD = svn_info(self.svnbin, self.env, wc.url)['Revision']
+        if self.hook:
+            hook_mode = ['pre-update', 'pre-boot'][boot]
+            logging.info('running hook: %s at %s',
+                         wc.path, hook_mode)
+            args = [self.hook, hook_mode, wc.path, HEAD, wc.url]
+            rc = check_call(args, env=self.env, __okayexits=[0, 1])
+            if rc == 1:
+                # TODO: log stderr
+                logging.warn('hook denied update of %s at %s',
+                             wc.path, hook_mode)
+                return
+            del rc
+
         ### we need to move some of these args into the config. these are
         ### still specific to the ASF setup.
         args = [self.svnbin, 'switch',
@@ -302,12 +323,13 @@ class BackgroundWorker(threading.Thread)
                 '--config-option',
                 'config:miscellany:use-commit-times=on',
                 '--',
-                wc.url,
+                wc.url + '@' + HEAD,
                 wc.path]
         check_call(args, env=self.env)
 
         ### check the loglevel before running 'svn info'?
         info = svn_info(self.svnbin, self.env, wc.path)
+        assert info['Revision'] == HEAD
         logging.info("updated: %s now at r%s", wc.path, info['Revision'])
 
         ## Run the hook

Modified: subversion/branches/move-tracking-1/win-tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/win-tests.py?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/win-tests.py (original)
+++ subversion/branches/move-tracking-1/win-tests.py Mon Aug 19 11:21:01 2013
@@ -592,6 +592,12 @@ class Httpd:
 
   def _create_dontdothat_file(self):
     "Create empty mime.types file"
+    # If the tests have not previously been run or were cleaned
+    # up, then 'svn-test-work' does not exist yet.
+    parent_dir = os.path.dirname(self.dontdothat_file)
+    if not os.path.exists(parent_dir):
+      os.makedirs(parent_dir)
+
     fp = open(self.dontdothat_file, 'w')
     fp.write('[recursive-actions]\n')
     fp.write('/ = deny\n')