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/17 02:08:29 UTC

svn commit: r1035894 - in /subversion/trunk: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_ra/ subversion/libsvn_ra_local/ subver...

Author: pburba
Date: Wed Nov 17 01:08:28 2010
New Revision: 1035894

URL: http://svn.apache.org/viewvc?rev=1035894&view=rev
Log:
Reintegrate the issue-3668-3669 branch.

Modified:
    subversion/trunk/   (props changed)
    subversion/trunk/subversion/include/private/svn_dav_protocol.h
    subversion/trunk/subversion/include/svn_fs.h
    subversion/trunk/subversion/include/svn_ra.h
    subversion/trunk/subversion/include/svn_repos.h
    subversion/trunk/subversion/libsvn_client/copy.c
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.h
    subversion/trunk/subversion/libsvn_fs/fs-loader.c
    subversion/trunk/subversion/libsvn_fs/fs-loader.h
    subversion/trunk/subversion/libsvn_fs_base/tree.c
    subversion/trunk/subversion/libsvn_fs_fs/tree.c
    subversion/trunk/subversion/libsvn_ra/deprecated.c
    subversion/trunk/subversion/libsvn_ra/ra_loader.c
    subversion/trunk/subversion/libsvn_ra/ra_loader.h
    subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
    subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c
    subversion/trunk/subversion/libsvn_ra_neon/options.c
    subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h
    subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c
    subversion/trunk/subversion/libsvn_ra_serf/options.c
    subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
    subversion/trunk/subversion/libsvn_ra_svn/client.c
    subversion/trunk/subversion/libsvn_repos/fs-wrap.c
    subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
    subversion/trunk/subversion/svnserve/serve.c
    subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
    subversion/trunk/subversion/tests/cmdline/merge_tests.py

Propchange: subversion/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Nov 17 01:08:28 2010
@@ -19,6 +19,7 @@
 /subversion/branches/issue-3220-dev:872210-872226
 /subversion/branches/issue-3242-dev:879653-896436
 /subversion/branches/issue-3334-dirs:875156-875867
+/subversion/branches/issue-3668-3669:1031000-1035744
 /subversion/branches/kwallet:870785-871314
 /subversion/branches/log-g-performance:870941-871032
 /subversion/branches/merge-skips-obstructions:874525-874615

Modified: subversion/trunk/subversion/include/private/svn_dav_protocol.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_dav_protocol.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_dav_protocol.h (original)
+++ subversion/trunk/subversion/include/private/svn_dav_protocol.h Wed Nov 17 01:08:28 2010
@@ -43,6 +43,7 @@ extern "C" {
 #define SVN_DAV__PATH "path"
 #define SVN_DAV__INHERIT "inherit"
 #define SVN_DAV__REVISION "revision"
+#define SVN_DAV__VALIDATE_INHERITED "validate-inherited"
 #define SVN_DAV__INCLUDE_DESCENDANTS "include-descendants"
 #define SVN_DAV__VERSION_NAME "version-name"
 

Modified: subversion/trunk/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_fs.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_fs.h (original)
+++ subversion/trunk/subversion/include/svn_fs.h Wed Nov 17 01:08:28 2010
@@ -1477,16 +1477,36 @@ svn_fs_closest_copy(svn_fs_root_t **root
  * @a inherit indicates whether to retrieve explicit,
  * explicit-or-inherited, or only inherited mergeinfo.
  *
+ * If the mergeinfo for any path is inherited and
+ * @a validate_inherited_mergeinfo is TRUE, then the mergeinfo for
+ * that path in @a *catalog will only contain merge source
+ * path-revisions that actually exist in repository.
+ *
  * If @a include_descendants is TRUE, then additionally return the
  * mergeinfo for any descendant of any element of @a paths which has
  * the #SVN_PROP_MERGEINFO property explicitly set on it.  (Note
  * that inheritance is only taken into account for the elements in @a
  * paths; descendants of the elements in @a paths which get their
- * mergeinfo via inheritance are not included in @a *mergeoutput.)
+ * mergeinfo via inheritance are not included in @a *catalog.)
  *
  * Do any necessary temporary allocation in @a pool.
  *
- * @since New in 1.5.
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+                      svn_fs_root_t *root,
+                      const apr_array_header_t *paths,
+                      svn_mergeinfo_inheritance_t inherit,
+                      svn_boolean_t validate_inherited_mergeinfo,
+                      svn_boolean_t include_descendants,
+                      apr_pool_t *pool);
+
+/**
+ * Similar to svn_fs_get_mergeinfo2(), but with
+ * @a validate_inherited_mergeinfo always passed as FALSE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
 svn_error_t *
 svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
@@ -1496,6 +1516,25 @@ svn_fs_get_mergeinfo(svn_mergeinfo_catal
                      svn_boolean_t include_descendants,
                      apr_pool_t *pool);
 
+/**
+ * Set @a *validated_mergeinfo equal to deep copy of @a mergeinfo, less
+ * any mergeinfo that describes path-revs that do not exist in @a FS.
+ * If @a mergeinfo is empty then @a *validated_mergeinfo is set to an empty
+ * mergeinfo hash.  If @a mergeinfo is NULL then @a *validated_mergeinfo is
+ * set to NULL.
+ *
+ * @a *validated_mergeinfo is allocated in @a result_pool.  All tempporary
+ * allocations are performed in @a scratch_pool.
+ *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_fs_validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                          svn_mergeinfo_t mergeinfo,
+                          svn_fs_t *fs,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool);
+
 /** Merge changes between two nodes into a third node.
  *
  * Given nodes @a source and @a target, and a common ancestor @a ancestor,

Modified: subversion/trunk/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_ra.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_ra.h (original)
+++ subversion/trunk/subversion/include/svn_ra.h Wed Nov 17 01:08:28 2010
@@ -1011,6 +1011,14 @@ svn_ra_get_dir(svn_ra_session_t *session
  * @a inherit indicates whether explicit, explicit or inherited, or
  * only inherited mergeinfo for @a paths is retrieved.
  *
+ * If the mergeinfo for any path is inherited and
+ * @a *validate_inherited_mergeinfo is TRUE, then request that the server
+ * validate the mergeinfo in @a *catalog, so it contains only merge source
+ * path-revisions that actually exist in repository.  If validation is
+ * requested and the server supports it, then set
+ * @a *validate_inherited_mergeinfo to TRUE on return.  Set it to FALSE
+ * in all other cases.
+ *
  * If @a include_descendants is TRUE, then additionally return the
  * mergeinfo for any descendant of any element of @a paths which has
  * the @c SVN_PROP_MERGEINFO property explicitly set on it.  (Note
@@ -1027,7 +1035,23 @@ svn_ra_get_dir(svn_ra_session_t *session
  * upgraded), return @c SVN_ERR_UNSUPPORTED_FEATURE in preference to
  * any other error that might otherwise be returned.
  *
- * @since New in 1.5.
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_ra_get_mergeinfo2(svn_ra_session_t *session,
+                      svn_mergeinfo_catalog_t *catalog,
+                      const apr_array_header_t *paths,
+                      svn_revnum_t revision,
+                      svn_mergeinfo_inheritance_t inherit,
+                      svn_boolean_t *validate_inherited_mergeinfo,
+                      svn_boolean_t include_descendants,
+                      apr_pool_t *pool);
+
+/**
+ * Similar to svn_ra_get_mergeinfo2(), but with
+ * @a validate_inherited_mergeinfo always passed as FALSE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
 svn_error_t *
 svn_ra_get_mergeinfo(svn_ra_session_t *session,

Modified: subversion/trunk/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_repos.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_repos.h (original)
+++ subversion/trunk/subversion/include/svn_repos.h Wed Nov 17 01:08:28 2010
@@ -1715,6 +1715,11 @@ svn_repos_get_logs(svn_repos_t *repos,
  * @a inherit indicates whether explicit, explicit or inherited, or
  * only inherited mergeinfo for @a paths is fetched.
  *
+ * If the mergeinfo for any path is inherited and
+ * @a validate_inherited_mergeinfo is TRUE, then the mergeinfo for
+ * that path in @a *catalog will only contain merge source
+ * path-revisions that actually exist in repository.
+ *
  * If @a revision is #SVN_INVALID_REVNUM, it defaults to youngest.
  *
  * If @a include_descendants is TRUE, then additionally return the
@@ -1731,7 +1736,25 @@ svn_repos_get_logs(svn_repos_t *repos,
  *
  * Use @a pool for all allocations.
  *
- * @since New in 1.5.
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_repos_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+                            svn_repos_t *repos,
+                            const apr_array_header_t *paths,
+                            svn_revnum_t revision,
+                            svn_mergeinfo_inheritance_t inherit,
+                            svn_boolean_t validate_inherited_mergeinfo,
+                            svn_boolean_t include_descendants,
+                            svn_repos_authz_func_t authz_read_func,
+                            void *authz_read_baton,
+                            apr_pool_t *pool);
+
+/**
+ * Similar to svn_repos_fs_get_mergeinfo2(), but with
+ * @a validate_inherited_mergeinfo always passed as FALSE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
 svn_error_t *
 svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,

Modified: subversion/trunk/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy.c Wed Nov 17 01:08:28 2010
@@ -118,6 +118,8 @@ calculate_target_mergeinfo(svn_ra_sessio
 
   if (! locally_added)
     {
+      svn_boolean_t validate_inherited_mergeinfo = FALSE;
+
       /* Fetch any existing (explicit) mergeinfo.  We'll temporarily
          reparent to the target URL here, just to keep the code simple.
          We could, as an alternative, first see if the target URL was a
@@ -128,8 +130,9 @@ calculate_target_mergeinfo(svn_ra_sessio
                                                 ra_session, src_url, pool));
       SVN_ERR(svn_client__get_repos_mergeinfo(ra_session, &src_mergeinfo,
                                               "", src_revnum,
-                                              svn_mergeinfo_inherited,
-                                              TRUE, pool));
+                                              svn_mergeinfo_inherited, TRUE,
+                                              &validate_inherited_mergeinfo,
+                                              pool));
       if (old_session_url)
         SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
     }

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Wed Nov 17 01:08:28 2010
@@ -3290,6 +3290,110 @@ fix_deleted_subtree_ranges(const char *u
 
 /*** Determining What Remains To Be Merged ***/
 
+
+/* Attempt to determine if a working copy path inherits any invalid
+   mergeinfo.
+
+   Query the repository for the mergeinfo TARGET_ABSPATH inherits at its
+   base revision and set *VALIDATED to indicate to the caller if we can
+   determine what portions of that inherited mergeinfo are invalid.
+
+   If no mergeinfo is inherited set *INVALID_INHERITED_MERGEINFO to NULL and
+   *VALIDATED to true.
+
+   If only empty mergeinfo is inherited set *INVALID_INHERITED_MERGEINFO to
+   and empty hash and *VALIDATED to true.
+
+   If non-empty inherited mergeinfo is inherited then, if the server (1.7+)
+   supports inherited mergeinfo validation, remove all valid path-revisions
+   from the raw inherited mergeinfo, set *INVALID_INHERITED_MERGEINFO to the
+   remainder, and set *VALIDATED to true.  If the server doesn't support
+   inherited mergeinfo validation then set *INVALID_INHERITED_MERGEINFO to
+   NULL and set *VALIDATED to false.
+
+   Note that if validation occurs, but all inherited mergeinfo describes
+   non-existent paths, then *INVALID_INHERITED_MERGEINFO is set to an empty
+   hash.
+
+   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_boolean_t *validated,
+                                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;
+  svn_boolean_t validate_inherited_mergeinfo;
+
+  /* Our starting assumptions. */ 
+  *invalid_inherited_mergeinfo = NULL;
+  *validated = TRUE;
+
+  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 */
+      validate_inherited_mergeinfo = FALSE;
+      SVN_ERR(svn_client__get_repos_mergeinfo(
+        ra_session, &repos_raw_inherited, "", base_revision,
+        svn_mergeinfo_inherited, TRUE,
+        &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,
+            validated,
+            scratch_pool));
+          if (*validated)
+            SVN_ERR(svn_mergeinfo_remove2(invalid_inherited_mergeinfo,
+                                          repos_validated_inherited,
+                                          repos_raw_inherited, FALSE,
+                                          result_pool, scratch_pool));
+          else
+            *invalid_inherited_mergeinfo = NULL;
+        }
+      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.
 
@@ -3300,6 +3404,10 @@ fix_deleted_subtree_ranges(const char *u
    If IMPLICIT_MERGEINFO is not NULL then set *IMPLICIT_MERGEINFO
    to TARGET_ABSPATH's implicit mergeinfo (a.k.a. natural history).
 
+   If both RECORDED_MERGEINFO and IMPLICIT_MERGEINFO are not NULL and
+   *RECORDED_MERGEINFO is inherited, then *IMPLICIT_MERGEINFO will be
+   removed from *RECORDED_MERGEINFO.
+
    If INDIRECT is not NULL set *INDIRECT to TRUE if *RECORDED_MERGEINFO
    is inherited and not explicit.  If RECORDED_MERGEINFO is NULL then
    INDIRECT is ignored.
@@ -3310,6 +3418,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 *
@@ -3325,11 +3436,14 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
                    apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
 {
-  /* First, we get the real mergeinfo. */
+  svn_boolean_t inherited = FALSE;
+  svn_boolean_t inherited_validated = FALSE;
+
+  /* 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)
     {
-      svn_boolean_t inherited;
-
       /* ### FIXME: There's probably an RA session we could/should be
          ### using here instead of having this function possibly spawn
          ### yet another one.  */
@@ -3337,9 +3451,29 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
                                                     &inherited, FALSE,
                                                     inherit, NULL,
                                                     target_abspath,
-                                                    ctx, result_pool));
+                                                    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, &inherited_validated,
+            ra_session, target_abspath, ctx,
+            scratch_pool, scratch_pool));
+
+          if (inherited_validated
+              && 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)
@@ -3347,7 +3481,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. */
@@ -3355,10 +3488,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)
         {
@@ -3371,7 +3506,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);
@@ -3382,52 +3516,60 @@ 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)
-        {
-          SVN_ERR(svn_client__ensure_ra_session_url(&session_url, ra_session,
-                                                    url, scratch_pool));
-        }
-      else
+      if (*implicit_mergeinfo == NULL)
         {
-          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) */
 
+
+  if (recorded_mergeinfo && *recorded_mergeinfo)
+    {
+      /* Issue #3668: Remove any self-referential mergeinfo from that
+         which TARGET_ABSPATH inherited; but only do this if we were able to
+         validate inherited mergeinfo (issue #3669) or otherwise we end
+         up with fragmented mergeinfo, see
+         http://subversion.tigris.org/issues/show_bug.cgi?id=3668#desc5 */
+      if (implicit_mergeinfo
+          && inherited
+          && inherited_validated)
+        SVN_ERR(svn_mergeinfo_remove2(recorded_mergeinfo,
+                                      *implicit_mergeinfo,
+                                      *recorded_mergeinfo, FALSE,
+                                      result_pool, scratch_pool));
+      else
+        *recorded_mergeinfo = svn_mergeinfo_dup(*recorded_mergeinfo,
+          result_pool);
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -4258,7 +4400,7 @@ populate_remaining_ranges(apr_array_head
         svn_mergeinfo_inherited, ra_session,
         child->abspath,
         MAX(revision1, revision2),
-        MIN(revision1, revision2),
+        0, /* Get all implicit mergeinfo */
         merge_b->ctx, pool, pool));
 
       /* If CHILD isn't the merge target find its parent. */
@@ -6643,7 +6785,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
                                  &indirect, svn_mergeinfo_inherited,
                                  merge_b->ra_session1, target_abspath,
                                  MAX(revision1, revision2),
-                                 MIN(revision1, revision2),
+                                 0, /* Get all implicit mergeinfo */
                                  ctx, scratch_pool, scratch_pool));
 
       SVN_ERR(svn_ra_reparent(merge_b->ra_session1, url1, scratch_pool));

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.c Wed Nov 17 01:08:28 2010
@@ -442,17 +442,16 @@ 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;
 
   *target_mergeinfo = NULL;
 
-  SVN_ERR(svn_client__get_repos_mergeinfo_catalog(&tgt_mergeinfo_cat,
-                                                  ra_session,
-                                                  rel_path, rev, inherit,
-                                                  squelch_incapable, FALSE,
-                                                  pool, pool));
+  SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
+    &tgt_mergeinfo_cat, 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 +467,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 +487,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)
@@ -606,6 +608,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
             {
               const char *session_url = NULL;
               apr_pool_t *sesspool = NULL;
+              svn_boolean_t validate_inherited_mergeinfo = FALSE;
 
               if (ra_session)
                 {
@@ -624,7 +627,8 @@ 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, &validate_inherited_mergeinfo,
+                        result_pool, scratch_pool));
 
               if (*target_mergeinfo_catalog
                   && apr_hash_get(*target_mergeinfo_catalog, "",
@@ -1027,6 +1031,7 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
   if (is_url)
     {
       svn_mergeinfo_catalog_t tmp_catalog;
+      svn_boolean_t validate_inherited_mergeinfo = FALSE;
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", scratch_pool));
       SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL,
@@ -1037,14 +1042,10 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
                                               local_abspath, ra_session,
                                               &peg_rev, scratch_pool));
       SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, scratch_pool));
-      SVN_ERR(svn_client__get_repos_mergeinfo_catalog(&tmp_catalog,
-                                                      ra_session,
-                                                      "", rev,
-                                                      svn_mergeinfo_inherited,
-                                                      FALSE,
-                                                      include_descendants,
-                                                      result_pool,
-                                                      scratch_pool));
+      SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
+        &tmp_catalog, ra_session, "", rev, svn_mergeinfo_inherited,
+        FALSE, include_descendants, &validate_inherited_mergeinfo,
+        result_pool, scratch_pool));
 
       /* If we're not querying the root of the repository, the catalog
          we fetched will be keyed on paths relative to the session

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.h Wed Nov 17 01:08:28 2010
@@ -155,7 +155,20 @@ 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.
+
+   If the *TARGET_MERGEINFO for REL_PATH path is inherited and
+   *VALIDATE_INHERITED_MERGEINFO is TRUE, then request that the server
+   validate the mergeinfo in *TARGET_MERGEINFO, so it contains only merge
+   source path-revisions that actually exist in repository.  If validation
+   is requested and the server supports it, then set
+   *VALIDATE_INHERITED_MERGEINFO to TRUE on return.  Set it to FALSE in
+   all other cases. */
 svn_error_t *
 svn_client__get_repos_mergeinfo(svn_ra_session_t *ra_session,
                                 svn_mergeinfo_t *target_mergeinfo,
@@ -163,6 +176,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 +190,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/trunk/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.c Wed Nov 17 01:08:28 2010
@@ -991,6 +991,22 @@ svn_fs_closest_copy(svn_fs_root_t **root
 }
 
 svn_error_t *
+svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+                      svn_fs_root_t *root,
+                      const apr_array_header_t *paths,
+                      svn_mergeinfo_inheritance_t inherit,
+                      svn_boolean_t validate_inherited_mergeinfo,
+                      svn_boolean_t include_descendants,
+                      apr_pool_t *pool)
+{
+  return svn_error_return(root->vtable->get_mergeinfo(catalog, root, paths,
+                                                      inherit,
+                                                      validate_inherited_mergeinfo,
+                                                      include_descendants,
+                                                      pool));
+}
+
+svn_error_t *
 svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
                      svn_fs_root_t *root,
                      const apr_array_header_t *paths,
@@ -998,10 +1014,133 @@ svn_fs_get_mergeinfo(svn_mergeinfo_catal
                      svn_boolean_t include_descendants,
                      apr_pool_t *pool)
 {
-  return svn_error_return(root->vtable->get_mergeinfo(catalog, root, paths,
-                                                      inherit,
-                                                      include_descendants,
-                                                      pool));
+  return svn_error_return(svn_fs_get_mergeinfo2(catalog, root, paths,
+                                                inherit,
+                                                FALSE,
+                                                include_descendants,
+                                                pool));
+}
+
+svn_error_t *
+svn_fs_validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                          svn_mergeinfo_t mergeinfo,
+                          svn_fs_t *fs,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  svn_mergeinfo_t filtered_mergeinfo;
+  apr_hash_t *rev_to_sources;
+  apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
+
+  /* A couple easy outs. */
+  if (mergeinfo == NULL)
+    {
+      *validated_mergeinfo = NULL;
+      return SVN_NO_ERROR;
+    }
+  else if (apr_hash_count(mergeinfo) == 0)
+    {
+      *validated_mergeinfo = apr_hash_make(result_pool);
+      return SVN_NO_ERROR;
+    }
+
+  filtered_mergeinfo = apr_hash_make(scratch_pool);
+  rev_to_sources = apr_hash_make(scratch_pool);
+
+  /* Since svn_fs_check_path needs an svn_fs_root_t based on a revision,
+     we convert MERGEINFO into a mapping of revisions to a hash of source
+     paths for efficiency. */
+  for (hi = apr_hash_first(scratch_pool, mergeinfo);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *path = svn__apr_hash_index_key(hi);
+      apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
+      int i;
+
+      for (i = 0; i < rangelist->nelts; i++)
+        {
+          svn_merge_range_t *range =
+            APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+          svn_revnum_t j;
+
+          for (j = range->start + 1; j <= range->end; j++)
+            {
+              apr_hash_t *paths_for_rev = apr_hash_get(rev_to_sources,
+                                                       &j,
+                                                       sizeof(svn_revnum_t));
+
+              /* No hash associated with this rev yet? */
+              if (!paths_for_rev)
+                {
+                  svn_revnum_t *rev = apr_palloc(scratch_pool, sizeof(*rev));
+
+                  *rev = j;
+                  paths_for_rev = apr_hash_make(scratch_pool);
+                  apr_hash_set(rev_to_sources, rev,
+                               sizeof(svn_revnum_t), paths_for_rev);
+                }
+
+              apr_hash_set(paths_for_rev, path, APR_HASH_KEY_STRING, path);
+            }
+        }
+    }
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  /* Validate the rev->source MERGEINFO equivalent hash, building the
+     validated mergeinfo as we go. */
+  for (hi = apr_hash_first(scratch_pool, rev_to_sources);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      apr_pool_t *inner_iterpool;
+      apr_hash_index_t *hi2;
+      svn_node_kind_t kind;
+      const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
+      apr_hash_t *paths = svn__apr_hash_index_val(hi);
+      svn_fs_root_t *mergeinfo_rev_root;
+
+      svn_pool_clear(iterpool);
+      inner_iterpool = svn_pool_create(iterpool);
+
+      SVN_ERR(svn_fs_revision_root(&mergeinfo_rev_root, fs,
+                                   *rev, iterpool));
+
+       for (hi2 = apr_hash_first(iterpool, paths);
+            hi2;
+            hi2 = apr_hash_next(hi2))
+         {
+            const char *path = svn__apr_hash_index_key(hi2);
+ 
+            svn_pool_clear(inner_iterpool);
+            SVN_ERR(svn_fs_check_path(&kind, mergeinfo_rev_root,
+                                      path, inner_iterpool));
+            if (kind == svn_node_none)
+              {
+                apr_hash_set(paths, path, APR_HASH_KEY_STRING, NULL);
+              }
+            else
+              {
+                const char *mergeinfo_str = apr_psprintf(inner_iterpool,
+                                                         "%s:%d",
+                                                         path, *rev);
+                svn_mergeinfo_t good_mergeinfo_fragment;
+
+                SVN_ERR(svn_mergeinfo_parse(&good_mergeinfo_fragment,
+                                            mergeinfo_str, scratch_pool));
+                SVN_ERR(svn_mergeinfo_merge(filtered_mergeinfo,
+                                            good_mergeinfo_fragment,
+                                            scratch_pool));
+              }
+         }
+      svn_pool_destroy(inner_iterpool);
+    }
+
+  svn_pool_destroy(iterpool);
+  *validated_mergeinfo = svn_mergeinfo_dup(filtered_mergeinfo, result_pool);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *

Modified: subversion/trunk/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.h Wed Nov 17 01:08:28 2010
@@ -331,6 +331,7 @@ typedef struct root_vtable_t
                                 svn_fs_root_t *root,
                                 const apr_array_header_t *paths,
                                 svn_mergeinfo_inheritance_t inherit,
+                                svn_boolean_t validate_inherited_mergeinfo,
                                 svn_boolean_t include_descendants,
                                 apr_pool_t *pool);
 } root_vtable_t;

Modified: subversion/trunk/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/tree.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/tree.c Wed Nov 17 01:08:28 2010
@@ -5278,12 +5278,14 @@ append_to_merged_froms(svn_mergeinfo_t *
 
 /* Calculate the mergeinfo for PATH under revision ROOT using
    inheritance type INHERIT.  Set *MERGEINFO to the mergeinfo, or to
-   NULL if there is none.  Results are allocated in POOL; TRAIL->pool
+   NULL if there is none.  If *MERGEINFO is inherited set *INHERITED
+   to true, false otherwise.  Results are allocated in POOL; TRAIL->POOL
    is used for temporary allocations.  */
 
 struct get_mergeinfo_for_path_baton
 {
   svn_mergeinfo_t *mergeinfo;
+  svn_boolean_t *inherited;
   svn_fs_root_t *root;
   const char *path;
   svn_mergeinfo_inheritance_t inherit;
@@ -5301,6 +5303,7 @@ txn_body_get_mergeinfo_for_path(void *ba
   dag_node_t *node = NULL;
 
   *(args->mergeinfo) = NULL;
+  *(args->inherited) = FALSE;
 
   SVN_ERR(open_path(&parent_path, args->root, args->path, 0,
                     NULL, trail, trail->pool));
@@ -5382,6 +5385,7 @@ txn_body_get_mergeinfo_for_path(void *ba
                                                          nearest_ancestor,
                                                          trail->pool),
                                      args->pool));
+      *(args->inherited) = TRUE;
     }
   return SVN_NO_ERROR;
 }
@@ -5413,14 +5417,17 @@ txn_body_get_node_mergeinfo_stats(void *
 }
 
 
-/* Get the mergeinfo for a set of paths, returned in
-   *MERGEINFO_CATALOG.  Returned values are allocated in POOL, while
-   temporary values are allocated in a sub-pool. */
+/* Get the mergeinfo for a set of paths, returned in *MERGEINFO_CATALOG.
+   If the mergeinfo for any path is inherited and VALIDATE_INHERITED_MERGEINFO
+   is true, then the mergeinfo for that path in *MERGEINFO_CATALOG will only
+   contain path-revs that actually exist in repository.  Returned values are
+   allocated in POOL, while temporary values are allocated in a sub-pool. */
 static svn_error_t *
 get_mergeinfos_for_paths(svn_fs_root_t *root,
                          svn_mergeinfo_catalog_t *mergeinfo_catalog,
                          const apr_array_header_t *paths,
                          svn_mergeinfo_inheritance_t inherit,
+                         svn_boolean_t validate_inherited_mergeinfo,
                          svn_boolean_t include_descendants,
                          apr_pool_t *pool)
 {
@@ -5431,6 +5438,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *
   for (i = 0; i < paths->nelts; i++)
     {
       svn_mergeinfo_t path_mergeinfo;
+      svn_boolean_t inherited;
       struct get_mergeinfo_for_path_baton gmfp_args;
       const char *path = APR_ARRAY_IDX(paths, i, const char *);
 
@@ -5440,6 +5448,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *
 
       /* Get the mergeinfo for PATH itself. */
       gmfp_args.mergeinfo = &path_mergeinfo;
+      gmfp_args.inherited = &inherited;
       gmfp_args.root = root;
       gmfp_args.path = path;
       gmfp_args.inherit = inherit;
@@ -5448,9 +5457,16 @@ get_mergeinfos_for_paths(svn_fs_root_t *
                                      txn_body_get_mergeinfo_for_path,
                                      &gmfp_args, FALSE, iterpool));
       if (path_mergeinfo)
-        apr_hash_set(result_catalog, apr_pstrdup(pool, path),
-                     APR_HASH_KEY_STRING,
-                     path_mergeinfo);
+        {
+          if (inherited && validate_inherited_mergeinfo)
+            SVN_ERR(svn_fs_validate_mergeinfo(&path_mergeinfo,
+                                              path_mergeinfo, root->fs,
+                                              pool, iterpool));
+
+          apr_hash_set(result_catalog, apr_pstrdup(pool, path),
+                       APR_HASH_KEY_STRING,
+                       path_mergeinfo);
+        }
 
       /* If we're including descendants, do so. */
       if (include_descendants)
@@ -5493,6 +5509,7 @@ base_get_mergeinfo(svn_mergeinfo_catalog
                    svn_fs_root_t *root,
                    const apr_array_header_t *paths,
                    svn_mergeinfo_inheritance_t inherit,
+                   svn_boolean_t validate_inherited_mergeinfo,
                    svn_boolean_t include_descendants,
                    apr_pool_t *pool)
 {
@@ -5506,8 +5523,8 @@ base_get_mergeinfo(svn_mergeinfo_catalog
 
   /* Retrieve a path -> mergeinfo mapping. */
   return get_mergeinfos_for_paths(root, catalog, paths,
-                                  inherit, include_descendants,
-                                  pool);
+                                  inherit, validate_inherited_mergeinfo,
+                                  include_descendants, pool);
 }
 
 

Modified: subversion/trunk/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/tree.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/tree.c Wed Nov 17 01:08:28 2010
@@ -3489,14 +3489,17 @@ append_to_merged_froms(svn_mergeinfo_t *
 
 /* Calculates the mergeinfo for PATH under REV_ROOT using inheritance
    type INHERIT.  Returns it in *MERGEINFO, or NULL if there is none.
-   The result is allocated in RESULT_POOL; POOL is used for temporary
-   allocations.
+   If *MERGEINFO is inherited and VALIDATE_INHERITED_MERGEINFO is true,
+   then *MERGEINFO will only contain path-revs that actually exist in
+   repository.  The result is allocated in RESULT_POOL; POOL is used for
+   temporary allocations.
  */
 static svn_error_t *
 get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
                        svn_fs_root_t *rev_root,
                        const char *path,
                        svn_mergeinfo_inheritance_t inherit,
+                       svn_boolean_t validate_inherited_mergeinfo,
                        apr_pool_t *pool,
                        apr_pool_t *result_pool)
 {
@@ -3546,7 +3549,6 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
           return SVN_NO_ERROR;
         }
     }
-  svn_pool_destroy(iterpool);
 
   SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, nearest_ancestor->node, pool));
   mergeinfo_string = apr_hash_get(proplist, SVN_PROP_MERGEINFO,
@@ -3560,6 +3562,7 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
   if (nearest_ancestor == parent_path)
     {
       /* We can return this directly. */
+      svn_pool_destroy(iterpool);
       return svn_mergeinfo_parse(mergeinfo,
                                  mergeinfo_string->data,
                                  result_pool);
@@ -3581,12 +3584,18 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
                                         NULL, SVN_INVALID_REVNUM,
                                         SVN_INVALID_REVNUM, pool));
 
-      return append_to_merged_froms(mergeinfo,
-                                    temp_mergeinfo,
-                                    parent_path_relpath(parent_path,
-                                                        nearest_ancestor,
-                                                        pool),
-                                    result_pool);
+      SVN_ERR(append_to_merged_froms(mergeinfo,
+                                     temp_mergeinfo,
+                                     parent_path_relpath(parent_path,
+                                                         nearest_ancestor,
+                                                         pool),
+                                     result_pool));
+
+      if (validate_inherited_mergeinfo)
+        SVN_ERR(svn_fs_validate_mergeinfo(mergeinfo, *mergeinfo,
+                                         rev_root->fs, pool, iterpool));
+      svn_pool_destroy(iterpool);
+      return SVN_NO_ERROR;
     }
 }
 
@@ -3619,13 +3628,17 @@ add_descendant_mergeinfo(svn_mergeinfo_c
 
 
 /* Get the mergeinfo for a set of paths, returned in
-   *MERGEINFO_CATALOG.  Returned values are allocated in POOL, while
-   temporary values are allocated in a sub-pool. */
+   *MERGEINFO_CATALOG.  If the mergeinfo for any path is inherited
+   and VALIDATE_INHERITED_MERGEINFO is true, then the mergeinfo for
+   that path in *MERGEINFO_CATALOG will only contain path-revs that
+   actually exist in repository.  Returned values are allocated in
+   POOL, while temporary values are allocated in a sub-pool. */
 static svn_error_t *
 get_mergeinfos_for_paths(svn_fs_root_t *root,
                          svn_mergeinfo_catalog_t *mergeinfo_catalog,
                          const apr_array_header_t *paths,
                          svn_mergeinfo_inheritance_t inherit,
+                         svn_boolean_t validate_inherited_mergeinfo,
                          svn_boolean_t include_descendants,
                          apr_pool_t *pool)
 {
@@ -3641,7 +3654,8 @@ get_mergeinfos_for_paths(svn_fs_root_t *
       svn_pool_clear(iterpool);
 
       SVN_ERR(get_mergeinfo_for_path(&path_mergeinfo, root, path,
-                                     inherit, iterpool, pool));
+                                     inherit, validate_inherited_mergeinfo,
+                                     iterpool, pool));
       if (path_mergeinfo)
         apr_hash_set(result_catalog, path, APR_HASH_KEY_STRING,
                      path_mergeinfo);
@@ -3662,6 +3676,7 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t
                  svn_fs_root_t *root,
                  const apr_array_header_t *paths,
                  svn_mergeinfo_inheritance_t inherit,
+                 svn_boolean_t validate_inherited_mergeinfo,
                  svn_boolean_t include_descendants,
                  apr_pool_t *pool)
 {
@@ -3681,8 +3696,8 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t
 
   /* Retrieve a path -> mergeinfo hash mapping. */
   return get_mergeinfos_for_paths(root, catalog, paths,
-                                  inherit, include_descendants,
-                                  pool);
+                                  inherit, validate_inherited_mergeinfo,
+                                  include_descendants, pool);
 }
 
 /* The vtable associated with root objects. */

Modified: subversion/trunk/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/deprecated.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_ra/deprecated.c Wed Nov 17 01:08:28 2010
@@ -418,3 +418,18 @@ svn_error_t *svn_ra_do_status(svn_ra_ses
                                     status_editor, status_baton, pool);
 }
 
+svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session,
+                                  svn_mergeinfo_catalog_t *catalog,
+                                  const apr_array_header_t *paths,
+                                  svn_revnum_t revision,
+                                  svn_mergeinfo_inheritance_t inherit,
+                                  svn_boolean_t include_descendants,
+                                  apr_pool_t *pool)
+{
+  svn_boolean_t validate_inherited_mergeinfo = FALSE;
+
+  return svn_error_return(svn_ra_get_mergeinfo2(session, catalog, paths,
+                          revision, inherit, &validate_inherited_mergeinfo,
+                          include_descendants, pool));
+}
+

Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.c Wed Nov 17 01:08:28 2010
@@ -753,13 +753,14 @@ svn_error_t *svn_ra_get_dir2(svn_ra_sess
                                   path, revision, dirent_fields, pool);
 }
 
-svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session,
-                                  svn_mergeinfo_catalog_t *catalog,
-                                  const apr_array_header_t *paths,
-                                  svn_revnum_t revision,
-                                  svn_mergeinfo_inheritance_t inherit,
-                                  svn_boolean_t include_descendants,
-                                  apr_pool_t *pool)
+svn_error_t *svn_ra_get_mergeinfo2(svn_ra_session_t *session,
+                                   svn_mergeinfo_catalog_t *catalog,
+                                   const apr_array_header_t *paths,
+                                   svn_revnum_t revision,
+                                   svn_mergeinfo_inheritance_t inherit,
+                                   svn_boolean_t *validate_inherited_mergeinfo,
+                                   svn_boolean_t include_descendants,
+                                   apr_pool_t *pool)
 {
   svn_error_t *err;
   int i;
@@ -781,6 +782,7 @@ svn_error_t *svn_ra_get_mergeinfo(svn_ra
 
   return session->vtable->get_mergeinfo(session, catalog, paths,
                                         revision, inherit,
+                                        validate_inherited_mergeinfo,
                                         include_descendants, pool);
 }
 

Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.h Wed Nov 17 01:08:28 2010
@@ -119,6 +119,7 @@ typedef struct svn_ra__vtable_t {
                                 const apr_array_header_t *paths,
                                 svn_revnum_t revision,
                                 svn_mergeinfo_inheritance_t inherit,
+                                svn_boolean_t *validate_inherited_mergeinfo,
                                 svn_boolean_t include_merged_revisions,
                                 apr_pool_t *pool);
   svn_error_t *(*do_update)(svn_ra_session_t *session,

Modified: subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c Wed Nov 17 01:08:28 2010
@@ -693,6 +693,7 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
                             const apr_array_header_t *paths,
                             svn_revnum_t revision,
                             svn_mergeinfo_inheritance_t inherit,
+                            svn_boolean_t *validate_inherited_mergeinfo,
                             svn_boolean_t include_descendants,
                             apr_pool_t *pool)
 {
@@ -709,9 +710,11 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
         svn_dirent_join(sess->fs_path->data, relative_path, pool);
     }
 
-  SVN_ERR(svn_repos_fs_get_mergeinfo(&tmp_catalog, sess->repos, abs_paths,
-                                     revision, inherit, include_descendants,
-                                     NULL, NULL, pool));
+  SVN_ERR(svn_repos_fs_get_mergeinfo2(&tmp_catalog, sess->repos, abs_paths,
+                                      revision, inherit,
+                                      *validate_inherited_mergeinfo,
+                                      include_descendants,
+                                      NULL, NULL, pool));
   if (apr_hash_count(tmp_catalog) > 0)
     SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(catalog,
                                                       tmp_catalog,

Modified: subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c Wed Nov 17 01:08:28 2010
@@ -51,6 +51,7 @@ struct mergeinfo_baton
   svn_stringbuf_t *curr_path;
   svn_stringbuf_t *curr_info;
   svn_mergeinfo_catalog_t catalog;
+  svn_boolean_t validated_inherited_mergeinfo;
   svn_error_t *err;
 };
 
@@ -62,6 +63,8 @@ static const svn_ra_neon__xml_elm_t merg
       SVN_RA_NEON__XML_CDATA },
     { SVN_XML_NAMESPACE, SVN_DAV__MERGEINFO_INFO, ELEM_mergeinfo_info,
       SVN_RA_NEON__XML_CDATA },
+    { SVN_XML_NAMESPACE, SVN_DAV__VALIDATE_INHERITED,
+      ELEM_validate_inherited_mergeinfo, SVN_RA_NEON__XML_CDATA },
     { NULL }
   };
 
@@ -93,6 +96,10 @@ start_element(int *elem, void *baton, in
       svn_stringbuf_setempty(mb->curr_info);
       svn_stringbuf_setempty(mb->curr_path);
     }
+  else if (elm->id == ELEM_validate_inherited_mergeinfo)
+    {
+      mb->validated_inherited_mergeinfo = TRUE;
+    }
 
   SVN_ERR(mb->err);
 
@@ -163,6 +170,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
                            const apr_array_header_t *paths,
                            svn_revnum_t revision,
                            svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t *validate_inherited_mergeinfo,
                            svn_boolean_t include_descendants,
                            apr_pool_t *pool)
 {
@@ -194,6 +202,14 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
                                         "</S:inherit>",
                                         svn_inheritance_to_word(inherit)));
 
+  if (*validate_inherited_mergeinfo)
+    {
+      /* Send it only if true; server will default to "no". */
+      svn_stringbuf_appendcstr(request_body,
+                               "<S:" SVN_DAV__VALIDATE_INHERITED ">yes"
+                               "</S:" SVN_DAV__VALIDATE_INHERITED ">");
+    }
+
   if (include_descendants)
     {
       /* Send it only if true; server will default to "no". */
@@ -224,6 +240,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
   mb.curr_path = svn_stringbuf_create("", pool);
   mb.curr_info = svn_stringbuf_create("", pool);
   mb.catalog = apr_hash_make(pool);
+  mb.validated_inherited_mergeinfo = FALSE;
   mb.err = SVN_NO_ERROR;
 
   /* ras's URL may not exist in HEAD, and thus it's not safe to send
@@ -253,5 +270,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
   if (mb.err == SVN_NO_ERROR && apr_hash_count(mb.catalog))
     *catalog = mb.catalog;
 
+  *validate_inherited_mergeinfo = mb.validated_inherited_mergeinfo;
+
   return mb.err;
 }

Modified: subversion/trunk/subversion/libsvn_ra_neon/options.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_neon/options.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_neon/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_neon/options.c Wed Nov 17 01:08:28 2010
@@ -395,12 +395,15 @@ svn_ra_neon__has_capability(svn_ra_sessi
              support mergeinfo. */
           svn_mergeinfo_catalog_t ignored;
           svn_error_t *err;
+          svn_boolean_t validate_inherited_mergeinfo = FALSE;
           apr_array_header_t *paths = apr_array_make(pool, 1,
                                                      sizeof(char *));
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_neon__get_mergeinfo(session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE,
+                                           &validate_inherited_mergeinfo,
+                                           FALSE, pool);
 
           if (err)
             {

Modified: subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h Wed Nov 17 01:08:28 2010
@@ -299,13 +299,15 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
 svn_error_t * svn_ra_neon__abort_commit(void *session_baton,
                                         void *edit_baton);
 
-svn_error_t * svn_ra_neon__get_mergeinfo(svn_ra_session_t *session,
-                                         apr_hash_t **mergeinfo,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool);
+svn_error_t * svn_ra_neon__get_mergeinfo(
+  svn_ra_session_t *session,
+  apr_hash_t **mergeinfo,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool);
 
 svn_error_t * svn_ra_neon__do_update(svn_ra_session_t *session,
                                      const svn_ra_reporter3_t **reporter,
@@ -859,7 +861,8 @@ enum {
   ELEM_mergeinfo_info,
   ELEM_has_children,
   ELEM_merged_revision,
-  ELEM_deleted_rev_report
+  ELEM_deleted_rev_report,
+  ELEM_validate_inherited_mergeinfo
 };
 
 /* ### docco */

Modified: subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c Wed Nov 17 01:08:28 2010
@@ -45,7 +45,8 @@ typedef enum {
   MERGEINFO_REPORT,
   MERGEINFO_ITEM,
   MERGEINFO_PATH,
-  MERGEINFO_INFO
+  MERGEINFO_INFO,
+  MERGEINFO_VALIDATED
 } mergeinfo_state_e;
 
 /* Baton for accumulating mergeinfo.  RESULT_CATALOG stores the final
@@ -62,6 +63,8 @@ typedef struct {
   const apr_array_header_t *paths;
   svn_revnum_t revision;
   svn_mergeinfo_inheritance_t inherit;
+  svn_boolean_t validate_inherited_mergeinfo;
+  svn_boolean_t validated_inherited_mergeinfo;
   svn_boolean_t include_descendants;
 } mergeinfo_context_t;
 
@@ -80,6 +83,11 @@ start_element(svn_ra_serf__xml_parser_t 
       svn_ra_serf__xml_push_state(parser, MERGEINFO_REPORT);
     }
   else if (state == MERGEINFO_REPORT &&
+           strcmp(name.name, SVN_DAV__VALIDATE_INHERITED) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, MERGEINFO_VALIDATED);
+    }
+  else if (state == MERGEINFO_REPORT &&
            strcmp(name.name, SVN_DAV__MERGEINFO_ITEM) == 0)
     {
       svn_ra_serf__xml_push_state(parser, MERGEINFO_ITEM);
@@ -169,6 +177,11 @@ cdata_handler(svn_ra_serf__xml_parser_t 
         svn_stringbuf_appendbytes(mergeinfo_ctx->curr_info, data, len);
       break;
 
+    case MERGEINFO_VALIDATED:
+      if (strncmp(data, "yes", 3) == 0)
+        mergeinfo_ctx->validated_inherited_mergeinfo = TRUE;
+      break;
+
     default:
       break;
     }
@@ -206,6 +219,13 @@ create_mergeinfo_body(serf_bucket_t **bk
                                    "yes", alloc);
     }
 
+  if (mergeinfo_ctx->validate_inherited_mergeinfo)
+    {
+      svn_ra_serf__add_tag_buckets(body_bkt, "S:"
+                                   SVN_DAV__VALIDATE_INHERITED,
+                                   "yes", alloc);
+    }
+
   if (mergeinfo_ctx->paths)
     {
       int i;
@@ -235,6 +255,7 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
                            const apr_array_header_t *paths,
                            svn_revnum_t revision,
                            svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t *validate_inherited_mergeinfo,
                            svn_boolean_t include_descendants,
                            apr_pool_t *pool)
 {
@@ -264,6 +285,8 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
   mergeinfo_ctx->paths = paths;
   mergeinfo_ctx->revision = revision;
   mergeinfo_ctx->inherit = inherit;
+  mergeinfo_ctx->validate_inherited_mergeinfo = *validate_inherited_mergeinfo;
+  mergeinfo_ctx->validated_inherited_mergeinfo = FALSE;
   mergeinfo_ctx->include_descendants = include_descendants;
 
   handler = apr_pcalloc(pool, sizeof(*handler));
@@ -303,6 +326,9 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
 
   SVN_ERR(err);
 
+  *validate_inherited_mergeinfo =
+    mergeinfo_ctx->validated_inherited_mergeinfo;
+
   if (mergeinfo_ctx->done && apr_hash_count(mergeinfo_ctx->result_catalog))
     *catalog = mergeinfo_ctx->result_catalog;
 

Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Wed Nov 17 01:08:28 2010
@@ -566,12 +566,15 @@ svn_ra_serf__has_capability(svn_ra_sessi
              support mergeinfo. */
           svn_mergeinfo_catalog_t ignored;
           svn_error_t *err;
+          svn_boolean_t validate_inherited_mergeinfo = FALSE;
           apr_array_header_t *paths = apr_array_make(pool, 1,
                                                      sizeof(char *));
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_serf__get_mergeinfo(ra_session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE,
+                                           &validate_inherited_mergeinfo,
+                                           FALSE, pool);
 
           if (err)
             {

Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Wed Nov 17 01:08:28 2010
@@ -1379,13 +1379,15 @@ svn_ra_serf__get_locks(svn_ra_session_t 
                        svn_depth_t depth,
                        apr_pool_t *pool);
 
-svn_error_t * svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
-                                         apr_hash_t **mergeinfo,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool);
+svn_error_t * svn_ra_serf__get_mergeinfo(
+  svn_ra_session_t *ra_session,
+  apr_hash_t **mergeinfo,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool);
 
 /* Exchange capabilities with the server, by sending an OPTIONS
  * request announcing the client's capabilities, and by filling

Modified: subversion/trunk/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/client.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/client.c Wed Nov 17 01:08:28 2010
@@ -1153,15 +1153,34 @@ static svn_error_t *ra_svn_get_dir(svn_r
   return SVN_NO_ERROR;
 }
 
+/* Converts a apr_uint64_t with values TRUE, FALSE or
+   SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
+   to a svn_tristate_t */
+static svn_tristate_t
+optbool_to_tristate(apr_uint64_t v)
+{
+  switch (v)
+  {
+    case TRUE:
+      return svn_tristate_true;
+    case FALSE:
+      return svn_tristate_false;
+    default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
+      return svn_tristate_unknown;
+  }
+}
+
 /* If REVISION is SVN_INVALID_REVNUM, no value is sent to the
    server, which defaults to youngest. */
-static svn_error_t *ra_svn_get_mergeinfo(svn_ra_session_t *session,
-                                         svn_mergeinfo_catalog_t *catalog,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool)
+static svn_error_t *ra_svn_get_mergeinfo(
+  svn_ra_session_t *session,
+  svn_mergeinfo_catalog_t *catalog,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool)
 {
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
@@ -1169,6 +1188,7 @@ static svn_error_t *ra_svn_get_mergeinfo
   apr_array_header_t *mergeinfo_tuple;
   svn_ra_svn_item_t *elt;
   const char *path;
+  apr_uint64_t validated_inherited_mergeinfo;
 
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "get-mergeinfo"));
   for (i = 0; i < paths->nelts; i++)
@@ -1176,12 +1196,17 @@ static svn_error_t *ra_svn_get_mergeinfo
       path = APR_ARRAY_IDX(paths, i, const char *);
       SVN_ERR(svn_ra_svn_write_cstring(conn, pool, path));
     }
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wb)", revision,
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wbb)", revision,
                                  svn_inheritance_to_word(inherit),
-                                 include_descendants));
+                                 include_descendants,
+                                 *validate_inherited_mergeinfo));
 
   SVN_ERR(handle_auth_request(sess_baton, pool));
-  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &mergeinfo_tuple));
+  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l?B", &mergeinfo_tuple,
+                                       &validated_inherited_mergeinfo));
+
+  *validate_inherited_mergeinfo =
+    (optbool_to_tristate(validated_inherited_mergeinfo) == svn_tristate_true);
 
   *catalog = NULL;
   if (mergeinfo_tuple->nelts > 0)
@@ -1313,22 +1338,6 @@ static svn_error_t *ra_svn_diff(svn_ra_s
   return SVN_NO_ERROR;
 }
 
-/* Converts a apr_uint64_t with values TRUE, FALSE or
-   SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
-   to a svn_tristate_t */
-static svn_tristate_t
-optbool_to_tristate(apr_uint64_t v)
-{
-  switch (v)
-  {
-    case TRUE:
-      return svn_tristate_true;
-    case FALSE:
-      return svn_tristate_false;
-    default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
-      return svn_tristate_unknown;
-  }
-}
 
 static svn_error_t *ra_svn_log(svn_ra_session_t *session,
                                const apr_array_header_t *paths,

Modified: subversion/trunk/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/fs-wrap.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/trunk/subversion/libsvn_repos/fs-wrap.c Wed Nov 17 01:08:28 2010
@@ -597,15 +597,16 @@ svn_repos_fs_get_locks2(apr_hash_t **loc
 
 
 svn_error_t *
-svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo,
-                           svn_repos_t *repos,
-                           const apr_array_header_t *paths,
-                           svn_revnum_t rev,
-                           svn_mergeinfo_inheritance_t inherit,
-                           svn_boolean_t include_descendants,
-                           svn_repos_authz_func_t authz_read_func,
-                           void *authz_read_baton,
-                           apr_pool_t *pool)
+svn_repos_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *mergeinfo,
+                            svn_repos_t *repos,
+                            const apr_array_header_t *paths,
+                            svn_revnum_t rev,
+                            svn_mergeinfo_inheritance_t inherit,
+                            svn_boolean_t validate_inherited_mergeinfo,
+                            svn_boolean_t include_descendants,
+                            svn_repos_authz_func_t authz_read_func,
+                            void *authz_read_baton,
+                            apr_pool_t *pool)
 {
   /* Here we cast away 'const', but won't try to write through this pointer
    * without first allocating a new array. */
@@ -653,8 +654,9 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
      the change itself. */
   /* ### TODO(reint): ... but how about descendant merged-to paths? */
   if (readable_paths->nelts > 0)
-    SVN_ERR(svn_fs_get_mergeinfo(mergeinfo, root, readable_paths, inherit,
-                                 include_descendants, pool));
+    SVN_ERR(svn_fs_get_mergeinfo2(mergeinfo, root, readable_paths, inherit,
+                                  validate_inherited_mergeinfo,
+                                  include_descendants, pool));
   else
     *mergeinfo = apr_hash_make(pool);
 
@@ -662,6 +664,26 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo,
+                           svn_repos_t *repos,
+                           const apr_array_header_t *paths,
+                           svn_revnum_t rev,
+                           svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t include_descendants,
+                           svn_repos_authz_func_t authz_read_func,
+                           void *authz_read_baton,
+                           apr_pool_t *pool)
+{
+  return svn_error_return(svn_repos_fs_get_mergeinfo2(mergeinfo, repos,
+                                                      paths, rev, inherit,
+                                                      FALSE,
+                                                      include_descendants,
+                                                      authz_read_func,
+                                                      authz_read_baton,
+                                                      pool));
+}
+
 struct pack_notify_baton
 {
   svn_repos_notify_func_t notify_func;

Modified: subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c Wed Nov 17 01:08:28 2010
@@ -50,6 +50,7 @@ dav_svn__get_mergeinfo_report(const dav_
   dav_error *derr = NULL;
   apr_xml_elem *child;
   svn_mergeinfo_catalog_t catalog;
+  svn_boolean_t validate_inherited_mergeinfo = FALSE;
   svn_boolean_t include_descendants = FALSE;
   dav_svn__authz_read_baton arb;
   const dav_svn_repos *repos = resource->info->repos;
@@ -99,6 +100,12 @@ dav_svn__get_mergeinfo_report(const dav_
                                  resource->pool);
           (*((const char **)(apr_array_push(paths)))) = target;
         }
+      else if (strcmp(child->name, SVN_DAV__VALIDATE_INHERITED) == 0)
+        {
+          const char *word = dav_xml_get_cdata(child, resource->pool, 1);
+          if (strcmp(word, "yes") == 0)
+            validate_inherited_mergeinfo = TRUE;
+        }
       else if (strcmp(child->name, SVN_DAV__INCLUDE_DESCENDANTS) == 0)
         {
           const char *word = dav_xml_get_cdata(child, resource->pool, 1);
@@ -117,10 +124,11 @@ dav_svn__get_mergeinfo_report(const dav_
   /* Build mergeinfo brigade */
   bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
 
-  serr = svn_repos_fs_get_mergeinfo(&catalog, repos->repos, paths, rev,
-                                    inherit, include_descendants,
-                                    dav_svn__authz_read_func(&arb),
-                                    &arb, resource->pool);
+  serr = svn_repos_fs_get_mergeinfo2(&catalog, repos->repos, paths, rev,
+                                     inherit, validate_inherited_mergeinfo,
+                                     include_descendants,
+                                     dav_svn__authz_read_func(&arb),
+                                     &arb, resource->pool);
   if (serr)
     {
       derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
@@ -197,6 +205,22 @@ dav_svn__get_mergeinfo_report(const dav_
         }
     }
 
+  if (validate_inherited_mergeinfo)
+    {
+      serr = dav_svn__brigade_puts(bb, output,
+                                   "<S:" SVN_DAV__VALIDATE_INHERITED ">"
+                                   "yes"
+                                   "</S:" SVN_DAV__VALIDATE_INHERITED ">"
+                                   DEBUG_CR);
+      if (serr)
+        {
+          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                      "Error ending REPORT response.",
+                                      resource->pool);
+          goto cleanup;
+        }
+    }
+
   if ((serr = dav_svn__brigade_puts(bb, output,
                                     "</S:" SVN_DAV__MERGEINFO_REPORT ">"
                                     DEBUG_CR)))

Modified: subversion/trunk/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/serve.c?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/serve.c (original)
+++ subversion/trunk/subversion/svnserve/serve.c Wed Nov 17 01:08:28 2010
@@ -1838,11 +1838,14 @@ static svn_error_t *get_mergeinfo(svn_ra
   apr_hash_index_t *hi;
   const char *inherit_word;
   svn_mergeinfo_inheritance_t inherit;
+  svn_boolean_t validate_inherited_mergeinfo;
   svn_boolean_t include_descendants;
   apr_pool_t *iterpool;
 
-  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)wb", &paths, &rev,
-                                 &inherit_word, &include_descendants));
+  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)wb?b", &paths, &rev,
+                                 &inherit_word,
+                                 &include_descendants,
+                                 &validate_inherited_mergeinfo));
   inherit = svn_inheritance_from_word(inherit_word);
 
   /* Canonicalize the paths which mergeinfo has been requested for. */
@@ -1868,12 +1871,13 @@ static svn_error_t *get_mergeinfo(svn_ra
                                              pool)));
 
   SVN_ERR(trivial_auth_request(conn, pool, b));
-  SVN_CMD_ERR(svn_repos_fs_get_mergeinfo(&mergeinfo, b->repos,
-                                         canonical_paths, rev,
-                                         inherit,
-                                         include_descendants,
-                                         authz_check_access_cb_func(b), b,
-                                         pool));
+  SVN_CMD_ERR(svn_repos_fs_get_mergeinfo2(&mergeinfo, b->repos,
+                                          canonical_paths, rev,
+                                          inherit,
+                                          validate_inherited_mergeinfo,
+                                          include_descendants,
+                                          authz_check_access_cb_func(b), b,
+                                          pool));
   SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(&mergeinfo, mergeinfo,
                                                     b->fs_path->data, pool));
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "success"));
@@ -1891,7 +1895,8 @@ static svn_error_t *get_mergeinfo(svn_ra
                                      mergeinfo_string));
     }
   svn_pool_destroy(iterpool);
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)b)",
+    validate_inherited_mergeinfo));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py Wed Nov 17 01:08:28 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/trunk/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=1035894&r1=1035893&r2=1035894&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Wed Nov 17 01:08:28 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',
@@ -12804,6 +12804,13 @@ def merge_target_and_subtrees_need_nonin
     None, expected_merge_output([[8]], ['U    ' + nu_COPY_path    + '\n',
                                         ' G   ' + nu_COPY_path    + '\n']),
     [], 'merge', '-c8', sbox.repo_url + '/A/D/G/nu', nu_COPY_path)
+  # Replicate pre 1.7 merge behavior where self-referential mergeinfo
+  # could be inherited, this keeps the original intent of this test intact,
+  # see http://subversion.tigris.org/issues/show_bug.cgi?id=3669#desc8
+  svntest.actions.run_and_verify_svn(None, None, [], 'ps',
+                                     SVN_PROP_MERGEINFO, '/A/D/G/nu:2-8',
+                                     nu_COPY_path)
+  
   svntest.actions.run_and_verify_svn(
     None, expected_merge_output([[-6]], ['G    ' + omega_COPY_path    + '\n',
                                          ' G   ' + omega_COPY_path    + '\n']),
@@ -16157,10 +16164,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 +16417,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__':



Re: svn commit: r1035894 - in /subversion/trunk: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_ra/ subversion/libsvn_ra_local/ subver...

Posted by Julian Foad <ju...@wandisco.com>.
Hi Paul.

On Wed, 2010-11-17, pburba@apache.org wrote:
> Log:
> Reintegrate the issue-3668-3669 branch.

If you could insert a summary of this change here in the log message,
that would be helpful.  I see it's ... rather large.

> Modified:
>     subversion/trunk/   (props changed)
>     subversion/trunk/subversion/include/private/svn_dav_protocol.h
>     subversion/trunk/subversion/include/svn_fs.h
>     subversion/trunk/subversion/include/svn_ra.h
>     subversion/trunk/subversion/include/svn_repos.h
>     subversion/trunk/subversion/libsvn_client/copy.c
>     subversion/trunk/subversion/libsvn_client/merge.c
>     subversion/trunk/subversion/libsvn_client/mergeinfo.c
>     subversion/trunk/subversion/libsvn_client/mergeinfo.h
>     subversion/trunk/subversion/libsvn_fs/fs-loader.c
>     subversion/trunk/subversion/libsvn_fs/fs-loader.h
>     subversion/trunk/subversion/libsvn_fs_base/tree.c
>     subversion/trunk/subversion/libsvn_fs_fs/tree.c
>     subversion/trunk/subversion/libsvn_ra/deprecated.c
>     subversion/trunk/subversion/libsvn_ra/ra_loader.c
>     subversion/trunk/subversion/libsvn_ra/ra_loader.h
>     subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
>     subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c
>     subversion/trunk/subversion/libsvn_ra_neon/options.c
>     subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h
>     subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c
>     subversion/trunk/subversion/libsvn_ra_serf/options.c
>     subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
>     subversion/trunk/subversion/libsvn_ra_svn/client.c
>     subversion/trunk/subversion/libsvn_repos/fs-wrap.c
>     subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
>     subversion/trunk/subversion/svnserve/serve.c
>     subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
>     subversion/trunk/subversion/tests/cmdline/merge_tests.py




Re: svn commit: r1035894 - undefined reference to 'svn_fs_validate_mergeinfo'

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Julian Foad wrote on Wed, Nov 17, 2010 at 10:18:05 +0000:
> Since r1035894 I'm getting a link error on Linux (and so is Noorul):
> 
> cd subversion/libsvn_fs_fs && /usr/share/apr-1.0/build/libtool --tag=CC
> --silent --mode=link gcc  -W[...] -D[...] -g -pthread
> -rpath /home/julianfoad/local/subversion-d/lib -Wl,--no-undefined -o
> libsvn_fs_fs-1.la  caching.lo dag.lo fs.lo fs_fs.lo id.lo key-gen.lo
> lock.lo rep-cache.lo
> tree.lo ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la -laprutil-1 -lapr-1 ../../subversion/libsvn_fs_util/libsvn_fs_util-1.la
> .libs/tree.o: In function `get_mergeinfo_for_path':
> /home/julianfoad/src/subversion-d/subversion/libsvn_fs_fs/tree.c:3595:
> undefined reference to `svn_fs_validate_mergeinfo'
> 
> I have deleted my ~/local/subversion-d directory, so it doesn't exist at
> this stage, and then I have run autogen.sh and configure.
> 
> It appears that the new function 'svn_fs_validate_mergeinfo' is the only
> function outside libsvn_fs_fs and libsvn_fs_util that is called directly
> from within.  I don't see why that shouldn't be OK, but it is
> suspicious.
> 
> I wonder if the compiler option '-Wl,--no-undefined' is now wrong for
> this lib.  How is that option controlled?  Globally, by the configure
> flag '--enable-disallowing-of-undefined-references' (ugh), but how per
> lib?
> 

build.conf contains "undefined-lib-symbols = yes" for libsvn_test.

Though in general, seems that disallowing undefined references is
preferable (when possible).

> Or should this function be moved to libsvn_fs_util/util.c, with merely a
> public wrapper placed in libsvn_fs/loader.c if required?
> 

IIRC, libsvn_fs depends on libsvn_fs_{fs,base} depend on libsvn_fs_util.

So if code in fsfs or bdb wants to call svn_fs_validate_mergeinfo(),
then the code they call should live in libsvn_fs_util.

(This probably means "Yes".)

Daniel

> - Julian
> 
> 
> On Wed, 2010-11-17, pburba@apache.org wrote:
> > Log:
> > Reintegrate the issue-3668-3669 branch.
> 
> 

Re: svn commit: r1035894 - undefined reference to 'svn_fs_validate_mergeinfo'

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Julian Foad wrote on Wed, Nov 17, 2010 at 10:18:05 +0000:
> Since r1035894 I'm getting a link error on Linux (and so is Noorul):
> 
> cd subversion/libsvn_fs_fs && /usr/share/apr-1.0/build/libtool --tag=CC
> --silent --mode=link gcc  -W[...] -D[...] -g -pthread
> -rpath /home/julianfoad/local/subversion-d/lib -Wl,--no-undefined -o
> libsvn_fs_fs-1.la  caching.lo dag.lo fs.lo fs_fs.lo id.lo key-gen.lo
> lock.lo rep-cache.lo
> tree.lo ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la -laprutil-1 -lapr-1 ../../subversion/libsvn_fs_util/libsvn_fs_util-1.la
> .libs/tree.o: In function `get_mergeinfo_for_path':
> /home/julianfoad/src/subversion-d/subversion/libsvn_fs_fs/tree.c:3595:
> undefined reference to `svn_fs_validate_mergeinfo'
> 
> I have deleted my ~/local/subversion-d directory, so it doesn't exist at
> this stage, and then I have run autogen.sh and configure.
> 
> It appears that the new function 'svn_fs_validate_mergeinfo' is the only
> function outside libsvn_fs_fs and libsvn_fs_util that is called directly
> from within.  I don't see why that shouldn't be OK, but it is
> suspicious.
> 
> I wonder if the compiler option '-Wl,--no-undefined' is now wrong for
> this lib.  How is that option controlled?  Globally, by the configure
> flag '--enable-disallowing-of-undefined-references' (ugh), but how per
> lib?
> 

build.conf contains "undefined-lib-symbols = yes" for libsvn_test.

Though in general, seems that disallowing undefined references is
preferable (when possible).

> Or should this function be moved to libsvn_fs_util/util.c, with merely a
> public wrapper placed in libsvn_fs/loader.c if required?
> 

IIRC, libsvn_fs depends on libsvn_fs_{fs,base} depend on libsvn_fs_util.

So if code in fsfs or bdb wants to call svn_fs_validate_mergeinfo(),
then the code they call should live in libsvn_fs_util.

(This probably means "Yes".)

Daniel

> - Julian
> 
> 
> On Wed, 2010-11-17, pburba@apache.org wrote:
> > Log:
> > Reintegrate the issue-3668-3669 branch.
> 
> 

Re: svn commit: r1035894 - undefined reference to 'svn_fs_validate_mergeinfo'

Posted by Julian Foad <ju...@wandisco.com>.
Since r1035894 I'm getting a link error on Linux (and so is Noorul):

cd subversion/libsvn_fs_fs && /usr/share/apr-1.0/build/libtool --tag=CC
--silent --mode=link gcc  -W[...] -D[...] -g -pthread
-rpath /home/julianfoad/local/subversion-d/lib -Wl,--no-undefined -o
libsvn_fs_fs-1.la  caching.lo dag.lo fs.lo fs_fs.lo id.lo key-gen.lo
lock.lo rep-cache.lo
tree.lo ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la -laprutil-1 -lapr-1 ../../subversion/libsvn_fs_util/libsvn_fs_util-1.la
.libs/tree.o: In function `get_mergeinfo_for_path':
/home/julianfoad/src/subversion-d/subversion/libsvn_fs_fs/tree.c:3595:
undefined reference to `svn_fs_validate_mergeinfo'

I have deleted my ~/local/subversion-d directory, so it doesn't exist at
this stage, and then I have run autogen.sh and configure.

It appears that the new function 'svn_fs_validate_mergeinfo' is the only
function outside libsvn_fs_fs and libsvn_fs_util that is called directly
from within.  I don't see why that shouldn't be OK, but it is
suspicious.

I wonder if the compiler option '-Wl,--no-undefined' is now wrong for
this lib.  How is that option controlled?  Globally, by the configure
flag '--enable-disallowing-of-undefined-references' (ugh), but how per
lib?

Or should this function be moved to libsvn_fs_util/util.c, with merely a
public wrapper placed in libsvn_fs/loader.c if required?

- Julian


On Wed, 2010-11-17, pburba@apache.org wrote:
> Log:
> Reintegrate the issue-3668-3669 branch.



Re: svn commit: r1035894 - in /subversion/trunk: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_ra/ subversion/libsvn_ra_local/ subver...

Posted by Julian Foad <ju...@wandisco.com>.
Hi Paul.

On Wed, 2010-11-17, pburba@apache.org wrote:
> Log:
> Reintegrate the issue-3668-3669 branch.

If you could insert a summary of this change here in the log message,
that would be helpful.  I see it's ... rather large.

> Modified:
>     subversion/trunk/   (props changed)
>     subversion/trunk/subversion/include/private/svn_dav_protocol.h
>     subversion/trunk/subversion/include/svn_fs.h
>     subversion/trunk/subversion/include/svn_ra.h
>     subversion/trunk/subversion/include/svn_repos.h
>     subversion/trunk/subversion/libsvn_client/copy.c
>     subversion/trunk/subversion/libsvn_client/merge.c
>     subversion/trunk/subversion/libsvn_client/mergeinfo.c
>     subversion/trunk/subversion/libsvn_client/mergeinfo.h
>     subversion/trunk/subversion/libsvn_fs/fs-loader.c
>     subversion/trunk/subversion/libsvn_fs/fs-loader.h
>     subversion/trunk/subversion/libsvn_fs_base/tree.c
>     subversion/trunk/subversion/libsvn_fs_fs/tree.c
>     subversion/trunk/subversion/libsvn_ra/deprecated.c
>     subversion/trunk/subversion/libsvn_ra/ra_loader.c
>     subversion/trunk/subversion/libsvn_ra/ra_loader.h
>     subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
>     subversion/trunk/subversion/libsvn_ra_neon/mergeinfo.c
>     subversion/trunk/subversion/libsvn_ra_neon/options.c
>     subversion/trunk/subversion/libsvn_ra_neon/ra_neon.h
>     subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c
>     subversion/trunk/subversion/libsvn_ra_serf/options.c
>     subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
>     subversion/trunk/subversion/libsvn_ra_svn/client.c
>     subversion/trunk/subversion/libsvn_repos/fs-wrap.c
>     subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
>     subversion/trunk/subversion/svnserve/serve.c
>     subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
>     subversion/trunk/subversion/tests/cmdline/merge_tests.py



Re: svn commit: r1035894 - in /subversion/trunk: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_ra/ subversion/libsvn_ra_local/ subver...

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
pburba@apache.org wrote on Wed, Nov 17, 2010 at 01:08:29 -0000:
> +++ subversion/trunk/subversion/svnserve/serve.c Wed Nov 17 01:08:28 2010
> @@ -1838,11 +1838,14 @@ static svn_error_t *get_mergeinfo(svn_ra
> +  svn_boolean_t validate_inherited_mergeinfo;
>  
> -  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)wb", &paths, &rev,
> -                                 &inherit_word, &include_descendants));
> +  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)wb?b", &paths, &rev,
> +                                 &inherit_word,
> +                                 &include_descendants,
> +                                 &validate_inherited_mergeinfo));

Please update subversion/libsvn_ra_svn/protocol. :-)

Re: svn commit: r1035894 - undefined reference to 'svn_fs_validate_mergeinfo'

Posted by Julian Foad <ju...@wandisco.com>.
Since r1035894 I'm getting a link error on Linux (and so is Noorul):

cd subversion/libsvn_fs_fs && /usr/share/apr-1.0/build/libtool --tag=CC
--silent --mode=link gcc  -W[...] -D[...] -g -pthread
-rpath /home/julianfoad/local/subversion-d/lib -Wl,--no-undefined -o
libsvn_fs_fs-1.la  caching.lo dag.lo fs.lo fs_fs.lo id.lo key-gen.lo
lock.lo rep-cache.lo
tree.lo ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la -laprutil-1 -lapr-1 ../../subversion/libsvn_fs_util/libsvn_fs_util-1.la
.libs/tree.o: In function `get_mergeinfo_for_path':
/home/julianfoad/src/subversion-d/subversion/libsvn_fs_fs/tree.c:3595:
undefined reference to `svn_fs_validate_mergeinfo'

I have deleted my ~/local/subversion-d directory, so it doesn't exist at
this stage, and then I have run autogen.sh and configure.

It appears that the new function 'svn_fs_validate_mergeinfo' is the only
function outside libsvn_fs_fs and libsvn_fs_util that is called directly
from within.  I don't see why that shouldn't be OK, but it is
suspicious.

I wonder if the compiler option '-Wl,--no-undefined' is now wrong for
this lib.  How is that option controlled?  Globally, by the configure
flag '--enable-disallowing-of-undefined-references' (ugh), but how per
lib?

Or should this function be moved to libsvn_fs_util/util.c, with merely a
public wrapper placed in libsvn_fs/loader.c if required?

- Julian


On Wed, 2010-11-17, pburba@apache.org wrote:
> Log:
> Reintegrate the issue-3668-3669 branch.