subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1516646 [2/2] - in /subversion/branches/log-addressing: ./ build/generator/ build/generator/templates/ subversion/bindings/ctypes-python/csvn/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ ...
Date Thu, 22 Aug 2013 22:35:03 GMT
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c Thu
Aug 22 22:35:01 2013
@@ -156,11 +156,16 @@ create_packed_filesystem(const char *dir
 
   subpool = svn_pool_create(pool);
 
-  /* Rewrite the format file */
-  SVN_ERR(svn_io_read_version_file(&version,
-                                   svn_dirent_join(dir, "format", subpool),
-                                   subpool));
-  SVN_ERR(write_format(dir, version, shard_size, subpool));
+  /* Rewrite the format file.  (The rest of this function is backend-agnostic,
+     so we just avoid adding the FSFS-specific format information if we run on
+     some other backend.) */
+  if ((strcmp(opts->fs_type, "fsfs") == 0))
+    {
+      SVN_ERR(svn_io_read_version_file(&version,
+                                       svn_dirent_join(dir, "format", subpool),
+                                       subpool));
+      SVN_ERR(write_format(dir, version, shard_size, subpool));
+    }
 
   /* Reopen the filesystem */
   SVN_ERR(svn_fs_open(&fs, dir, NULL, subpool));
@@ -423,11 +428,6 @@ read_packed_fs(const svn_test_opts_t *op
   svn_stringbuf_t *rstring;
   svn_revnum_t i;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 6)))
-    return SVN_NO_ERROR;
-
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
   SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));
 
@@ -470,11 +470,6 @@ commit_packed_fs(const svn_test_opts_t *
   const char *conflict;
   svn_revnum_t after_rev;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 6)))
-    return SVN_NO_ERROR;
-
   /* Create the packed FS and open it. */
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, 5, pool));
   SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));
@@ -505,11 +500,6 @@ get_set_revprop_packed_fs(const svn_test
   svn_fs_t *fs;
   svn_string_t *prop_value;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 7)))
-    return SVN_NO_ERROR;
-
   /* Create the packed FS and open it. */
   SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
                                pool));
@@ -562,11 +552,6 @@ get_set_large_revprop_packed_fs(const sv
   svn_string_t *prop_value;
   svn_revnum_t rev;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 7)))
-    return SVN_NO_ERROR;
-
   /* Create the packed FS and open it. */
   SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
                                pool));
@@ -635,11 +620,6 @@ get_set_huge_revprop_packed_fs(const svn
   svn_string_t *prop_value;
   svn_revnum_t rev;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 7)))
-    return SVN_NO_ERROR;
-
   /* Create the packed FS and open it. */
   SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
                                pool));
@@ -710,7 +690,7 @@ recover_fully_packed(const svn_test_opts
 
   /* Bail (with success) on known-untestable scenarios */
   if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 7)))
+      || (opts->server_minor_version && (opts->server_minor_version < 6)))
     return SVN_NO_ERROR;
 
   /* Create a packed FS for which every revision will live in a pack
@@ -771,11 +751,6 @@ file_hint_at_shard_boundary(const svn_te
   svn_stringbuf_t *retrieved_contents;
   svn_error_t *err = SVN_NO_ERROR;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 8)))
-    return SVN_NO_ERROR;
-
   /* Create a packed FS and MAX_REV revisions */
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
 
@@ -820,11 +795,6 @@ test_info(const svn_test_opts_t *opts,
   const svn_fs_fsfs_info_t *fsfs_info;
   const svn_fs_info_placeholder_t *info;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 8)))
-    return SVN_NO_ERROR;
-
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE,
                                    pool));
 
@@ -868,11 +838,6 @@ pack_shard_size_one(const svn_test_opts_
   svn_string_t *propval;
   svn_fs_t *fs;
 
-  /* Bail (with success) on known-untestable scenarios */
-  if ((strcmp(opts->fs_type, "fsfs") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 6)))
-    return SVN_NO_ERROR;
-
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE,
                                    pool));
   SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));
@@ -887,6 +852,70 @@ pack_shard_size_one(const svn_test_opts_
 #undef SHARD_SIZE
 #undef MAX_REV
 /* ------------------------------------------------------------------------ */
+#define REPO_NAME "get_set_multiple_huge_revprops_packed_fs"
+#define SHARD_SIZE 4
+#define MAX_REV 9
+static svn_error_t *
+get_set_multiple_huge_revprops_packed_fs(const svn_test_opts_t *opts,
+                                         apr_pool_t *pool)
+{
+  svn_fs_t *fs;
+  svn_string_t *prop_value;
+  svn_revnum_t rev;
+
+  /* Create the packed FS and open it. */
+  SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
+                               pool));
+
+  /* Set commit messages to different values */
+  for (rev = 0; rev <= MAX_REV; ++rev)
+    SVN_ERR(svn_fs_change_rev_prop(fs, rev, SVN_PROP_REVISION_LOG,
+                                   default_log(rev, pool),
+                                   pool));
+
+  /* verify */
+  for (rev = 0; rev <= MAX_REV; ++rev)
+    {
+      SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
+                                   SVN_PROP_REVISION_LOG, pool));
+      SVN_TEST_STRING_ASSERT(prop_value->data, default_log(rev, pool)->data);
+    }
+
+  /* Put a huge revprop into revision 1 and 2. */
+  SVN_ERR(svn_fs_change_rev_prop(fs, 1, SVN_PROP_REVISION_LOG,
+                                 huge_log(1, pool),
+                                 pool));
+  SVN_ERR(svn_fs_change_rev_prop(fs, 2, SVN_PROP_REVISION_LOG,
+                                 huge_log(2, pool),
+                                 pool));
+  SVN_ERR(svn_fs_change_rev_prop(fs, 5, SVN_PROP_REVISION_LOG,
+                                 huge_log(5, pool),
+                                 pool));
+  SVN_ERR(svn_fs_change_rev_prop(fs, 6, SVN_PROP_REVISION_LOG,
+                                 huge_log(6, pool),
+                                 pool));
+
+  /* verify */
+  for (rev = 0; rev <= MAX_REV; ++rev)
+    {
+      SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
+                                   SVN_PROP_REVISION_LOG, pool));
+
+      if (rev == 1 || rev == 2 || rev == 5 || rev == 6)
+        SVN_TEST_STRING_ASSERT(prop_value->data,
+                               huge_log(rev, pool)->data);
+      else
+        SVN_TEST_STRING_ASSERT(prop_value->data,
+                               default_log(rev, pool)->data);
+    }
+
+  return SVN_NO_ERROR;
+}
+#undef REPO_NAME
+#undef MAX_REV
+#undef SHARD_SIZE
+
+/* ------------------------------------------------------------------------ */
 
 /* The test table.  */
 
@@ -915,5 +944,7 @@ struct svn_test_descriptor_t test_funcs[
                        "test svn_fs_info"),
     SVN_TEST_OPTS_PASS(pack_shard_size_one,
                        "test packing with shard size = 1"),
+    SVN_TEST_OPTS_PASS(get_set_multiple_huge_revprops_packed_fs,
+                       "set multiple huge revprops in packed FSFS"),
     SVN_TEST_NULL
   };

Propchange: subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/trunk/subversion/tests/libsvn_fs_x:r1512320-1516631
  Merged /subversion/branches/fsfs-improvements/subversion/tests/libsvn_fs_x:r1512324-1516644

Modified: subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/fs-x-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/fs-x-pack-test.c?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/fs-x-pack-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/fs-x-pack-test.c Thu Aug
22 22:35:01 2013
@@ -760,7 +760,7 @@ file_hint_at_shard_boundary(const svn_te
 
   /* Bail (with success) on known-untestable scenarios */
   if ((strcmp(opts->fs_type, "fsx") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 8)))
+      || (opts->server_minor_version && (opts->server_minor_version < 9)))
     return SVN_NO_ERROR;
 
   /* Create a packed FS and MAX_REV revisions */
@@ -809,7 +809,7 @@ test_info(const svn_test_opts_t *opts,
 
   /* Bail (with success) on known-untestable scenarios */
   if ((strcmp(opts->fs_type, "fsx") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 8)))
+      || (opts->server_minor_version && (opts->server_minor_version < 9)))
     return SVN_NO_ERROR;
 
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE,
@@ -862,7 +862,7 @@ test_reps(const svn_test_opts_t *opts,
 
   /* Bail (with success) on known-untestable scenarios */
   if ((strcmp(opts->fs_type, "fsx") != 0)
-      || (opts->server_minor_version && (opts->server_minor_version < 8)))
+      || (opts->server_minor_version && (opts->server_minor_version < 9)))
     return SVN_NO_ERROR;
 
   for (i = 0; i < 10000; ++i)

Modified: subversion/branches/log-addressing/tools/dev/unix-build/Makefile.svn
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/dev/unix-build/Makefile.svn?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/dev/unix-build/Makefile.svn (original)
+++ subversion/branches/log-addressing/tools/dev/unix-build/Makefile.svn Thu Aug 22 22:35:01
2013
@@ -72,7 +72,7 @@ GNU_ICONV_VER	= 1.14
 APR_UTIL_VER	= 1.4.1
 HTTPD_VER	= 2.2.25
 NEON_VER	= 0.29.6
-SERF_VER	= 1.3.0
+SERF_VER	= 1.3.1
 SERF_OLD_VER	= 0.3.1
 CYRUS_SASL_VER	= 2.1.25
 SQLITE_VER	= 3071600
@@ -733,7 +733,7 @@ $(SERF_OBJDIR)/.retrieved:
 # compile serf (serf won't compile outside its source tree)
 $(SERF_OBJDIR)/.compiled: $(SERF_OBJDIR)/.retrieved
 	cd $(SERF_SRCDIR) && \
-		scons DEBUG=1 CFLAGS="-O0,-g,$(PROFILE_CFLAGS)" \
+		scons DEBUG=1 CFLAGS="-O0 -g $(PROFILE_CFLAGS)" \
 			APR=$(PREFIX)/apr \
 			APU=$(PREFIX)/apr \
 			PREFIX=$(PREFIX)/serf
@@ -1171,7 +1171,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
+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
@@ -1180,7 +1180,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
+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
@@ -1200,7 +1200,7 @@ BDB_FLAG=db.h:$(PREFIX)/bdb/include:$(PR
 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
+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

Modified: subversion/branches/log-addressing/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/dist/backport.pl?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/dist/backport.pl (original)
+++ subversion/branches/log-addressing/tools/dist/backport.pl Thu Aug 22 22:35:01 2013
@@ -22,7 +22,7 @@ use feature qw/switch say/;
 
 use Digest ();
 use Term::ReadKey qw/ReadMode ReadKey/;
-use File::Basename qw/basename/;
+use File::Basename qw/basename dirname/;
 use File::Copy qw/copy move/;
 use File::Temp qw/tempfile/;
 use POSIX qw/ctermid strftime/;
@@ -89,9 +89,28 @@ $SVNq =~ s/-q// if $DEBUG eq 'true';
 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:
@@ -120,12 +139,12 @@ 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 modes 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.
@@ -137,7 +156,7 @@ sub nominate_usage {
   print <<EOF;
 nominate.pl: a tool for adding entries to STATUS.
 
-Usage: $0 "r42,r43,45." "\$Some_justification"
+Usage: $0 "foo r42 bar r43 qux 45." "\$Some_justification"
 
 Will add:
  * r42, r43, r45
@@ -147,16 +166,30 @@ Will add:
    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: Handle log messages such as "* file.c: Change."
+# 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 = @_;
@@ -320,6 +353,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;
@@ -396,7 +430,7 @@ sub parse_entry {
     entry => [@lines],
     accept => $accept,
     raw => $raw,
-    digest => digest_string($raw),
+    digest => digest_entry($raw),
   );
 }
 
@@ -434,7 +468,7 @@ 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};
@@ -466,7 +500,7 @@ sub vote {
 
     if ($vote eq 'edit') {
       local $_ = $entry->{raw};
-      $votesarray[-1]->{digest} = digest_string $_;
+      $votesarray[-1]->{digest} = digest_entry $_;
       (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
       next;
     }
@@ -475,7 +509,7 @@ sub vote {
     or s/(.*\w.*?\n)/"$1     $vote: $AVAILID\n"/se;
     $_ = edit_string $_, $entry->{header}, trailing_eol => 2
         if $vote ne '+1';
-    $votesarray[-1]->{digest} = digest_string $_;
+    $votesarray[-1]->{digest} = digest_entry $_;
     (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
   }
   close STATUS;
@@ -530,7 +564,10 @@ sub vote {
         or warn("Committing the votes failed($?): $!") and return;
     unlink $logmsg_filename;
 
-    $state->{$_->{digest}}++ for @votesarray;
+    # Add to state votes that aren't '+0' or 'edit'
+    $state->{$_->{digest}}++ for grep
+                                   +{ qw/-1 t -0 t +1 t/ }->{$_->{vote}},
+                                 @votesarray;
   }
 }
 
@@ -623,9 +660,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) {
@@ -662,11 +703,13 @@ sub handle_entry {
         revert;
       }
     }
-  } elsif ($state->{$entry{digest}}) {
+  } elsif (defined($skip) ? not $match : $state->{$entry{digest}}) {
     print "\n\n";
-    say "Skipping $entry{header} (remove $STATEFILE to reset):";
+    my $reason = defined($skip) ? "doesn't match pattern"
+                                : "remove $STATEFILE to reset";
+    say "Skipping $entry{header} ($reason):";
     say logsummarysummary \%entry;
-  } else {
+  } 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) {
@@ -760,6 +803,9 @@ sub handle_entry {
     }
     last; } # QUESTION
     last; } # PROMPT
+  } else {
+    # NOTREACHED
+    die "Unreachable code reached.";
   }
 
   # TODO: merge() changes ./STATUS, which we're reading below, but
@@ -774,7 +820,10 @@ sub backport_main {
   my %votes;
   my $state = read_state;
 
-  backport_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 (backport_usage, exit 1);
 
@@ -823,7 +872,8 @@ sub backport_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]'";
@@ -861,9 +911,21 @@ sub nominate_main {
   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, ($logmsg =~ /^(.*?)\n\n/s);
+  push @lines, wrap ' 'x3, ' 'x3, split /\n/, $logmsg;
   push @lines, "   Justification:";
   push @lines, wrap ' 'x5, ' 'x5, $justification;
   push @lines, "   Branch: $branch" if defined $branch;
@@ -908,12 +970,14 @@ sub nominate_main {
 # Dispatch to the appropriate main().
 given (basename($0)) {
   when (/^b$|backport/) {
-    &backport_main;
+    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;
+    &backport_main(@ARGV);
   }
 }

Modified: subversion/branches/log-addressing/tools/dist/templates/download.ezt
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/dist/templates/download.ezt?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/dist/templates/download.ezt (original)
+++ subversion/branches/log-addressing/tools/dist/templates/download.ezt Thu Aug 22 22:35:01
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/log-addressing/tools/examples/blame.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/examples/blame.py?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/examples/blame.py (original)
+++ subversion/branches/log-addressing/tools/examples/blame.py Thu Aug 22 22:35:01 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/log-addressing/tools/server-side/fsfs-stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/server-side/fsfs-stats.c?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/server-side/fsfs-stats.c (original)
+++ subversion/branches/log-addressing/tools/server-side/fsfs-stats.c Thu Aug 22 22:35:01
2013
@@ -1241,7 +1241,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);
 

Modified: subversion/branches/log-addressing/tools/server-side/svnpubsub/daemonize.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/server-side/svnpubsub/daemonize.py?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/server-side/svnpubsub/daemonize.py (original)
+++ subversion/branches/log-addressing/tools/server-side/svnpubsub/daemonize.py Thu Aug 22
22:35:01 2013
@@ -24,6 +24,7 @@ import os
 import signal
 import sys
 import time
+import multiprocessing  # requires Python 2.6
 
 
 # possible return values from Daemon.daemonize()
@@ -50,11 +51,11 @@ class Daemon(object):
   def daemonize_exit(self):
     try:
       result = self.daemonize()
-    except (ChildFailed, DaemonFailed) as e:
+    except (ChildFailed, DaemonFailed), e:
       # duplicate the exit code
       sys.exit(e.code)
     except (ChildTerminatedAbnormally, ChildForkFailed,
-            DaemonTerminatedAbnormally, DaemonForkFailed) as e:
+            DaemonTerminatedAbnormally, DaemonForkFailed), e:
       sys.stderr.write('ERROR: %s\n' % e)
       sys.exit(1)
     except ChildResumedIncorrectly:
@@ -71,29 +72,41 @@ class Daemon(object):
     # in original process. daemon is up and running. we're done.
 
   def daemonize(self):
-    # fork off a child that can detach itself from this process.
-    try:
-      pid = os.fork()
-    except OSError as e:
-      raise ChildForkFailed(e.errno, e.strerror)
-
-    if pid > 0:
-      # we're in the parent. let's wait for the child to finish setting
-      # things up -- on our exit, we want to ensure the child is accepting
-      # connections.
-      cpid, status = os.waitpid(pid, 0)
-      assert pid == cpid
-      if os.WIFEXITED(status):
-        code = os.WEXITSTATUS(status)
-        if code:
-          raise ChildFailed(code)
-        return DAEMON_RUNNING
-
-      # the child did not exit cleanly.
-      raise ChildTerminatedAbnormally(status)
+    ### review error situations. map to backwards compat. ??
+    ### be mindful of daemonize_exit().
+    ### we should try and raise ChildFailed / ChildTerminatedAbnormally.
+    ### ref: older revisions. OR: remove exceptions.
+
+    child_is_ready = multiprocessing.Event()
+    child_completed = multiprocessing.Event()
+
+    p = multiprocessing.Process(target=self._first_child,
+                                args=(child_is_ready, child_completed))
+    p.start()
+    
+    # Wait for the child to finish setting things up (in case we need
+    # to communicate with it). It will only exit when ready.
+    ### use a timeout here! (parameterized, of course)
+    p.join()
+
+    ### need to propagate errors, to adjust the return codes
+    if child_completed.is_set():
+      ### what was the exit status?
+      return DAEMON_COMPLETE
+    if child_is_ready.is_set():
+      return DAEMON_RUNNING
+
+    ### how did we get here?! the immediate child should not exit without
+    ### signalling ready/complete. some kind of error.
+    return DAEMON_STARTED
 
+  def _first_child(self, child_is_ready, child_completed):
     # we're in the child.
 
+    ### NOTE: the original design was a bit bunk. Exceptions raised from
+    ### this point are within the child processes. We need to signal the
+    ### errors to the parent in other ways.
+
     # decouple from the parent process
     os.chdir('/')
     os.umask(0)
@@ -102,56 +115,86 @@ class Daemon(object):
     # remember this pid so the second child can signal it.
     thispid = os.getpid()
 
-    # register a signal handler so the SIGUSR1 doesn't stop the process.
-    # this object will also record whether if got signalled.
-    daemon_accepting = SignalCatcher(signal.SIGUSR1)
-
-    # if the daemon process exits before sending SIGUSR1, then we need to see
-    # the problem. trap SIGCHLD with a SignalCatcher.
+    # if the daemon process exits before signalling readiness, then we
+    # need to see the problem. trap SIGCHLD with a SignalCatcher.
     daemon_exit = SignalCatcher(signal.SIGCHLD)
 
     # perform the second fork
     try:
       pid = os.fork()
-    except OSError as e:
+    except OSError, e:
+      ### this won't make it to the parent process
       raise DaemonForkFailed(e.errno, e.strerror)
 
     if pid > 0:
       # in the parent.
 
-      # we want to wait for the daemon to signal that it has created and
-      # bound the socket, and is (thus) ready for connections. if the
-      # daemon improperly exits before serving, we'll see SIGCHLD and the
-      # .pause will return.
-      ### we should add a timeout to this. allow an optional parameter to
-      ### specify the timeout, in case it takes a long time to start up.
-      signal.pause()
+
+      # Wait for the child to be ready for operation.
+      while True:
+        # The readiness event will invariably be signalled early/first.
+        # If it *doesn't* get signalled because the child has prematurely
+        # exited, then we will pause 10ms before noticing the exit. The
+        # pause is acceptable since that is aberrant/unexpected behavior.
+        ### is there a way to break this wait() on a signal such as SIGCHLD?
+        ### parameterize this wait, in case the app knows children may
+        ### fail quickly?
+        if child_is_ready.wait(timeout=0.010):
+          # The child signalled readiness. Yay!
+          break
+        if daemon_exit.signalled:
+          # Whoops. The child exited without signalling :-(
+          break
+        # Python 2.6 compat: .wait() may exit when set, but return None
+        if child_is_ready.is_set():
+          break
+        # A simple timeout. The child is taking a while to prepare. Go
+        # back and wait for readiness.
 
       if daemon_exit.signalled:
+        # Tell the parent that the child has exited.
+        ### we need to communicate the exit status, if possible.
+        child_completed.set()
+
         # reap the daemon process, getting its exit code. bubble it up.
         cpid, status = os.waitpid(pid, 0)
         assert pid == cpid
         if os.WIFEXITED(status):
           code = os.WEXITSTATUS(status)
           if code:
+            ### this won't make it to the parent process
             raise DaemonFailed(code)
+          ### this return value is ignored
           return DAEMON_NOT_RUNNING
 
         # the daemon did not exit cleanly.
+        ### this won't make it to the parent process
         raise DaemonTerminatedAbnormally(status)
 
-      if daemon_accepting.signalled:
-        # the daemon is up and running, so save the pid and return success.
-        if self.pidfile:
-          open(self.pidfile, 'w').write('%d\n' % pid)
-        return DAEMON_STARTED
+      # child_is_ready got asserted. the daemon is up and running, so
+      # save the pid and return success.
+      if self.pidfile:
+        # Be wary of symlink attacks
+        try:
+          os.remove(self.pidfile)
+        except OSError:
+          pass
+        fd = os.open(self.pidfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0444)
+        os.write(fd, '%d\n' % pid)
+        os.close(fd)
 
+      ### this return value is ignored
+      return DAEMON_STARTED
+
+      ### old code. what to do with this? throw ChildResumedIncorrectly
+      ### or just toss this and the exception.
       # some other signal popped us out of the pause. the daemon might not
       # be running.
+      ### this won't make it to the parent process
       raise ChildResumedIncorrectly()
 
-    # we're a deamon now. get rid of the final remnants of the parent.
-    # start by restoring default signal handlers
+    # we're a daemon now. get rid of the final remnants of the parent:
+    # restore the signal handlers and switch std* to the proper files.
     signal.signal(signal.SIGUSR1, signal.SIG_DFL)
     signal.signal(signal.SIGCHLD, signal.SIG_DFL)
     sys.stdout.flush()
@@ -169,30 +212,31 @@ class Daemon(object):
     so.close()
     se.close()
 
-    # TEST: don't release the parent immediately. the whole parent stack
-    #       should pause along with this sleep.
+    ### TEST: don't release the parent immediately. the whole parent stack
+    ###       should pause along with this sleep.
     #time.sleep(10)
 
     # everything is set up. call the initialization function.
     self.setup()
 
-    # sleep for one second before signalling. we want to make sure the
-    # parent has called signal.pause()
-    ### we should think of a better wait around the race condition.
-    time.sleep(1)
+    ### TEST: exit before signalling.
+    #sys.exit(0)
+    #sys.exit(1)
 
-    # okay. the daemon is ready. signal the parent to tell it we're set.
-    os.kill(thispid, signal.SIGUSR1)
+    # the child is now ready for parent/anyone to communicate with it.
+    child_is_ready.set()
 
     # start the daemon now.
     self.run()
 
     # The daemon is shutting down, so toss the pidfile.
-    try:
-      os.remove(self.pidfile)
-    except OSError:
-      pass
+    if self.pidfile:
+      try:
+        os.remove(self.pidfile)
+      except OSError:
+        pass
 
+    ### this return value is ignored
     return DAEMON_COMPLETE
 
   def setup(self):
@@ -202,6 +246,34 @@ class Daemon(object):
     raise NotImplementedError
 
 
+class _Detacher(Daemon):
+  def __init__(self, target, logfile='/dev/null', pidfile=None,
+               args=(), kwargs={}):
+    Daemon.__init__(self, logfile, pidfile)
+    self.target = target
+    self.args = args
+    self.kwargs = kwargs
+
+  def setup(self):
+    pass
+
+  def run(self):
+    self.target(*self.args, **self.kwargs)
+
+    
+def run_detached(target, *args, **kwargs):
+  """Simple function to run TARGET as a detached daemon.
+  
+  The additional arguments/keywords will be passed along. This function
+  does not return -- sys.exit() will be called as appropriate.
+  
+  (capture SystemExit if logging/reporting is necessary)
+  ### if needed, a variant of this func could be written to not exit
+  """
+  d = _Detacher(target, args=args, kwargs=kwargs)
+  d.daemonize_exit()
+
+
 class SignalCatcher(object):
   def __init__(self, signum):
     self.signalled = False

Modified: subversion/branches/log-addressing/tools/server-side/svnpubsub/svnwcsub.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/server-side/svnpubsub/svnwcsub.py?rev=1516646&r1=1516645&r2=1516646&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/server-side/svnpubsub/svnwcsub.py (original)
+++ subversion/branches/log-addressing/tools/server-side/svnpubsub/svnwcsub.py Thu Aug 22
22:35:01 2013
@@ -476,7 +476,15 @@ def handle_options(options):
     # Otherwise, we should write this (foreground) PID into the file.
     if options.pidfile and not options.daemon:
         pid = os.getpid()
-        open(options.pidfile, 'w').write('%s\n' % pid)
+        # Be wary of symlink attacks
+        try:
+            os.remove(options.pidfile)
+        except OSError:
+            pass
+        fd = os.open(options.pidfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL,
+                     0444)
+        os.write(fd, '%d\n' % pid)
+        os.close(fd)
         logging.info('pid %d written to %s', pid, options.pidfile)
 
     if options.gid:
@@ -536,7 +544,8 @@ def main(args):
 
     # We manage the logfile ourselves (along with possible rotation). The
     # daemon process can just drop stdout/stderr into /dev/null.
-    d = Daemon('/dev/null', options.pidfile, options.umask, bdec)
+    d = Daemon('/dev/null', os.path.abspath(options.pidfile),
+               options.umask, bdec)
     if options.daemon:
         # Daemonize the process and call sys.exit() with appropriate code
         d.daemonize_exit()



Mime
View raw message