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

svn commit: r1031336 - in /subversion/branches/issue-3668-3669/subversion: include/ include/private/ libsvn_fs/ libsvn_fs_base/ libsvn_fs_fs/ libsvn_ra/ libsvn_ra_local/ libsvn_ra_neon/ libsvn_ra_serf/ libsvn_ra_svn/ libsvn_repos/ mod_dav_svn/reports/ ...

Author: pburba
Date: Thu Nov  4 23:05:29 2010
New Revision: 1031336

URL: http://svn.apache.org/viewvc?rev=1031336&view=rev
Log:
On the issue-3668-3669 branch: Rev svn_ra_get_mergeinfo so it can optionally
validate inherited mergeinfo when talking to a 1.7+ server.

* subversion/include/svn_fs.h
  (svn_fs_get_mergeinfo2): New.
  (svn_fs_get_mergeinfo): Deprecated.
  (svn_fs_validate_mergeinfo): New.
* subversion/include/svn_ra.h
  (svn_ra_get_mergeinfo2): New.
  (svn_ra_get_mergeinfo): Deprecated.
* subversion/include/svn_repos.h
  (svn_repos_fs_get_mergeinfo2): New.
  (svn_repos_fs_get_mergeinfo): Deprecated.

  The three revved APIs above all add a new arg to optionally validate
  inherited mergeinfo; svn_fs_validate_mergeinfo ultimately does the
  heavy lifting for all three.
  
* subversion/libsvn_fs/fs-loader.c

  (svn_fs_get_mergeinfo2): New.
  
  (svn_fs_get_mergeinfo): Make into a wrapper around svn_fs_get_mergeinfo2().
  
  (svn_fs_validate_mergeinfo): New.
  
* subversion/libsvn_fs/fs-loader.h

  (fs_vtable_t): Add 'validate_inherited_mergeinfo' arg to to get_mergeinfo()
   vtable function.
  
* subversion/libsvn_fs_base/tree.c

  (get_mergeinfo_for_path_baton): Add new member to baton.
  
  (txn_body_get_mergeinfo_for_path): Set new baton member.

  (get_mergeinfos_for_paths,
   base_get_mergeinfo): Add new arg to optionally validate inherited
   mergeinfo.

* subversion/libsvn_fs_fs/tree.c

  (get_mergeinfo_for_path,
   get_mergeinfos_for_paths,
   fs_get_mergeinfo): Add new arg to optionally validate inherited
   mergeinfo.
  
* subversion/libsvn_ra/deprecated.c

  (svn_ra_get_mergeinfo): Moved here from ra_loader.c, now just a wrapper
  around svn_ra_get_mergeinfo2().
 
* subversion/libsvn_ra/ra_loader.c

  (svn_ra_get_mergeinfo2): New.
  
* subversion/libsvn_ra/ra_loader.h

  (svn_ra__vtable_t): Add 'validate_inherited_mergeinfo' argument to 
   get_mergeinfo' function.:
  
* subversion/libsvn_ra_neon/ra_neon.h (svn_ra_neon__get_mergeinfo):
* subversion/libsvn_ra_serf/ra_serf.h (svn_ra_serf__get_mergeinfo):
  Add new arg to optionally validate inherited mergeinfo.
  
* subversion/libsvn_ra_local/ra_plugin.c (svn_ra_local__get_mergeinfo):
* subversion/libsvn_ra_neon/mergeinfo.c  (svn_ra_neon__get_mergeinfo):
* subversion/libsvn_ra_svn/client.c      (ra_svn_get_mergeinfo):
  Add new arg to optionally validate inherited mergeinfo.

* subversion/libsvn_ra_serf/mergeinfo.c

  (mergeinfo_context_t): Add new member to signal if inherited mergeinfo
   validation desired.

  (create_mergeinfo_body): Send SVN_DAV__VALIDATE_INHERITED=yes if we want
   to validate inherited mergeinfo.

  (svn_ra_serf__get_mergeinfo): Add new arg to optionally validate
   inherited mergeinfo.
  
* subversion/libsvn_ra_neon/options.c (svn_ra_neon__has_capability): 
* subversion/libsvn_ra_serf/options.c (svn_ra_serf__has_capability):
  Update calls to respective DAV svn_ra_*__get_mergeinfo() implementations.

* subversion/libsvn_repos/fs-wrap.c
 
  (svn_repos_fs_get_mergeinfo2): New.
  
  (svn_repos_fs_get_mergeinfo): Make into a wrapper around
   svn_repos_fs_get_mergeinfo2().
 
* subversion/include/private/svn_dav_protocol.h

  (SVN_DAV__VALIDATE_INHERITED): New report child element.

* subversion/mod_dav_svn/reports/mergeinfo.c

  (dav_svn__get_mergeinfo_report): Handle new SVN_DAV__VALIDATE_INHERITED
   element.

* subversion/svnserve/serve.c

  (get_mergeinfo): Handle request for validated inherited mergeinfo.

Modified:
    subversion/branches/issue-3668-3669/subversion/include/private/svn_dav_protocol.h
    subversion/branches/issue-3668-3669/subversion/include/svn_fs.h
    subversion/branches/issue-3668-3669/subversion/include/svn_ra.h
    subversion/branches/issue-3668-3669/subversion/include/svn_repos.h
    subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.c
    subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.h
    subversion/branches/issue-3668-3669/subversion/libsvn_fs_base/tree.c
    subversion/branches/issue-3668-3669/subversion/libsvn_fs_fs/tree.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra/deprecated.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.h
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_local/ra_plugin.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/mergeinfo.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/options.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/ra_neon.h
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/mergeinfo.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/options.c
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/ra_serf.h
    subversion/branches/issue-3668-3669/subversion/libsvn_ra_svn/client.c
    subversion/branches/issue-3668-3669/subversion/libsvn_repos/fs-wrap.c
    subversion/branches/issue-3668-3669/subversion/mod_dav_svn/reports/mergeinfo.c
    subversion/branches/issue-3668-3669/subversion/svnserve/serve.c

Modified: subversion/branches/issue-3668-3669/subversion/include/private/svn_dav_protocol.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/include/private/svn_dav_protocol.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/include/private/svn_dav_protocol.h (original)
+++ subversion/branches/issue-3668-3669/subversion/include/private/svn_dav_protocol.h Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/include/svn_fs.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/include/svn_fs.h (original)
+++ subversion/branches/issue-3668-3669/subversion/include/svn_fs.h Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/include/svn_ra.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/include/svn_ra.h (original)
+++ subversion/branches/issue-3668-3669/subversion/include/svn_ra.h Thu Nov  4 23:05:29 2010
@@ -1011,6 +1011,11 @@ 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 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 @c SVN_PROP_MERGEINFO property explicitly set on it.  (Note
@@ -1027,7 +1032,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/branches/issue-3668-3669/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/include/svn_repos.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/include/svn_repos.h (original)
+++ subversion/branches/issue-3668-3669/subversion/include/svn_repos.h Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.c Thu Nov  4 23:05:29 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,137 @@ 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++)
+            {
+              const char *path_val;
+              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);
+                }
+
+              /* ### TODO: Do we really need to dup this path? */
+              path_val = apr_pstrdup(scratch_pool, path);
+
+              apr_hash_set(paths_for_rev, path_val, APR_HASH_KEY_STRING,
+                           path_val);
+            }
+        }
+    }
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  /* Validate the rev->source MERGEINFO equivalent hash. */
+  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, inner_iterpool));
+                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/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_fs/fs-loader.h Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_fs_base/tree.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_fs_base/tree.c Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_fs_fs/tree.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_fs_fs/tree.c Thu Nov  4 23:05:29 2010
@@ -3490,14 +3490,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)
 {
@@ -3547,7 +3550,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,
@@ -3561,6 +3563,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);
@@ -3582,12 +3585,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;
     }
 }
 
@@ -3620,13 +3629,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)
 {
@@ -3642,7 +3655,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);
@@ -3663,6 +3677,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)
 {
@@ -3682,8 +3697,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/branches/issue-3668-3669/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra/deprecated.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra/deprecated.c Thu Nov  4 23:05:29 2010
@@ -418,3 +418,15 @@ 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)
+{
+  return svn_error_return(svn_ra_get_mergeinfo2(session, catalog, paths, revision,
+                          inherit, FALSE, include_descendants, pool));
+}
+

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.c Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra/ra_loader.h Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_local/ra_plugin.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_local/ra_plugin.c Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_ra_neon/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/mergeinfo.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/mergeinfo.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/mergeinfo.c Thu Nov  4 23:05:29 2010
@@ -163,6 +163,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 +195,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". */

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/options.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/options.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/options.c Thu Nov  4 23:05:29 2010
@@ -400,7 +400,7 @@ svn_ra_neon__has_capability(svn_ra_sessi
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_neon__get_mergeinfo(session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE, FALSE, FALSE, pool);
 
           if (err)
             {

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/ra_neon.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_neon/ra_neon.h Thu Nov  4 23:05:29 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,

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/mergeinfo.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/mergeinfo.c Thu Nov  4 23:05:29 2010
@@ -62,6 +62,7 @@ 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 include_descendants;
 } mergeinfo_context_t;
 
@@ -206,6 +207,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 +243,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 +273,7 @@ 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->include_descendants = include_descendants;
 
   handler = apr_pcalloc(pool, sizeof(*handler));

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/options.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/options.c Thu Nov  4 23:05:29 2010
@@ -571,7 +571,7 @@ svn_ra_serf__has_capability(svn_ra_sessi
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_serf__get_mergeinfo(ra_session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE, FALSE, FALSE, pool);
 
           if (err)
             {

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/ra_serf.h?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_serf/ra_serf.h Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_ra_svn/client.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_ra_svn/client.c Thu Nov  4 23:05:29 2010
@@ -1160,6 +1160,7 @@ static svn_error_t *ra_svn_get_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)
 {
@@ -1176,9 +1177,10 @@ 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));

Modified: subversion/branches/issue-3668-3669/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/libsvn_repos/fs-wrap.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/issue-3668-3669/subversion/libsvn_repos/fs-wrap.c Thu Nov  4 23:05:29 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/branches/issue-3668-3669/subversion/mod_dav_svn/reports/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/mod_dav_svn/reports/mergeinfo.c (original)
+++ subversion/branches/issue-3668-3669/subversion/mod_dav_svn/reports/mergeinfo.c Thu Nov  4 23:05:29 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,

Modified: subversion/branches/issue-3668-3669/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3668-3669/subversion/svnserve/serve.c?rev=1031336&r1=1031335&r2=1031336&view=diff
==============================================================================
--- subversion/branches/issue-3668-3669/subversion/svnserve/serve.c (original)
+++ subversion/branches/issue-3668-3669/subversion/svnserve/serve.c Thu Nov  4 23:05:29 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"));