You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2010/11/05 21:35:23 UTC

svn commit: r1031780 - in /subversion/branches/issue-3668-3669/subversion: libsvn_client/copy.c libsvn_client/merge.c libsvn_client/mergeinfo.c libsvn_client/mergeinfo.h tests/cmdline/merge_reintegrate_tests.py tests/cmdline/merge_tests.py

Author: pburba
Date: Fri Nov  5 20:35:22 2010
New Revision: 1031780

URL: http://svn.apache.org/viewvc?rev=1031780&view=rev
Log:
On the issue-3668-3669 branch: Fix issue #3669 'inheritance can result in
mergeinfo describing nonexistent sources'.

* subversion/libsvn_client/copy.c

  (svn_client__get_repos_mergeinfo): Update call to
   svn_client__get_repos_mergeinfo().

* subversion/libsvn_client/merge.c

  (svn_client__get_repos_mergeinfo): New.

  (get_full_mergeinfo): Use new function to validate inherited mergeinfo.

* subversion/libsvn_client/mergeinfo.h

  (svn_client__get_repos_mergeinfo,
   svn_client__get_repos_mergeinfo_catalog): Add new arg to optionally
   validate inherited mergeinfo

* subversion/libsvn_client/mergeinfo.c

  (svn_client__get_repos_mergeinfo,
   svn_client__get_repos_mergeinfo_catalog): Add new arg to optionally
   validate inherited mergeinfo

  (svn_client__get_wc_or_repos_mergeinfo_catalog,
   get_mergeinfo): Update calls to svn_client__get_repos_mergeinfo_catalog.
 
* subversion/tests/cmdline/merge_reintegrate_tests.py

  (added_subtrees_with_mergeinfo_break_reintegrate): Don't expect mergeinfo
   update notification to be ' G' anymore, rather ' U' because the diff
   applied by the reintegrate is now inoperative.

* subversion/tests/cmdline/merge_tests.py

  (new_subtrees_should_not_break_merge): Don't expect inherited mergeinfo to
   be self-referential.

  (no_self_referential_or_nonexistent_inherited_mergeinfo): Remove comment
   re XFail status.

  (test_list): Remove XFail from
   no_self_referential_or_nonexistent_inherited_mergeinfo.

Modified:
    subversion/branches/issue-3668-3669/subversion/libsvn_client/copy.c
    subversion/branches/issue-3668-3669/subversion/libsvn_client/merge.c
    subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.c
    subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.h
    subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_reintegrate_tests.py
    subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_tests.py

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_client/copy.c?rev=1031780&r1=1031779&r2=1031780&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_client/copy.c Fri Nov  5 20:35:22 2010
@@ -129,7 +129,7 @@ calculate_target_mergeinfo(svn_ra_sessio
       SVN_ERR(svn_client__get_repos_mergeinfo(ra_session, &src_mergeinfo,
                                               "", src_revnum,
                                               svn_mergeinfo_inherited,
-                                              TRUE, pool));
+                                              TRUE, FALSE, pool));
       if (old_session_url)
         SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
     }

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_client/merge.c?rev=1031780&r1=1031779&r2=1031780&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_client/merge.c Fri Nov  5 20:35:22 2010
@@ -3290,6 +3290,86 @@ fix_deleted_subtree_ranges(const char *u
 
 /*** Determining What Remains To Be Merged ***/
 
+
+/* Set *INVALID_INHERITED_MERGEINFO to the mergeinfo that working copy path
+   TARGET_ABSPATH inherits, less any merge source path-revisions that don't
+   actually exist in the repository.  If all inherited mergeinfo describes
+   non-existent paths, then *INVALID_INHERITED_MERGEINFO is set to an empty
+   hash.  If TARGET_ABSPATH inherits no mergeinfo whatsoever (pre-validation),
+   then *INVALID_INHERITED_MERGEINFO is set to NULL.
+
+   RA_SESSION is an open session that points to TARGET_ABSPATH's repository
+   location or to the location of one of TARGET_ABSPATH's parents.  It may
+   be temporarily reparented.
+
+   RESULT_POOL is used to allocate *INVALID_INHERITED_MERGEINFO, SCRATCH_POOL
+   is used for any temporary allocations. */
+static svn_error_t *
+get_invalid_inherited_mergeinfo(svn_mergeinfo_t *invalid_inherited_mergeinfo,
+                                svn_ra_session_t *ra_session,
+                                const char *target_abspath,
+                                svn_client_ctx_t *ctx,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool)
+{
+  svn_mergeinfo_t repos_raw_inherited;
+  svn_mergeinfo_t repos_validated_inherited;
+  svn_revnum_t base_revision;
+
+  /* Our starting assumption. */ 
+  *invalid_inherited_mergeinfo = NULL;
+
+  SVN_ERR(svn_wc__node_get_base_rev(&base_revision, ctx->wc_ctx,
+                                    target_abspath, scratch_pool));
+
+  /* If there is no base revision then TARGET_ABSPATH doesn't exist
+     in the repository yet, so we're done. */
+  if (SVN_IS_VALID_REVNUM(base_revision))
+    {
+      const char *target_url;
+      const char *session_url;
+
+      /* Reparent RA_SESSION if necessary. */
+      SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, target_abspath,
+                                   scratch_pool, scratch_pool));
+      SVN_ERR(svn_client__ensure_ra_session_url(&session_url, ra_session,
+                                                target_url, scratch_pool));
+
+      /* Contact the repository to derive the portion of
+         TARGET_ABSPATH's inherited mergeinfo which is non-existent
+         and remove it from */
+      SVN_ERR(svn_client__get_repos_mergeinfo(
+        ra_session, &repos_raw_inherited, "", base_revision,
+        svn_mergeinfo_inherited, TRUE,
+        FALSE, /* validate_inherited_mergeinfo */
+        scratch_pool));
+
+      if (repos_raw_inherited == NULL)
+        {
+          *invalid_inherited_mergeinfo = NULL;
+        }
+      else if (apr_hash_count(repos_raw_inherited) == 0)
+        {
+          *invalid_inherited_mergeinfo = apr_hash_make(result_pool);
+        }
+      else
+        {
+          SVN_ERR(svn_client__get_repos_mergeinfo(
+            ra_session, &repos_validated_inherited, "", base_revision,
+            svn_mergeinfo_inherited, TRUE,
+            TRUE, /* validate_inherited_mergeinfo */
+            scratch_pool));
+          SVN_ERR(svn_mergeinfo_remove2(invalid_inherited_mergeinfo,
+                                        repos_validated_inherited,
+                                        repos_raw_inherited, FALSE,
+                                        result_pool, scratch_pool));
+        }
+      SVN_ERR(svn_client__ensure_ra_session_url(&session_url, ra_session,
+                                                session_url, scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
+
 /* Get explicit and/or implicit mergeinfo for the working copy path
    TARGET_ABSPATH.
 
@@ -3314,6 +3394,9 @@ fix_deleted_subtree_ranges(const char *u
    is older than START, then the base revision is used as the younger
    bound in place of START.
 
+   RA_SESSION is an open session that may be temporarily reparented as
+   needed by this function.
+
    Allocate *RECORDED_MERGEINFO and *IMPLICIT_MERGEINFO in RESULT_POOL.
    Use SCRATCH_POOL for any temporary allocations. */
 static svn_error_t *
@@ -3331,8 +3414,10 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
 {
   svn_boolean_t inherited = FALSE;
 
-  /* First, we get the real mergeinfo. */
-  if (recorded_mergeinfo)
+  /* First, we get the real mergeinfo.  We use SCRATCH_POOL throughout this
+     block because we'll make a final copy of *RECORDED_MERGEINFO only after
+     removing any self-referential mergeinfo. */
+if (recorded_mergeinfo)
     {
       /* ### FIXME: There's probably an RA session we could/should be
          ### using here instead of having this function possibly spawn
@@ -3344,6 +3429,25 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
                                                     ctx, scratch_pool));
       if (indirect)
         *indirect = inherited;
+
+      /* Issue #3669: Remove any non-existent mergeinfo sources
+         from TARGET_ABSPATH's inherited mergeinfo. */
+      if (inherited)
+        {
+          svn_mergeinfo_t invalid_inherited_mergeinfo;
+
+          SVN_ERR(get_invalid_inherited_mergeinfo(&invalid_inherited_mergeinfo,
+                                                  ra_session, target_abspath,
+                                                  ctx, scratch_pool,
+                                                  scratch_pool));
+
+          if (invalid_inherited_mergeinfo
+              && apr_hash_count(invalid_inherited_mergeinfo))
+            SVN_ERR(svn_mergeinfo_remove2(recorded_mergeinfo,
+                                          invalid_inherited_mergeinfo,
+                                          *recorded_mergeinfo, FALSE,
+                                          scratch_pool, scratch_pool));
+        }
     }
 
   if (implicit_mergeinfo)
@@ -3351,7 +3455,6 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
       const char *session_url = NULL, *url;
       svn_revnum_t target_rev;
       svn_opt_revision_t peg_revision;
-      apr_pool_t *sesspool = NULL;
       svn_error_t *err;
 
       /* Assert that we have sane input. */
@@ -3359,10 +3462,12 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
                  && SVN_IS_VALID_REVNUM(end)
                  && (start > end));
 
+      *implicit_mergeinfo = NULL;
+
       peg_revision.kind = svn_opt_revision_working;
       err = svn_client__derive_location(&url, &target_rev, target_abspath,
                                         &peg_revision, ra_session,
-                                        ctx, result_pool, scratch_pool);
+                                        ctx, scratch_pool, scratch_pool);
 
       if (err)
         {
@@ -3375,7 +3480,6 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
                * mergeinfo is empty. */
               svn_error_clear(err);
               *implicit_mergeinfo = apr_hash_make(result_pool);
-              return SVN_NO_ERROR;
             }
           else
             return svn_error_return(err);
@@ -3386,49 +3490,37 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
           /* We're asking about a range outside our natural history
              altogether.  That means our implicit mergeinfo is empty. */
           *implicit_mergeinfo = apr_hash_make(result_pool);
-          return SVN_NO_ERROR;
         }
 
-      /* Temporarily point our RA_SESSION at our target URL so we can
-         fetch so-called "implicit mergeinfo" (that is, natural history). */
-      if (ra_session)
+      if (*implicit_mergeinfo == NULL)
         {
-          SVN_ERR(svn_client__ensure_ra_session_url(&session_url, ra_session,
-                                                    url, scratch_pool));
-        }
-      else
-        {
-          SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url,
-                                                       NULL, NULL,
-                                                       FALSE, TRUE,
-                                                       ctx, scratch_pool));
-        }
-
-      /* Do not ask for implicit mergeinfo from TARGET_ABSPATH's future.
-         TARGET_ABSPATH might not even exist, and even if it does the
-         working copy is *at* TARGET_REV so its implicit history ends
-         at TARGET_REV! */
-      if (target_rev < start)
-        start = target_rev;
-
-      /* Fetch the implicit mergeinfo. */
-      peg_revision.kind = svn_opt_revision_number;
-      peg_revision.value.number = target_rev;
-      SVN_ERR(svn_client__get_history_as_mergeinfo(implicit_mergeinfo, url,
-                                                   &peg_revision, start, end,
-                                                   ra_session, ctx,
-                                                   result_pool));
+          /* Temporarily point our RA_SESSION at our target URL so we can
+             fetch so-called "implicit mergeinfo" (that is, natural
+             history). */
+          SVN_ERR(svn_client__ensure_ra_session_url(&session_url,
+                                                    ra_session, url,
+                                                    scratch_pool));
 
-      /* If we created an RA_SESSION above, destroy it.  Otherwise, if
-         reparented an existing session, point it back where it was when
-         we were called. */
-      if (sesspool)
-        {
-          svn_pool_destroy(sesspool);
-        }
-      else if (session_url)
-        {
-          SVN_ERR(svn_ra_reparent(ra_session, session_url, scratch_pool));
+          /* Do not ask for implicit mergeinfo from TARGET_ABSPATH's future.
+             TARGET_ABSPATH might not even exist, and even if it does the
+             working copy is *at* TARGET_REV so its implicit history ends
+             at TARGET_REV! */
+          if (target_rev < start)
+            start = target_rev;
+
+          /* Fetch the implicit mergeinfo. */
+          peg_revision.kind = svn_opt_revision_number;
+          peg_revision.value.number = target_rev;
+          SVN_ERR(svn_client__get_history_as_mergeinfo(implicit_mergeinfo,
+                                                       url, &peg_revision,
+                                                       start, end,
+                                                       ra_session, ctx,
+                                                       result_pool));
+
+          /* Return RA_SESSION back to where it was when we were called. */
+         SVN_ERR(svn_client__ensure_ra_session_url(&session_url,
+                                                   ra_session, session_url,
+                                                   scratch_pool)); 
         }
     } /*if (implicit_mergeinfo) */
 

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.c?rev=1031780&r1=1031779&r2=1031780&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.c Fri Nov  5 20:35:22 2010
@@ -442,6 +442,7 @@ svn_client__get_repos_mergeinfo(svn_ra_s
                                 svn_revnum_t rev,
                                 svn_mergeinfo_inheritance_t inherit,
                                 svn_boolean_t squelch_incapable,
+                                svn_boolean_t validate_inherited_mergeinfo,
                                 apr_pool_t *pool)
 {
   svn_mergeinfo_catalog_t tgt_mergeinfo_cat;
@@ -452,6 +453,7 @@ svn_client__get_repos_mergeinfo(svn_ra_s
                                                   ra_session,
                                                   rel_path, rev, inherit,
                                                   squelch_incapable, FALSE,
+                                                  validate_inherited_mergeinfo,
                                                   pool, pool));
 
   if (tgt_mergeinfo_cat && apr_hash_count(tgt_mergeinfo_cat))
@@ -468,15 +470,17 @@ svn_client__get_repos_mergeinfo(svn_ra_s
 }
 
 svn_error_t *
-svn_client__get_repos_mergeinfo_catalog(svn_mergeinfo_catalog_t *mergeinfo_cat,
-                                        svn_ra_session_t *ra_session,
-                                        const char *rel_path,
-                                        svn_revnum_t rev,
-                                        svn_mergeinfo_inheritance_t inherit,
-                                        svn_boolean_t squelch_incapable,
-                                        svn_boolean_t include_descendants,
-                                        apr_pool_t *result_pool,
-                                        apr_pool_t *scratch_pool)
+svn_client__get_repos_mergeinfo_catalog(
+  svn_mergeinfo_catalog_t *mergeinfo_cat,
+  svn_ra_session_t *ra_session,
+  const char *rel_path,
+  svn_revnum_t rev,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t squelch_incapable,
+  svn_boolean_t include_descendants,
+  svn_boolean_t validate_inherited_mergeinfo,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
   svn_mergeinfo_t repos_mergeinfo;
@@ -486,8 +490,9 @@ svn_client__get_repos_mergeinfo_catalog(
   APR_ARRAY_PUSH(rel_paths, const char *) = rel_path;
 
   /* Fetch the mergeinfo. */
-  err = svn_ra_get_mergeinfo(ra_session, &repos_mergeinfo, rel_paths, rev,
-                             inherit, include_descendants, result_pool);
+  err = svn_ra_get_mergeinfo2(ra_session, &repos_mergeinfo, rel_paths, rev,
+                              inherit, validate_inherited_mergeinfo,
+                              include_descendants, result_pool);
   if (err)
     {
       if (squelch_incapable && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
@@ -624,7 +629,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
               SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
                         target_mergeinfo_catalog, ra_session,
                         "", target_rev, inherit,
-                        TRUE, FALSE, result_pool, scratch_pool));
+                        TRUE, FALSE, FALSE, result_pool, scratch_pool));
 
               if (*target_mergeinfo_catalog
                   && apr_hash_get(*target_mergeinfo_catalog, "",
@@ -1043,7 +1048,7 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
                                                       svn_mergeinfo_inherited,
                                                       FALSE,
                                                       include_descendants,
-                                                      result_pool,
+                                                      FALSE, result_pool,
                                                       scratch_pool));
 
       /* If we're not querying the root of the repository, the catalog

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.h?rev=1031780&r1=1031779&r2=1031780&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_client/mergeinfo.h Fri Nov  5 20:35:22 2010
@@ -155,7 +155,12 @@ svn_client__get_wc_mergeinfo_catalog(svn
 
    If there is no mergeinfo available for REL_PATH, or if the server
    doesn't support a mergeinfo capability and SQUELCH_INCAPABLE is
-   TRUE, set *TARGET_MERGEINFO to NULL. */
+   TRUE, set *TARGET_MERGEINFO to NULL.
+
+   If the *TARGET_MERGEINFO for REL_PATH path is inherited and
+   VALIDATE_INHERITED_MERGEINFO is TRUE, then *TARGET_MERGEINFO
+   will only contain merge source path-revisions that actually
+   exist in repository. */
 svn_error_t *
 svn_client__get_repos_mergeinfo(svn_ra_session_t *ra_session,
                                 svn_mergeinfo_t *target_mergeinfo,
@@ -163,6 +168,7 @@ svn_client__get_repos_mergeinfo(svn_ra_s
                                 svn_revnum_t rev,
                                 svn_mergeinfo_inheritance_t inherit,
                                 svn_boolean_t squelch_incapable,
+                                svn_boolean_t validate_inherited_mergeinfo,
                                 apr_pool_t *pool);
 
 /* If INCLUDE_DESCENDANTS is FALSE, behave exactly like
@@ -176,15 +182,17 @@ svn_client__get_repos_mergeinfo(svn_ra_s
    paths of the subtrees.  If no mergeinfo is found, then
    *TARGET_MERGEINFO_CAT is set to NULL. */
 svn_error_t *
-svn_client__get_repos_mergeinfo_catalog(svn_mergeinfo_catalog_t *mergeinfo_cat,
-                                        svn_ra_session_t *ra_session,
-                                        const char *rel_path,
-                                        svn_revnum_t rev,
-                                        svn_mergeinfo_inheritance_t inherit,
-                                        svn_boolean_t squelch_incapable,
-                                        svn_boolean_t include_descendants,
-                                        apr_pool_t *result_pool,
-                                        apr_pool_t *scratch_pool);
+svn_client__get_repos_mergeinfo_catalog(
+  svn_mergeinfo_catalog_t *mergeinfo_cat,
+  svn_ra_session_t *ra_session,
+  const char *rel_path,
+  svn_revnum_t rev,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t squelch_incapable,
+  svn_boolean_t include_descendants,
+  svn_boolean_t validate_inherited_mergeinfo,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool);
 
 /* Retrieve the direct mergeinfo for the TARGET_WCPATH from the WC's
    mergeinfo prop, or that inherited from its nearest ancestor if the

Modified: subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1031780&r1=1031779&r2=1031780&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_reintegrate_tests.py Fri Nov  5 20:35:22 2010
@@ -1997,7 +1997,7 @@ def added_subtrees_with_mergeinfo_break_
     })
   expected_mergeinfo_output = wc.State(A_path, {
     ''     : Item(status=' U'),
-    'C/nu' : Item(status=' G'),
+    'C/nu' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_path, {
     })

Modified: subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_tests.py?rev=1031780&r1=1031779&r2=1031780&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/issue-3668-3669/subversion/tests/cmdline/merge_tests.py Fri Nov  5 20:35:22 2010
@@ -9586,7 +9586,7 @@ def new_subtrees_should_not_break_merge(
     'D/H/psi'   : Item("This is the file 'psi'.\n"),
     'D/H/omega' : Item("New content"),
     'D/H/nu'    : Item("New content",
-                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:7-8'}),
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:8'}),
     })
   expected_skip = wc.State(A_COPY_path, { })
   svntest.actions.run_and_verify_merge(A_COPY_path, '4', '6',
@@ -9632,7 +9632,7 @@ def new_subtrees_should_not_break_merge(
     'H/psi'   : Item("This is the file 'psi'.\n"),
     'H/omega' : Item("This is the file 'omega'.\n"),
     'H/nu'    : Item("New content",
-                     props={SVN_PROP_MERGEINFO : '/A/D/H/nu:7-8'}),
+                     props={SVN_PROP_MERGEINFO : '/A/D/H/nu:8'}),
     })
   expected_skip = wc.State(D_COPY_path, { })
   svntest.actions.run_and_verify_merge(D_COPY_path, '6', '5',
@@ -9704,7 +9704,7 @@ def new_subtrees_should_not_break_merge(
     'D/H/psi'   : Item("This is the file 'psi'.\n"),
     'D/H/omega' : Item("New content"),
     'D/H/nu'    : Item("New content",
-                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:7-8'}),
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:8'}),
     })
   expected_skip = wc.State(A_COPY_path, { })
   svntest.actions.run_and_verify_merge(A_COPY_path, '5', '6',
@@ -16157,10 +16157,6 @@ def no_self_referential_or_nonexistent_i
   # Update the WC in preparation for merges.
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
-  # This test is marked as XFail because the following two merges
-  # create mergeinfo with both non-existent path-revs and self-referential
-  # mergeinfo.c
-  #
   # Merge all available revisions from A/C/nu to A_COPY/C/nu.
   # The target has no explicit mergeinfo of its own but inherits mergeinfo
   # from A_COPY.  A_COPY has the mergeinfo '/A:2-9' so the naive mergeinfo
@@ -16414,7 +16410,7 @@ test_list = [ None,
               merge_into_locally_added_file,
               merge_into_locally_added_directory,
               merge_with_os_deleted_subtrees,
-              XFail(no_self_referential_or_nonexistent_inherited_mergeinfo),
+              no_self_referential_or_nonexistent_inherited_mergeinfo,
              ]
 
 if __name__ == '__main__':