You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2015/03/04 16:56:21 UTC

svn commit: r1664059 [11/11] - in /subversion/branches/reuse-ra-session: ./ build/generator/ doc/ subversion/bindings/javahl/native/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/bindings/swig/python/libsvn_swig_py/ subversion/...

Modified: subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/op-depth-test.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/op-depth-test.c Wed Mar  4 15:56:18 2015
@@ -310,16 +310,17 @@ check_db_rows(svn_test__sandbox_t *b,
       row->repo_revnum = svn_sqlite__column_revnum(stmt, 3);
       row->repo_relpath = svn_sqlite__column_text(stmt, 4, b->pool);
       row->file_external = !svn_sqlite__column_is_null(stmt, 5);
-      if (row->file_external && svn_sqlite__column_is_null(stmt, 6))
-        comparison_baton.errors
-          = svn_error_createf(SVN_ERR_TEST_FAILED, comparison_baton.errors,
-                              "incomplete {%s}", print_row(row, b->pool));
       row->moved_to = svn_sqlite__column_text(stmt, 7, b->pool);
       row->moved_here = svn_sqlite__column_boolean(stmt, 8);
       SVN_ERR(svn_sqlite__column_properties(&props_hash, stmt, 9,
                                             b->pool, b->pool));
       row->props = props_hash_to_text(props_hash, b->pool);
 
+      if (row->file_external && svn_sqlite__column_is_null(stmt, 6))
+        comparison_baton.errors
+          = svn_error_createf(SVN_ERR_TEST_FAILED, comparison_baton.errors,
+                              "incomplete {%s}", print_row(row, b->pool));
+
       key = apr_psprintf(b->pool, "%d %s", row->op_depth, row->local_relpath);
       apr_hash_set(found_hash, key, APR_HASH_KEY_STRING, row);
 
@@ -3582,11 +3583,13 @@ revert_file_externals(const svn_test_opt
   SVN_ERR(sbox_wc_update(&b, "", 1));
   {
     nodes_row_t rows[] = {
-      { 0, "",    "normal", 1, "" },
-      { 0, "f",   "normal", 1, "f" },
-      { 1, "A",   "normal", NO_COPY_FROM },
-      { 0, "h",   "normal", 1, "f", TRUE },
-      { 0, "A/g", "normal", 1, "f", TRUE },
+      { 0, "",    "normal",      1, "" },
+      { 0, "f",   "normal",      1, "f" },
+      { 1, "A",   "normal",      NO_COPY_FROM },
+      { 0, "h",   "normal",      1, "f", TRUE },
+      { 0, "A/g", "normal",      1, "f", TRUE },
+
+      { 0, "g",   "not-present", 0, "g"},
       { 0 }
     };
     SVN_ERR(check_db_rows(&b, "", rows));
@@ -3595,10 +3598,12 @@ revert_file_externals(const svn_test_opt
   SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
   {
     nodes_row_t rows[] = {
-      { 0, "",    "normal", 1, "" },
-      { 0, "f",   "normal", 1, "f" },
-      { 0, "h",   "normal", 1, "f", TRUE },
-      { 0, "A/g", "normal", 1, "f", TRUE },
+      { 0, "",    "normal",      1, "" },
+      { 0, "f",   "normal",      1, "f" },
+      { 0, "h",   "normal",      1, "f", TRUE },
+      { 0, "A/g", "normal",      1, "f", TRUE },
+
+      { 0, "g",   "not-present", 0, "g"},
       { 0 }
     };
     SVN_ERR(check_db_rows(&b, "", rows));
@@ -3607,9 +3612,11 @@ revert_file_externals(const svn_test_opt
   SVN_ERR(sbox_wc_update(&b, "", 1));
   {
     nodes_row_t rows[] = {
-      { 0, "",    "normal", 1, "" },
-      { 0, "f",   "normal", 1, "f" },
-      { 0, "g",   "normal", 1, "f", TRUE },
+      { 0, "",    "normal",      1, "" },
+      { 0, "f",   "normal",      1, "f" },
+      { 0, "g",   "normal",      1, "f", TRUE },
+
+      { 0, "h",   "not-present", 0, "h"},
       { 0 }
     };
     SVN_ERR(check_db_rows(&b, "", rows));

Modified: subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.c (original)
+++ subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.c Wed Mar  4 15:56:18 2015
@@ -599,6 +599,35 @@ sbox_wc_resolve(svn_test__sandbox_t *b,
 }
 
 svn_error_t *
+sbox_wc_resolve_prop(svn_test__sandbox_t *b, const char *path,
+                     const char *propname,
+                     svn_wc_conflict_choice_t conflict_choice)
+{
+  const char *lock_abspath;
+  svn_error_t *err;
+
+  SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, b->wc_ctx,
+                                                 sbox_wc_path(b, path),
+                                                 b->pool, b->pool));
+  err = svn_wc__resolve_conflicts(b->wc_ctx, sbox_wc_path(b, path),
+                                  svn_depth_empty,
+                                  FALSE,
+                                  propname,
+                                  FALSE,
+                                  conflict_choice,
+                                  NULL, NULL, /* conflict func */
+                                  NULL, NULL, /* cancellation */
+                                  NULL, NULL, /* notification */
+                                  b->pool);
+
+  err = svn_error_compose_create(err, svn_wc__release_write_lock(b->wc_ctx,
+                                                                 lock_abspath,
+                                                                 b->pool));
+  return err;
+}
+
+
+svn_error_t *
 sbox_wc_move(svn_test__sandbox_t *b, const char *src, const char *dst)
 {
   svn_client_ctx_t *ctx;

Modified: subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.h (original)
+++ subversion/branches/reuse-ra-session/subversion/tests/libsvn_wc/utils.h Wed Mar  4 15:56:18 2015
@@ -166,6 +166,12 @@ sbox_wc_resolve(svn_test__sandbox_t *b,
 
 /* */
 svn_error_t *
+sbox_wc_resolve_prop(svn_test__sandbox_t *b, const char *path,
+                     const char *propname,
+                     svn_wc_conflict_choice_t conflict_choice);
+
+/* */
+svn_error_t *
 sbox_wc_move(svn_test__sandbox_t *b, const char *src, const char *dst);
 
 /* Set property NAME to VALUE on PATH. If VALUE=NULL, delete the property. */

Modified: subversion/branches/reuse-ra-session/subversion/tests/svn_test_main.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/tests/svn_test_main.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/tests/svn_test_main.c (original)
+++ subversion/branches/reuse-ra-session/subversion/tests/svn_test_main.c Wed Mar  4 15:56:18 2015
@@ -158,29 +158,46 @@ static const apr_getopt_option_t cl_opti
 /* When non-zero, don't remove test directories */
 static svn_boolean_t skip_cleanup = FALSE;
 
-/* All cleanup actions are registered as cleanups on this pool. */
-#if !defined(thread_local) && APR_HAS_THREADS
+/* All cleanup actions are registered as cleanups on the cleanup_pool,
+ * which may be thread-specific. */
+#if APR_HAS_THREADS
+/* The thread-local data key for the cleanup pool. */
+static apr_threadkey_t *cleanup_pool_key = NULL;
 
-#  if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
-#    define thread_local _Thread_local
-#  elif defined(WIN32) && defined(_MSC_VER)
-#    define thread_local __declspec(thread)
-#  elif defined(__thread)
-     /* ### Might work somewhere? */
-#    define thread_local __thread
-#  else
-     /* gcc defines __thread in some versions, but not all.
-        ### Who knows how to check for this?
-        ### stackoverflow recommends __GNUC__ but that breaks on
-        ### openbsd. */
-#  endif
-#endif
+/* No-op destructor for apr_threadkey_private_create(). */
+static void null_threadkey_dtor(void *stuff) {}
+
+/* Set the thread-specific cleanup pool. */
+static void set_cleanup_pool(apr_pool_t *pool)
+{
+  apr_status_t status = apr_threadkey_private_set(pool, cleanup_pool_key);
+  if (status)
+    {
+      printf("apr_threadkey_private_set() failed with code %ld.\n",
+             (long)status);
+      exit(1);
+    }
+}
 
-#ifdef thread_local
-#define HAVE_PER_THREAD_CLEANUP
-static thread_local apr_pool_t * cleanup_pool = NULL;
+/* Get the thread-specific cleanup pool. */
+static apr_pool_t *get_cleanup_pool(void)
+{
+  void *data;
+  apr_status_t status = apr_threadkey_private_get(&data, cleanup_pool_key);
+  if (status)
+    {
+      printf("apr_threadkey_private_get() failed with code %ld.\n",
+             (long)status);
+      exit(1);
+    }
+  return data;
+}
+
+#  define cleanup_pool (get_cleanup_pool())
+#  define HAVE_PER_THREAD_CLEANUP
 #else
 static apr_pool_t *cleanup_pool = NULL;
+#  define set_cleanup_pool(p) (cleanup_pool = (p))
 #endif
 
 /* Used by test_thread to serialize access to stdout. */
@@ -508,7 +525,7 @@ test_thread(apr_thread_t *thread, void *
     = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
 #ifdef HAVE_PER_THREAD_CLEANUP
-  cleanup_pool = svn_pool_create(thread_root);
+  set_cleanup_pool(svn_pool_create(thread_root));
 #endif
 
   pool = svn_pool_create(thread_root);
@@ -780,6 +797,19 @@ svn_test_main(int argc, const char *argv
       svn_error_clear(err);
     }
 
+  /* Set up the thread-local storage key for the cleanup pool. */
+#ifdef HAVE_PER_THREAD_CLEANUP
+  apr_err = apr_threadkey_private_create(&cleanup_pool_key,
+                                         null_threadkey_dtor,
+                                         pool);
+  if (apr_err)
+    {
+      printf("apr_threadkey_private_create() failed with code %ld.\n",
+             (long)apr_err);
+      exit(1);
+    }
+#endif /* HAVE_PER_THREAD_CLEANUP */
+
   /* Remember the command line */
   test_argc = argc;
   test_argv = argv;
@@ -954,7 +984,7 @@ svn_test_main(int argc, const char *argv
     }
 
   /* Create an iteration pool for the tests */
-  cleanup_pool = svn_pool_create(pool);
+  set_cleanup_pool(svn_pool_create(pool));
   test_pool = svn_pool_create(pool);
 
   if (!allow_segfaults)

Modified: subversion/branches/reuse-ra-session/tools/client-side/bash_completion
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/tools/client-side/bash_completion?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/tools/client-side/bash_completion (original)
+++ subversion/branches/reuse-ra-session/tools/client-side/bash_completion Wed Mar  4 15:56:18 2015
@@ -781,7 +781,7 @@ _svn()
 
 	# otherwise build possible options for the command
 	pOpts="--username --password --no-auth-cache --non-interactive \
-	       --trust-server-cert --trust-unknown-ca --trust-cn-mismatch \
+	       --trust-unknown-ca --trust-cn-mismatch \
 	       --trust-expired --trust-not-yet-valid --trust-other-failure \
 	       --force-interactive"
 	mOpts="-m --message -F --file --encoding --force-log --with-revprop"
@@ -829,7 +829,7 @@ _svn()
 		;;
 	copy|cp)
 		cmdOpts="$mOpts $rOpts $qOpts --editor-cmd $pOpts --parents \
-		         --ignore-externals"
+		         --ignore-externals --pin-externals"
 		;;
 	delete|del|remove|rm)
 		cmdOpts="--force $mOpts $qOpts --targets --editor-cmd $pOpts \
@@ -856,7 +856,8 @@ _svn()
 		;;
 	info)
 		cmdOpts="$pOpts $rOpts --targets -R --recursive --depth \
-                         --include-externals --incremental --xml $cOpts"
+                         --include-externals --incremental --xml \
+                         --show-item --no-newline $cOpts"
 		;;
 	list|ls)
 		cmdOpts="$rOpts -v --verbose -R --recursive $pOpts \
@@ -876,7 +877,7 @@ _svn()
 	merge)
 		cmdOpts="$rOpts $nOpts $qOpts --force --dry-run --diff3-cmd \
 		         $pOpts --ignore-ancestry -c --change -x --extensions \
-                         --record-only --accept --reintegrate \
+                         --record-only --accept \
 		         --allow-mixed-revisions -v --verbose"
 		;;
 	mergeinfo)
@@ -905,7 +906,7 @@ _svn()
 		    cmdOpts="$cmdOpts --revprop $rOpts"
 		;;
 	propget|pget|pg)
-	        cmdOpts="-v --verbose -R --recursive $rOpts --strict \
+	        cmdOpts="-v --verbose -R --recursive $rOpts --no-newline \
 		         $pOpts $cOpts --depth --xml --show-inherited-props"
 		[[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop"
 		;;

Modified: subversion/branches/reuse-ra-session/tools/client-side/bash_completion_test
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/tools/client-side/bash_completion_test?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/tools/client-side/bash_completion_test (original)
+++ subversion/branches/reuse-ra-session/tools/client-side/bash_completion_test Wed Mar  4 15:56:18 2015
@@ -114,14 +114,18 @@ get_svn_subcommands() {
 # Usage: get_svn_options SUBCMD
 get_svn_options() {
   { svn help "$1" |
+      # Remove deprecated options
+      grep -v deprecated |
       # Find the relevant lines; remove "arg" and description.
       sed -n -e '1,/^Valid options:$/d;/^  -/!d' \
              -e 's/\( ARG\)* * : .*//;p' |
       # Remove brackets; put each word on its own line.
       tr -d '] ' | tr '[' '\n'
     # The following options are always accepted but not listed in the help
-    echo "-h"
-    echo "--help"
+    if [ "$1" != "help" ] ; then
+      echo "-h"
+      echo "--help"
+    fi
   } | sort
   
 }

Modified: subversion/branches/reuse-ra-session/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/tools/dist/backport.pl?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/tools/dist/backport.pl (original)
+++ subversion/branches/reuse-ra-session/tools/dist/backport.pl Wed Mar  4 15:56:18 2015
@@ -3,7 +3,16 @@ use warnings;
 use strict;
 use feature qw/switch say/;
 
-#no warnings 'experimental::smartmatch';
+use v5.10.0; # needed for $^V
+
+# The given/when smartmatch facility, introduced in Perl v5.10, was made
+# experimental and "subject to change" in v5.18 (see perl5180delta).  Every
+# use of it now triggers a warning.
+#
+# As of Perl v5.20.1, the semantics of given/when provided by Perl are
+# compatible with those expected by the script, so disable the warning for
+# those Perls.
+no if $^V le v5.20.1, warnings => 'experimental::smartmatch';
 
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
@@ -28,6 +37,8 @@ use Term::ReadKey qw/ReadMode ReadKey/;
 use File::Basename qw/basename dirname/;
 use File::Copy qw/copy move/;
 use File::Temp qw/tempfile/;
+use IO::Select ();
+use IPC::Open3 qw/open3/;
 use POSIX qw/ctermid strftime isprint isspace/;
 use Text::Wrap qw/wrap/;
 use Tie::File ();
@@ -201,8 +212,9 @@ is not parsed; only its presence or abse
 
 Both batch modes also perform a basic sanity-check on entries that declare
 backport branches (via the "Branch:" header): if a backport branch is used, but
-at least one of the revisions enumerated in the entry title had not been merged
-from $TRUNK to the branch root, the hourly bot will turn red and 
+at least one of the revisions enumerated in the entry title had neither been
+merged from $TRUNK to the branch root, nor been committed
+directly to the backport branch, the hourly bot will turn red and 
 nightly bot will skip the entry and email its admins.  (The nightly bot does
 not email the list on failure, since it doesn't use buildbot.)
 
@@ -318,9 +330,46 @@ sub my_tempfile {
   return ($fh, $fn);
 }
 
+# The first argument is a shell script.  Run it and return the shell's
+# exit code, and stdout and stderr as references to arrays of lines.
+sub run_in_shell($) {
+  my $script = shift;
+  my $pid = open3 \*SHELL_IN, \*SHELL_OUT, \*SHELL_ERR, qw#/bin/sh#;
+  # open3 raises exception when it fails; no need to error check
+
+  print SHELL_IN $script;
+  close SHELL_IN;
+
+  # Read loop: tee stdout,stderr to arrays.
+  my $select = IO::Select->new(\*SHELL_OUT, \*SHELL_ERR);
+  my (@readable, $outlines, $errlines);
+  while (@readable = $select->can_read) {
+    for my $fh (@readable) {
+      my $line = <$fh>;
+      $select->remove($fh) if eof $fh or not defined $line;
+      next unless defined $line;
+
+      if ($fh == \*SHELL_OUT) {
+        push @$outlines, $line;
+        print STDOUT $line;
+      }
+      if ($fh == \*SHELL_ERR) {
+        push @$errlines, $line;
+        print STDERR $line;
+      }
+    }
+  }
+  waitpid $pid, 0; # sets $?
+  return $?, $outlines, $errlines;
+}
+
 
+# EXPECTED_ERROR_P is subref called with EXIT_CODE, OUTLINES, ERRLINES,
+# expected to return TRUE if the error should be considered fatal (cause
+# backport.pl to exit non-zero) or not.  It may be undef for default behaviour.
 sub merge {
-  my %entry = @_;
+  my %entry = %{ +shift };
+  my $expected_error_p = shift // sub { 0 }; # by default, errors are unexpected
   my $parno = $entry{parno} - scalar grep { $_->{parno} < $entry{parno} } @MERGES_TODAY;
 
   my ($logmsg_fh, $logmsg_filename) = my_tempfile();
@@ -434,15 +483,26 @@ EOF
   revert(verbose => 0, discard_STATUS => $MAY_COMMIT);
 
   $MERGED_SOMETHING++;
-  open SHELL, '|-', qw#/bin/sh# or die "$! (in '$entry{header}')";
-  print SHELL $script;
-  close SHELL or do {
-    warn "$0: sh($?): $! (in '$entry{header}')";
-    die "Lost track of paragraph numbers; aborting" if $MAY_COMMIT
-  };
-  $ERRORS{$entry{id}} = [\%entry, "sh($?): $!"] if $?;
+  my ($exit_code, $outlines, $errlines) = run_in_shell $script;
+  unless ($! == 0) {
+    die "system() failed to spawn subshell ($!); aborting";
+  }
+  unless ($exit_code == 0) {
+    warn "$0: subshell exited with code $exit_code (in '$entry{header}') "
+        ."(maybe due to 'set -e'?)";
+
+    # If we're committing, don't attempt to guess the problem and gracefully
+    # continue; just abort.
+    if ($MAY_COMMIT) {
+      die "Lost track of paragraph numbers; aborting";
+    }
+
+    # Record the error, unless the caller wants not to.
+    $ERRORS{$entry{id}} = [\%entry, "subshell exited with code $exit_code"]
+      unless $expected_error_p->($exit_code, $outlines, $errlines);
+  }
 
-  unlink $logmsg_filename unless $? or $!;
+  unlink $logmsg_filename unless $exit_code;
 }
 
 # Input formats:
@@ -845,7 +905,8 @@ sub validate_branch_contains_named_revis
 
   my $shell_escaped_branch = shell_escape($entry{branch});
   %present = do {
-    my @present = `$SVN mergeinfo --show-revs=merged -- $TRUNK $BRANCHES/$shell_escaped_branch`;
+    my @present = `$SVN mergeinfo --show-revs=merged -- $TRUNK $BRANCHES/$shell_escaped_branch &&
+                   $SVN mergeinfo --show-revs=eligible -- $BRANCHES/$shell_escaped_branch`;
     chomp @present;
     @present = map /(\d+)/g, @present;
     map +($_ => 1), @present;
@@ -881,7 +942,7 @@ sub handle_entry {
     unless (@vetoes) {
       if ($MAY_COMMIT and $in_approved) {
         # svn-role mode
-        merge %entry if validate_branch_contains_named_revisions %entry;
+        merge \%entry if validate_branch_contains_named_revisions %entry;
       } elsif (!$MAY_COMMIT) {
         # Scan-for-conflicts mode
 
@@ -890,7 +951,14 @@ sub handle_entry {
         # block.
         validate_branch_contains_named_revisions %entry;
 
-        merge %entry;
+        # E155015 is SVN_ERR_WC_FOUND_CONFLICT
+        my $expected_error_p = sub {
+          my ($exit_code, $outlines, $errlines) = @_;
+          ($exit_code == 0)
+            or
+          (grep /svn: E155015:/, @$errlines)
+        };
+        merge \%entry, ($entry{depends} ? $expected_error_p : undef);
 
         my $output = `$SVN status`;
 
@@ -951,7 +1019,7 @@ sub handle_entry {
                    verbose => 1, extra => qr/[+-]/) {
       when (/^y/i) {
         #validate_branch_contains_named_revisions %entry;
-        merge %entry;
+        merge \%entry;
         while (1) {
           given (prompt "Shall I open a subshell? [ydN] ", verbose => 1) {
             when (/^y/i) {

Modified: subversion/branches/reuse-ra-session/tools/dist/backport_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/tools/dist/backport_tests.py?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/tools/dist/backport_tests.py (original)
+++ subversion/branches/reuse-ra-session/tools/dist/backport_tests.py Wed Mar  4 15:56:18 2015
@@ -110,7 +110,8 @@ class BackportTest(object):
       verify_backport(sbox, expected_dump_file, self.uuid)
     return wrapped_test_func
 
-def make_entry(revisions=None, logsummary=None, notes=None, branch=None, votes=None):
+def make_entry(revisions=None, logsummary=None, notes=None, branch=None,
+               depends=None, votes=None):
   assert revisions
   if logsummary is None:
     logsummary = "default logsummary"
@@ -122,6 +123,7 @@ def make_entry(revisions=None, logsummar
     'logsummary': logsummary,
     'notes': notes,
     'branch': branch,
+    'depends': depends,
     'votes': votes,
   }
 
@@ -143,6 +145,9 @@ def serialize_entry(entry):
     # branch
     '   Branch: %s\n' % (entry['branch'],) if entry['branch'] else '',
 
+    # depends
+    '   Depends: %s\n' % (entry['depends'],) if entry['depends'] else '',
+
     # votes
     '   Votes:\n',
     ''.join('     '
@@ -382,7 +387,11 @@ def backport_conflicts_detection(sbox):
                                            # Choose conflicts mode:
                                            ["MAY_COMMIT=0"])
 
-  # Verify
+  # Verify the conflict is detected.
+  expected_output = svntest.verify.RegexOutput(
+    'Index: iota',
+    match_all=False,
+  )
   expected_errput = (
     r'(?ms)' # re.MULTILINE | re.DOTALL
     r'.*Warning summary.*'
@@ -396,9 +405,25 @@ def backport_conflicts_detection(sbox):
                       ],
                       match_all=False)
   svntest.verify.verify_outputs(None, output, errput,
-                                svntest.verify.AnyOutput, expected_errput)
+                                expected_output, expected_errput)
   svntest.verify.verify_exit_code(None, exit_code, 1)
 
+  ## Now, let's test the "Depends:" annotation silences the error.
+
+  # Re-nominate.
+  approved_entries = [
+    make_entry([4], depends="World peace."),
+  ]
+  sbox.simple_append(STATUS, serialize_STATUS(approved_entries), truncate=True)
+  sbox.simple_commit(message='Re-nominate r4')
+
+  # Detect conflicts.
+  exit_code, output, errput = run_backport(sbox, extra_env=["MAY_COMMIT=0"])
+
+  # Verify stdout.  (exit_code and errput were verified by run_backport().)
+  svntest.verify.verify_outputs(None, output, errput,
+                                "Conflicts found.*, as expected.", [])
+
 
 #----------------------------------------------------------------------
 @BackportTest(None) # would be 000000000007
@@ -455,6 +480,116 @@ def backport_branch_contains(sbox):
 
 
 #----------------------------------------------------------------------
+@BackportTest(None) # would be 000000000008
+def backport_double_conflict(sbox):
+  "two-revisioned entry with two conflicts"
+
+  # r6: conflicting change on branch
+  sbox.simple_append('branch/iota', 'Conflicts with first change')
+  sbox.simple_commit(message="Conflicting change on iota")
+
+  # r7: further conflicting change to same file
+  sbox.simple_update()
+  sbox.simple_append('subversion/trunk/iota', 'Third line\n')
+  sbox.simple_commit(message="iota's third line")
+
+  # r8: nominate
+  approved_entries = [
+    make_entry([4,7], depends="World peace.")
+  ]
+  sbox.simple_append(STATUS, serialize_STATUS(approved_entries))
+  sbox.simple_commit(message='Nominate the r4 group')
+
+  # Run it, in conflicts mode.
+  exit_code, output, errput = run_backport(sbox, True, ["MAY_COMMIT=0"])
+
+  # Verify the failure mode: "merge conflict" error on stderr, but backport.pl
+  # itself exits with code 0, since conflicts were confined to Depends:-ed
+  # entries.
+  #
+  # The error only happens with multi-pass merges where the first pass
+  # conflicts and the second pass touches the conflict victim.
+  #
+  # The error would be:
+  #    subversion/libsvn_client/merge.c:5499: (apr_err=SVN_ERR_WC_FOUND_CONFLICT)
+  #    svn: E155015: One or more conflicts were produced while merging r3:4
+  #    into '/tmp/stw/working_copies/backport_tests-8/branch' -- resolve all
+  #    conflicts and rerun the merge to apply the remaining unmerged revisions
+  #    ...
+  #    Warning summary
+  #    ===============
+  #    
+  #    r4 (default logsummary): subshell exited with code 256
+  # And backport.pl would exit with exit code 1.
+
+  expected_output = 'Conflicts found.*, as expected.'
+  expected_errput = svntest.verify.RegexOutput(
+      ".*svn: E155015:.*", # SVN_ERR_WC_FOUND_CONFLICT
+      match_all=False,
+  )
+  svntest.verify.verify_outputs(None, output, errput,
+                                expected_output, expected_errput)
+  svntest.verify.verify_exit_code(None, exit_code, 0)
+  if any("Warning summary" in line for line in errput):
+    raise svntest.verify.SVNUnexpectedStderr(errput)
+
+  ## Now, let's ensure this does get detected if not silenced.
+  # r9: Re-nominate
+  approved_entries = [
+    make_entry([4,7]) # no depends=
+  ]
+  sbox.simple_append(STATUS, serialize_STATUS(approved_entries), truncate=True)
+  sbox.simple_commit(message='Re-nominate the r4 group')
+
+  exit_code, output, errput = run_backport(sbox, True, ["MAY_COMMIT=0"])
+
+  # [1-9]\d+ matches non-zero exit codes
+  expected_errput = r'r4 .*: subshell exited with code (?:[1-9]\d+)'
+  svntest.verify.verify_exit_code(None, exit_code, 1)
+  svntest.verify.verify_outputs(None, output, errput,
+                                svntest.verify.AnyOutput, expected_errput)
+
+
+
+#----------------------------------------------------------------------
+@BackportTest('76cee987-25c9-4d6c-ad40-000000000009')
+def backport_branch_with_original_revision(sbox):
+  "branch with original revision"
+
+  # r6: conflicting change on branch
+  sbox.simple_append('branch/iota', 'Conflicts with first change')
+  sbox.simple_commit(message="Conflicting change on iota")
+
+  # r7: backport branch
+  sbox.simple_update()
+  sbox.simple_copy('branch', 'subversion/branches/r4')
+  sbox.simple_commit(message='Create a backport branch')
+
+  # r8: merge into backport branch
+  sbox.simple_update()
+  svntest.main.run_svn(None, 'merge', '--record-only', '-c4',
+                       '^/subversion/trunk', sbox.ospath('subversion/branches/r4'))
+  sbox.simple_mkdir('subversion/branches/r4/A_resolved')
+  sbox.simple_append('subversion/branches/r4/iota', "resolved\n", truncate=1)
+  sbox.simple_commit(message='Conflict resolution via mkdir')
+
+  # r9: original revision on branch
+  sbox.simple_update()
+  sbox.simple_mkdir('subversion/branches/r4/dir-created-on-backport-branch')
+  sbox.simple_commit(message='An original revision on the backport branch')
+
+  # r10: nominate the branch with r9 listed
+  approved_entries = [
+    make_entry([4, 9], branch="r4")
+  ]
+  sbox.simple_append(STATUS, serialize_STATUS(approved_entries))
+  sbox.simple_commit(message='Nominate r4+r9')
+
+  # r11, r12: Run it.
+  run_backport(sbox)
+
+
+#----------------------------------------------------------------------
 
 ########################################################################
 # Run the tests
@@ -468,6 +603,8 @@ test_list = [ None,
               backport_multirevisions,
               backport_conflicts_detection,
               backport_branch_contains,
+              backport_double_conflict,
+              backport_branch_with_original_revision,
               # When adding a new test, include the test number in the last
               # 6 bytes of the UUID.
              ]