
* subversion/libsvn_client/merge.c
  (remove_noop_subtree_ranges): 
  (do_mergeinfo_aware_dir_merge): 

* subversion/tests/cmdline/merge_tests.py

--This line, and those below, will be ignored--

Index: subversion/libsvn_client/merge.c
===================================================================
--- subversion/libsvn_client/merge.c	(revision 1367335)
+++ subversion/libsvn_client/merge.c	(working copy)
@@ -8551,6 +8551,24 @@ remove_noop_subtree_ranges(const merge_s
   return SVN_NO_ERROR;
 }
 
+/* ### */
+static void
+print_remaining_ranges(const char *prefix,
+                       const apr_array_header_t *children_with_mergeinfo,
+                       apr_pool_t *scratch_pool)
+{
+  int i;
+  for (i = 0; i < children_with_mergeinfo->nelts; i++)
+    {
+      svn_client__merge_path_t *child
+        = APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
+      svn_string_t *s;
+      svn_error_clear(svn_rangelist_to_string(&s, child->remaining_ranges, scratch_pool));
+      SVN_DBG(("%s: ...%s: %s\n",
+               prefix, child->abspath + strlen(child->abspath) - 10, s->data));
+    }
+}
+
 /* Perform a merge of changes in SOURCE to the working copy path
    TARGET_ABSPATH. Both URLs in SOURCE, and TARGET_ABSPATH all represent
    directories -- for the single file case, the caller should use
@@ -8674,6 +8692,8 @@ do_mergeinfo_aware_dir_merge(svn_mergein
       if (SVN_IS_VALID_REVNUM(new_range_start))
         range.start = new_range_start;
 
+      print_remaining_ranges("1", notify_b->children_with_mergeinfo, scratch_pool);
+
       /* Remove inoperative ranges from any subtrees' remaining_ranges
          to spare the expense of noop editor drives. */
       if (!is_rollback)
@@ -8682,6 +8702,8 @@ do_mergeinfo_aware_dir_merge(svn_mergein
                                            notify_b->children_with_mergeinfo,
                                            scratch_pool, iterpool));
 
+      print_remaining_ranges("2", notify_b->children_with_mergeinfo, scratch_pool);
+
       /* Adjust subtrees' remaining_ranges to deal with issue #3067:
        * "subtrees that don't exist at the start or end of a merge range
        * shouldn't break the merge". */
@@ -8690,6 +8712,8 @@ do_mergeinfo_aware_dir_merge(svn_mergein
                                          notify_b->children_with_mergeinfo,
                                          merge_b->ctx, scratch_pool, iterpool));
 
+      print_remaining_ranges("3", notify_b->children_with_mergeinfo, scratch_pool);
+
       /* remove_noop_subtree_ranges() and/or fix_deleted_subtree_range()
          may have further refined the starting revision for our editor
          drive. */
Index: subversion/tests/cmdline/merge_tests.py
===================================================================
--- subversion/tests/cmdline/merge_tests.py	(revision 1367335)
+++ subversion/tests/cmdline/merge_tests.py	(working copy)
@@ -17828,6 +17828,118 @@ def merge_with_added_subtrees_with_merge
                                        None, None, None, None,
                                        None, 1, 0)
 
+#----------------------------------------------------------------------
+# A trimmed-down copy of dont_merge_revs_into_subtree_that_predate_it(),
+# specifically for issue #???? ...
+#
+#   Issue #3138
+#   Another test for issue #3067: 'subtrees with intersecting mergeinfo,
+#   that don't exist at the start of a merge range shouldn't break the
+#   merge'.  Specifically see
+#   http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc5
+@SkipUnless(server_has_mergeinfo)
+@Issues(3138,3067)
+def dont_merge_revs_into_subtree_that_predate_it2(sbox):
+  "dont merge revs into a subtree that predate it"
+
+  #                        +-> merge -c4 A/D/H/nu@4 H_COPY/nu
+  #                        | +-> merge A/D/H H_COPY
+  #                        | |
+  # A/D/H      A--------------
+  #     +-psi  +---------M----
+  #     +-nu     A---M-D
+  # H_COPY         C---------G
+  #     +-psi      +---------+
+  #     +-nu       +-------G-+
+  #            1 2 3 4 5 6 w w
+
+  # Create our good 'ole greek tree.
+  sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+  wc_dir = sbox.wc_dir
+
+  # Some paths we'll care about
+  psi_path     = sbox.ospath('A/D/H/psi')
+  nu_path      = sbox.ospath('A/D/H/nu')
+  H_COPY_path  = sbox.ospath('H_COPY')
+  nu_COPY_path = sbox.ospath('H_COPY/nu')
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+
+  # Create 'A/D/H/nu' and commit it as r2.
+  svntest.main.file_write(nu_path, "This is the file 'nu'.\n")
+  sbox.simple_add('A/D/H/nu')
+  expected_status.add({'A/D/H/nu' : Item(status='  ', wc_rev=2)})
+  sbox.simple_commit()
+
+  # Copy 'A/D/H' to 'H_COPY' in r3.
+  sbox.simple_repo_copy('A/D/H', 'H_COPY')
+  expected_status.add({
+    "H_COPY"       : Item(),
+    "H_COPY/chi"   : Item(),
+    "H_COPY/omega" : Item(),
+    "H_COPY/psi"   : Item(),
+    "H_COPY/nu"    : Item()})
+
+  # Make a text mod to 'A/D/H/nu' and commit it as r4.
+  svntest.main.file_write(nu_path, "New content")
+  expected_status.tweak('A/D/H/nu', wc_rev=4)
+  sbox.simple_commit()
+
+  # Remove A/D/H/nu and commit it as r5.
+  # We do this deletion so that following cherry harvest has a *tough*
+  # time to identify the line of history of /A/D/H/nu@HEAD.
+  svntest.main.run_svn(None, 'rm', nu_path)
+  expected_status.remove('A/D/H/nu')
+  sbox.simple_commit()
+
+  # Make another text mod to 'A/D/H/psi' that can be merged to 'H_COPY'
+  # during a cherry harvest and commit it as r6.
+  svntest.main.file_write(psi_path, "Even *newer* content")
+  expected_status.tweak('A/D/H/psi', wc_rev=6)
+  sbox.simple_commit()
+
+  # Update to pull H_COPY into the WC, and so that elision occurs smoothly.
+  sbox.simple_update()
+  expected_status.tweak(status='  ', wc_rev=6)
+
+  # Merge r4 from 'A/D/H/nu' to 'H_COPY/nu'.
+  svntest.actions.run_and_verify_svn(
+    None,
+    expected_merge_output([[4]],
+                          ['U    ' + nu_COPY_path + '\n',
+                           ' U   ' + nu_COPY_path + '\n']),
+    [], 'merge', '-c4', sbox.repo_url + '/A/D/H/nu@4', nu_COPY_path)
+
+  # Cherry harvest all eligible revisions from 'A/D/H' to 'H_COPY'.
+  #
+  # This is where we see the problem described in
+  # http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc5.
+  #
+  # Use run_and_verify_svn() because run_and_verify_merge*() require
+  # explicit revision ranges.
+
+  # H_COPY needs r3-6 applied while H_COPY/nu needs only 3,5-6.
+  # This means r3 will be done as a separate editor drive targeted
+  # on H_COPY.  But r3 was only the copy of A/D/H to H_COPY and
+  # so is a no-op and there will no notification for r3.
+  svntest.actions.run_and_verify_svn(
+    None,
+    expected_merge_output(
+      [[3,6]], ['U    ' + sbox.ospath('H_COPY/psi') + '\n',
+                'D    ' + sbox.ospath('H_COPY/nu') + '\n',
+                ' U   ' + H_COPY_path + '\n',]),
+    [], 'merge', sbox.repo_url + '/A/D/H', H_COPY_path)
+
+  # Check the status after the merge.
+  expected_status.tweak('H_COPY', status=' M')
+  expected_status.tweak('H_COPY/psi', status='M ')
+  expected_status.tweak('H_COPY/nu', status='D ')
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+  check_mergeinfo_recursively(wc_dir,
+                              { H_COPY_path: '/A/D/H:3-6' })
+
 ########################################################################
 # Run the tests
 
@@ -17963,6 +18075,7 @@ test_list = [ None,
               reverse_merge_with_rename,
               merge_adds_then_deletes_subtree,
               merge_with_added_subtrees_with_mergeinfo,
+              dont_merge_revs_into_subtree_that_predate_it2,
              ]
 
 if __name__ == '__main__':
