You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/11/26 19:55:54 UTC

svn commit: r1039511 [2/5] - in /subversion/branches/performance: ./ build/ subversion/bindings/swig/perl/native/ subversion/bindings/swig/ruby/test/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ sub...

Modified: subversion/branches/performance/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/mergeinfo.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/performance/subversion/libsvn_client/mergeinfo.h Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/patch.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/patch.c Fri Nov 26 18:55:51 2010
@@ -939,9 +939,9 @@ match_hunk(svn_boolean_t *matched, targe
  * Return the line at which HUNK was matched in *MATCHED_LINE.
  * If the hunk did not match at all, set *MATCHED_LINE to zero.
  * If the hunk matched multiple times, and MATCH_FIRST is TRUE,
- * return the line number at which the first match occured in *MATCHED_LINE.
+ * return the line number at which the first match occurred in *MATCHED_LINE.
  * If the hunk matched multiple times, and MATCH_FIRST is FALSE,
- * return the line number at which the last match occured in *MATCHED_LINE.
+ * return the line number at which the last match occurred in *MATCHED_LINE.
  * If IGNORE_WHITESPACE is set, ignore whitespace during the matching.
  * If MATCH_MODIFIED is TRUE, match the modified hunk text,
  * rather than the original hunk text.
@@ -1313,7 +1313,7 @@ reject_hunk(patch_target_t *target, targ
     {
       const char *prop_header;
         
-      /* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Propperty'.
+      /* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Property'.
        */
       prop_header = apr_psprintf(pool, "Property: %s\n", prop_name);
       len = strlen(prop_header);
@@ -2754,10 +2754,8 @@ svn_client_patch(const char *patch_abspa
                             _("strip count must be positive"));
 
   if (svn_path_is_url(local_abspath))
-    return svn_error_return(svn_error_createf(SVN_ERR_ILLEGAL_TARGET,
-                                              NULL,
-                                              _("'%s' is not a local path"),
-                                              local_abspath));
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"), local_abspath);
 
   baton.patch_abspath = patch_abspath;
   baton.abs_wc_path = local_abspath;

Modified: subversion/branches/performance/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/relocate.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/relocate.c Fri Nov 26 18:55:51 2010
@@ -217,6 +217,11 @@ svn_client_relocate2(const char *wcroot_
   vb.url_uuids = apr_array_make(pool, 1, sizeof(struct url_uuid_t));
   vb.pool = pool;
 
+  if (svn_path_is_url(wcroot_dir))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"),
+                             wcroot_dir);
+
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, wcroot_dir, pool));
 
   /* If we're ignoring externals, just relocate and get outta here. */

Modified: subversion/branches/performance/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/resolved.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/resolved.c Fri Nov 26 18:55:51 2010
@@ -50,9 +50,8 @@ svn_client_resolve(const char *path,
   const char *local_abspath;
 
   if (svn_path_is_url(path))
-    return svn_error_return(svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                                              _("'%s' is not a local path"),
-                                              path));
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"), path);
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 

Modified: subversion/branches/performance/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/revert.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/revert.c Fri Nov 26 18:55:51 2010
@@ -130,10 +130,8 @@ svn_client_revert2(const apr_array_heade
       const char *path = APR_ARRAY_IDX(paths, i, const char *);
 
       if (svn_path_is_url(path))
-        return svn_error_return(svn_error_createf(SVN_ERR_ILLEGAL_TARGET,
-                                                  NULL,
-                                                  _("'%s' is not a local path"),
-                                                  path));
+        return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                 _("'%s' is not a local path"), path);
     }
   
   cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,

Modified: subversion/branches/performance/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/status.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/status.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/status.c Fri Nov 26 18:55:51 2010
@@ -270,9 +270,8 @@ svn_client_status5(svn_revnum_t *result_
   struct svn_client__external_func_baton_t externals_store = { NULL };
 
   if (svn_path_is_url(path))
-    return svn_error_return(svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                                              _("'%s' is not a local path"),
-                                              path));
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"), path);
 
   if (changelists && changelists->nelts)
     SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelists, pool));

Modified: subversion/branches/performance/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/switch.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/switch.c Fri Nov 26 18:55:51 2010
@@ -329,6 +329,11 @@ svn_client_switch2(svn_revnum_t *result_
                    svn_client_ctx_t *ctx,
                    apr_pool_t *pool)
 {
+  if (svn_path_is_url(path))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"),
+                             path);
+
   return svn_client__switch_internal(result_rev, path, switch_url,
                                      peg_revision, revision, depth,
                                      depth_is_sticky, NULL, ignore_externals,

Modified: subversion/branches/performance/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/update.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/update.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/update.c Fri Nov 26 18:55:51 2010
@@ -156,6 +156,20 @@ update_internal(svn_revnum_t *result_rev
     ? svn_cstring_split(preserved_exts_str, "\n\r\t\v ", FALSE, pool)
     : NULL;
 
+  /* Let everyone know we're starting a real update (unless we're
+     asked not to). */
+  if (ctx->notify_func2 && notify_summary)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(local_abspath, svn_wc_notify_update_started,
+                               pool);
+      notify->kind = svn_node_none;
+      notify->content_state = notify->prop_state
+        = svn_wc_notify_state_inapplicable;
+      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
+      (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+    }
+
   /* Open an RA session for the URL */
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
                                                anchor_url,

Modified: subversion/branches/performance/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_delta/path_driver.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/performance/subversion/libsvn_delta/path_driver.c Fri Nov 26 18:55:51 2010
@@ -194,7 +194,9 @@ svn_delta_path_driver(const svn_delta_ed
            current one.  For the first iteration, this is just the
            empty string. ***/
       if (i > 0)
-        common = svn_relpath_get_longest_ancestor(last_path, path, iterpool);
+        common = (last_path[0] == '/')
+          ? svn_fspath__get_longest_ancestor(last_path, path, iterpool)
+          : svn_relpath_get_longest_ancestor(last_path, path, iterpool);
       common_len = strlen(common);
 
       /*** Step B - Close any directories between the last path and
@@ -215,7 +217,7 @@ svn_delta_path_driver(const svn_delta_ed
       /*** Step C - Open any directories between the common ancestor
            and the parent of the current path. ***/
       if (*path == '/')
-        svn_uri_split(&pdir, &bname, path, iterpool);
+        svn_fspath__split(&pdir, &bname, path, iterpool);
       else
         svn_relpath_split(&pdir, &bname, path, iterpool);
       if (strlen(pdir) > common_len)

Modified: subversion/branches/performance/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_diff/parse-diff.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/performance/subversion/libsvn_diff/parse-diff.c Fri Nov 26 18:55:51 2010
@@ -1040,7 +1040,7 @@ git_move_from(enum parse_state *new_stat
   return SVN_NO_ERROR;
 }
 
-/* Parse the 'rename to ' line fo a git extended unidiff. */
+/* Parse the 'rename to ' line of a git extended unidiff. */
 static svn_error_t *
 git_move_to(enum parse_state *new_state, const char *line, svn_patch_t *patch,
             apr_pool_t *result_pool, apr_pool_t *scratch_pool)

Modified: subversion/branches/performance/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs/fs-loader.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs/fs-loader.c Fri Nov 26 18:55:51 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,24 @@ 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_fs_t *fs,
+                          svn_mergeinfo_t mergeinfo,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  return svn_error_return(fs->vtable->validate_mergeinfo(validated_mergeinfo,
+                                                         fs, mergeinfo,
+                                                         result_pool,
+                                                         scratch_pool));
 }
 
 svn_error_t *

Modified: subversion/branches/performance/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs/fs-loader.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs/fs-loader.h Fri Nov 26 18:55:51 2010
@@ -197,6 +197,11 @@ typedef struct fs_vtable_t
   svn_error_t *(*bdb_set_errcall)(svn_fs_t *fs,
                                   void (*handler)(const char *errpfx,
                                                   char *msg));
+  svn_error_t *(*validate_mergeinfo)(svn_mergeinfo_t *validated_mergeinfo,
+                                     svn_fs_t *fs,
+                                     svn_mergeinfo_t mergeinfo,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool);
 } fs_vtable_t;
 
 
@@ -331,6 +336,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/performance/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/dag.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/dag.c Fri Nov 26 18:55:51 2010
@@ -481,7 +481,7 @@ make_entry(dag_node_t **child_p,
   /* Create the new node's NODE-REVISION */
   memset(&new_noderev, 0, sizeof(new_noderev));
   new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
-  new_noderev.created_path = svn_uri_join(parent_path, name, pool);
+  new_noderev.created_path = svn_fspath__join(parent_path, name, pool);
   SVN_ERR(svn_fs_base__create_node
           (&new_node_id, svn_fs_base__dag_get_fs(parent), &new_noderev,
            svn_fs_base__id_copy_id(svn_fs_base__dag_get_id(parent)),
@@ -763,7 +763,7 @@ svn_fs_base__dag_clone_child(dag_node_t 
       noderev->predecessor_id = cur_entry->id;
       if (noderev->predecessor_count != -1)
         noderev->predecessor_count++;
-      noderev->created_path = svn_uri_join(parent_path, name, pool);
+      noderev->created_path = svn_fspath__join(parent_path, name, pool);
       SVN_ERR(svn_fs_base__create_successor(&new_node_id, fs, cur_entry->id,
                                             noderev, copy_id, txn_id,
                                             trail, pool));
@@ -1422,7 +1422,7 @@ svn_fs_base__dag_copy(dag_node_t *to_nod
       noderev->predecessor_id = svn_fs_base__id_copy(src_id, pool);
       if (noderev->predecessor_count != -1)
         noderev->predecessor_count++;
-      noderev->created_path = svn_uri_join
+      noderev->created_path = svn_fspath__join
         (svn_fs_base__dag_get_created_path(to_node), entry, pool);
       SVN_ERR(svn_fs_base__create_successor(&id, fs, src_id, noderev,
                                             copy_id, txn_id, trail, pool));

Modified: subversion/branches/performance/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/fs.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/fs.c Fri Nov 26 18:55:51 2010
@@ -497,6 +497,7 @@ static fs_vtable_t fs_vtable = {
   svn_fs_base__get_lock,
   svn_fs_base__get_locks,
   base_bdb_set_errcall,
+  svn_fs_base__validate_mergeinfo,
 };
 
 /* Where the format number is stored. */

Modified: subversion/branches/performance/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/tree.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/tree.c Fri Nov 26 18:55:51 2010
@@ -486,7 +486,7 @@ parent_path_path(parent_path_t *parent_p
   if (parent_path->parent)
     path_so_far = parent_path_path(parent_path->parent, pool);
   return parent_path->entry
-    ? svn_uri_join(path_so_far, parent_path->entry, pool)
+    ? svn_fspath__join(path_so_far, parent_path->entry, pool)
          : path_so_far;
 }
 
@@ -693,7 +693,7 @@ open_path(parent_path_t **parent_path_p,
       entry = svn_fs__next_entry_name(&next, rest, pool);
 
       /* Calculate the path traversed thus far. */
-      path_so_far = svn_uri_join(path_so_far, entry, pool);
+      path_so_far = svn_fspath__join(path_so_far, entry, pool);
 
       if (*entry == '\0')
         {
@@ -1727,7 +1727,7 @@ deltify_mutable(svn_fs_t *fs,
           apr_hash_this(hi, &key, NULL, &val);
           entry = val;
           SVN_ERR(deltify_mutable(fs, root,
-                                  svn_uri_join(path, key, subpool),
+                                  svn_fspath__join(path, key, subpool),
                                   entry->id, entry->kind, txn_id, subpool));
         }
 
@@ -2271,7 +2271,7 @@ merge(svn_stringbuf_t *conflict_p,
              a modification. In any of these cases, flag a conflict. */
           if (s_entry == NULL || t_entry == NULL)
             return conflict_err(conflict_p,
-                                svn_uri_join(target_path,
+                                svn_fspath__join(target_path,
                                                 a_entry->name,
                                                 iterpool));
 
@@ -2286,7 +2286,7 @@ merge(svn_stringbuf_t *conflict_p,
               || strcmp(svn_fs_base__id_copy_id(t_entry->id),
                         svn_fs_base__id_copy_id(a_entry->id)) != 0)
             return conflict_err(conflict_p,
-                                svn_uri_join(target_path,
+                                svn_fspath__join(target_path,
                                                 a_entry->name,
                                                 iterpool));
 
@@ -2303,14 +2303,14 @@ merge(svn_stringbuf_t *conflict_p,
               || (svn_fs_base__dag_node_kind(t_ent_node) == svn_node_file)
               || (svn_fs_base__dag_node_kind(a_ent_node) == svn_node_file))
             return conflict_err(conflict_p,
-                                svn_uri_join(target_path,
+                                svn_fspath__join(target_path,
                                                 a_entry->name,
                                                 iterpool));
 
           /* Direct modifications were made to the directory
              ANCESTOR-ENTRY in both SOURCE and TARGET.  Recursively
              merge these modifications. */
-          new_tpath = svn_uri_join(target_path, t_entry->name, iterpool);
+          new_tpath = svn_fspath__join(target_path, t_entry->name, iterpool);
           SVN_ERR(merge(conflict_p, new_tpath,
                         t_ent_node, s_ent_node, a_ent_node,
                         txn_id, &sub_mergeinfo_increment, trail, iterpool));
@@ -2346,7 +2346,7 @@ merge(svn_stringbuf_t *conflict_p,
       /* If NAME exists in TARGET, declare a conflict. */
       if (t_entry)
         return conflict_err(conflict_p,
-                            svn_uri_join(target_path,
+                            svn_fspath__join(target_path,
                                             t_entry->name,
                                             iterpool));
 
@@ -2522,7 +2522,7 @@ verify_locks(const char *txn_name,
       /* If this path has already been verified as part of a recursive
          check of one of its parents, no need to do it again.  */
       if (last_recursed
-          && svn_uri_is_child(last_recursed->data, path, subpool))
+          && svn_fspath__is_child(last_recursed->data, path, subpool))
         continue;
 
       /* Fetch the change associated with our path.  */
@@ -4488,7 +4488,7 @@ txn_body_history_prev(void *baton, trail
       if (strcmp(path, copy_dst) == 0)
         remainder = "";
       else
-        remainder = svn_uri_is_child(copy_dst, path, trail->pool);
+        remainder = svn_fspath__is_child(copy_dst, path, trail->pool);
 
       if (remainder)
         {
@@ -4501,7 +4501,7 @@ txn_body_history_prev(void *baton, trail
                   (&dst_rev, fs,
                    svn_fs_base__id_txn_id(copy->dst_noderev_id),
                    trail, trail->pool));
-          src_path = svn_uri_join(copy->src_path, remainder,
+          src_path = svn_fspath__join(copy->src_path, remainder,
                                      trail->pool);
           if (copy->kind == copy_kind_soft)
             retry = TRUE;
@@ -4911,8 +4911,8 @@ prev_location(const char **prev_path,
   SVN_ERR(base_copied_from(&copy_src_rev, &copy_src_path,
                            copy_root, copy_path, pool));
   if (! strcmp(copy_path, path) == 0)
-    remainder = svn_uri_is_child(copy_path, path, pool);
-  *prev_path = svn_uri_join(copy_src_path, remainder, pool);
+    remainder = svn_fspath__is_child(copy_path, path, pool);
+  *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
   *prev_rev = copy_src_rev;
   return SVN_NO_ERROR;
 }
@@ -5090,6 +5090,129 @@ base_node_origin_rev(svn_revnum_t *revis
 
 /* Mergeinfo Queries */
 
+
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_base__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                                svn_fs_t *fs,
+                                svn_mergeinfo_t mergeinfo,
+                                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))
+    {
+      const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
+      apr_hash_t *paths = svn__apr_hash_index_val(hi);
+      apr_pool_t *inner_iterpool;
+      apr_hash_index_t *hi2;
+      svn_node_kind_t kind;
+      svn_fs_root_t *mergeinfo_rev_root;
+
+      svn_pool_clear(iterpool);
+      inner_iterpool = svn_pool_create(iterpool);
+
+      SVN_ERR(svn_fs_base__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(base_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
+              {
+                svn_mergeinfo_t good_mergeinfo_fragment;
+                const char *mergeinfo_str =
+                  apr_psprintf(inner_iterpool, "%s:%ld", path, *rev);
+
+                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;
+}
+
+
 /* Examine directory NODE's immediately children for mergeinfo.
 
    For those which have explicit mergeinfo, add their mergeinfo to
@@ -5173,7 +5296,7 @@ txn_body_get_mergeinfo_data_and_entries(
           SVN_ERR(svn_mergeinfo_parse(&child_mergeinfo, pval->data,
                                       result_pool));
           apr_hash_set(args->result_catalog,
-                       svn_uri_join(args->node_path, dirent->name,
+                       svn_fspath__join(args->node_path, dirent->name,
                                        result_pool),
                        APR_HASH_KEY_STRING,
                        child_mergeinfo);
@@ -5243,7 +5366,7 @@ crawl_directory_for_mergeinfo(svn_fs_t *
       svn_pool_clear(iterpool);
       apr_hash_this(hi, &key, NULL, &val);
       crawl_directory_for_mergeinfo(fs, val,
-                                    svn_uri_join(node_path, key, iterpool),
+                                    svn_fspath__join(node_path, key, iterpool),
                                     result_catalog, iterpool);
     }
   svn_pool_destroy(iterpool);
@@ -5269,7 +5392,7 @@ append_to_merged_froms(svn_mergeinfo_t *
       const void *key;
       void *val;
       apr_hash_this(hi, &key, NULL, &val);
-      apr_hash_set(*output, svn_uri_join(key, rel_path, pool),
+      apr_hash_set(*output, svn_fspath__join(key, rel_path, pool),
                    APR_HASH_KEY_STRING, svn_rangelist_dup(val, pool));
     }
   return SVN_NO_ERROR;
@@ -5278,12 +5401,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 +5426,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 +5508,7 @@ txn_body_get_mergeinfo_for_path(void *ba
                                                          nearest_ancestor,
                                                          trail->pool),
                                      args->pool));
+      *(args->inherited) = TRUE;
     }
   return SVN_NO_ERROR;
 }
@@ -5413,14 +5540,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 +5561,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 +5571,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 +5580,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_base__validate_mergeinfo(&path_mergeinfo, root->fs,
+                                                    path_mergeinfo, 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 +5632,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,10 +5646,11 @@ 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);
 }
 
+
 
 /* Creating root objects.  */
 

Modified: subversion/branches/performance/subversion/libsvn_fs_base/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/tree.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/tree.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/tree.h Fri Nov 26 18:55:51 2010
@@ -95,6 +95,14 @@ svn_error_t *svn_fs_base__get_path_creat
                                                trail_t *trail,
                                                apr_pool_t *pool);
 
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_base__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                                svn_fs_t *fs,
+                                svn_mergeinfo_t mergeinfo,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool);
+
 /* ### Experimental obliterate-like-deltify - see implementation. */
 svn_error_t *
 svn_fs_base__obliterate_rep(svn_fs_t *fs,

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/dag.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/dag.c Fri Nov 26 18:55:51 2010
@@ -390,7 +390,7 @@ make_entry(dag_node_t **child_p,
   /* Create the new node's NODE-REVISION */
   memset(&new_noderev, 0, sizeof(new_noderev));
   new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
-  new_noderev.created_path = svn_uri_join(parent_path, name, pool);
+  new_noderev.created_path = svn_fspath__join(parent_path, name, pool);
 
   SVN_ERR(get_node_revision(&parent_noderev, parent, pool));
   new_noderev.copyroot_path = apr_pstrdup(pool,
@@ -704,7 +704,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **
       noderev->predecessor_id = svn_fs_fs__id_copy(cur_entry->id, pool);
       if (noderev->predecessor_count != -1)
         noderev->predecessor_count++;
-      noderev->created_path = svn_uri_join(parent_path, name, pool);
+      noderev->created_path = svn_fspath__join(parent_path, name, pool);
 
       SVN_ERR(svn_fs_fs__create_successor(&new_node_id, fs, cur_entry->id,
                                           noderev, copy_id, txn_id, pool));
@@ -1201,7 +1201,7 @@ svn_fs_fs__dag_copy(dag_node_t *to_node,
       if (to_noderev->predecessor_count != -1)
         to_noderev->predecessor_count++;
       to_noderev->created_path =
-        svn_uri_join(svn_fs_fs__dag_get_created_path(to_node), entry,
+        svn_fspath__join(svn_fs_fs__dag_get_created_path(to_node), entry,
                      pool);
       to_noderev->copyfrom_path = apr_pstrdup(pool, from_path);
       to_noderev->copyfrom_rev = from_rev;

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs.c Fri Nov 26 18:55:51 2010
@@ -159,7 +159,8 @@ static fs_vtable_t fs_vtable = {
   svn_fs_fs__unlock,
   svn_fs_fs__get_lock,
   svn_fs_fs__get_locks,
-  fs_set_errcall
+  fs_set_errcall,
+  svn_fs_fs__validate_mergeinfo,
 };
 
 

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Fri Nov 26 18:55:51 2010
@@ -1363,13 +1363,11 @@ upgrade_body(void *baton, apr_pool_t *po
     case svn_node_file:
       break;
     default:
-      return svn_error_return(svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
-                                                _("'%s' is not a regular file."
-                                                  " Please move it out of "
-                                                  "the way and try again"),
-                                                svn_dirent_join(fs->path,
-                                                                PATH_CONFIG,
-                                                                pool)));
+      return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
+                               _("'%s' is not a regular file."
+                                 " Please move it out of "
+                                 "the way and try again"),
+                               svn_dirent_join(fs->path, PATH_CONFIG, pool));
     }
 
   /* If we're already up-to-date, there's nothing else to be done here. */

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/lock.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/lock.c Fri Nov 26 18:55:51 2010
@@ -1024,7 +1024,7 @@ get_locks_filter_func(void *baton,
   else if ((b->requested_depth == svn_depth_files) ||
            (b->requested_depth == svn_depth_immediates))
     {
-      const char *rel_uri = svn_uri_is_child(b->path, lock->path, pool);
+      const char *rel_uri = svn_fspath__is_child(b->path, lock->path, pool);
       if (rel_uri && (svn_path_component_count(rel_uri) == 1))
         SVN_ERR(b->get_locks_func(b->get_locks_baton, lock, pool));
     }

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/tree.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/tree.c Fri Nov 26 18:55:51 2010
@@ -413,7 +413,7 @@ parent_path_path(parent_path_t *parent_p
   if (parent_path->parent)
     path_so_far = parent_path_path(parent_path->parent, pool);
   return parent_path->entry
-    ? svn_uri_join(path_so_far, parent_path->entry, pool)
+    ? svn_fspath__join(path_so_far, parent_path->entry, pool)
     : path_so_far;
 }
 
@@ -618,7 +618,7 @@ open_path(parent_path_t **parent_path_p,
       entry = svn_fs__next_entry_name(&next, rest, pool);
 
       /* Calculate the path traversed thus far. */
-      path_so_far = svn_uri_join(path_so_far, entry, pool);
+      path_so_far = svn_fspath__join(path_so_far, entry, pool);
 
       if (*entry == '\0')
         {
@@ -2981,7 +2981,7 @@ prev_location(const char **prev_path,
                          copy_root, copy_path, pool));
   if (strcmp(copy_path, path) != 0)
     remainder = svn_relpath_is_child(copy_path, path, pool);
-  *prev_path = svn_uri_join(copy_src_path, remainder, pool);
+  *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
   *prev_rev = copy_src_rev;
   return SVN_NO_ERROR;
 }
@@ -3241,7 +3241,7 @@ history_prev(void *baton, apr_pool_t *po
           SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copy_src, node, pool));
 
           dst_rev = copyroot_rev;
-          src_path = svn_uri_join(copy_src, remainder, pool);
+          src_path = svn_fspath__join(copy_src, remainder, pool);
         }
     }
 
@@ -3375,6 +3375,128 @@ assemble_history(svn_fs_t *fs,
 
 /* mergeinfo queries */
 
+
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_fs__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                              svn_fs_t *fs,
+                              svn_mergeinfo_t mergeinfo,
+                              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))
+    {
+      const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
+      apr_hash_t *paths = svn__apr_hash_index_val(hi);
+      apr_pool_t *inner_iterpool;
+      apr_hash_index_t *hi2;
+      svn_node_kind_t kind;
+      svn_fs_root_t *mergeinfo_rev_root;
+
+      svn_pool_clear(iterpool);
+      inner_iterpool = svn_pool_create(iterpool);
+
+      SVN_ERR(svn_fs_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_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
+              {
+                svn_mergeinfo_t good_mergeinfo_fragment;
+                const char *mergeinfo_str =
+                  apr_psprintf(inner_iterpool, "%s:%ld", path, *rev);
+
+                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;
+}
+
 /* DIR_DAG is a directory DAG node which has mergeinfo in its
    descendants.  This function iterates over its children.  For each
    child with immediate mergeinfo, it adds its mergeinfo to
@@ -3411,7 +3533,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs
 
       svn_pool_clear(iterpool);
 
-      kid_path = svn_uri_join(this_path, dirent->name, iterpool);
+      kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
       SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
 
       SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag, iterpool));
@@ -3480,7 +3602,7 @@ append_to_merged_froms(svn_mergeinfo_t *
       apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
       char *newpath;
 
-      newpath = svn_uri_join(path, path_piece, pool);
+      newpath = svn_fspath__join(path, path_piece, pool);
       apr_hash_set(*output, newpath, APR_HASH_KEY_STRING,
                    svn_rangelist_dup(rangelist, pool));
     }
@@ -3490,14 +3612,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 +3672,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 +3685,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 +3707,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_fs__validate_mergeinfo(mergeinfo, rev_root->fs,
+                                              *mergeinfo, pool, iterpool));
+      svn_pool_destroy(iterpool);
+      return SVN_NO_ERROR;
     }
 }
 
@@ -3620,13 +3751,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 +3777,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 +3799,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,10 +3819,11 @@ 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. */
 static root_vtable_t root_vtable = {
   fs_paths_changed,
@@ -3715,7 +3853,7 @@ static root_vtable_t root_vtable = {
   fs_contents_changed,
   fs_get_file_delta_stream,
   fs_merge,
-  fs_get_mergeinfo
+  fs_get_mergeinfo,
 };
 
 /* Construct a new root object in FS, allocated from POOL.  */

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/tree.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/tree.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/tree.h Fri Nov 26 18:55:51 2010
@@ -58,6 +58,7 @@ svn_error_t *svn_fs_fs__commit_obliterat
 svn_error_t *svn_fs_fs__txn_root(svn_fs_root_t **root_p, svn_fs_txn_t *txn,
                                  apr_pool_t *pool);
 
+
 /* Set KIND_P to the node kind of the node at PATH in ROOT.
    Allocate the structure in POOL. */
 svn_error_t *
@@ -76,6 +77,14 @@ svn_fs_fs__node_created_rev(svn_revnum_t
                             const char *path,
                             apr_pool_t *pool);
 
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_fs__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                              svn_fs_t *fs,
+                              svn_mergeinfo_t mergeinfo,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/performance/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra/deprecated.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra/deprecated.c Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra/ra_loader.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra/ra_loader.c Fri Nov 26 18:55:51 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/performance/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra/ra_loader.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/performance/subversion/libsvn_ra/ra_loader.h Fri Nov 26 18:55:51 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/performance/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c Fri Nov 26 18:55:51 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,
@@ -925,7 +928,7 @@ svn_ra_local__do_check_path(svn_ra_sessi
 {
   svn_ra_local__session_baton_t *sess = session->priv;
   svn_fs_root_t *root;
-  const char *abs_path = svn_uri_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   if (! SVN_IS_VALID_REVNUM(revision))
     SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/mergeinfo.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/mergeinfo.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/mergeinfo.c Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_ra_neon/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/options.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/options.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/options.c Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/mergeinfo.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/mergeinfo.c Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/options.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/options.c Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/ra_serf.h?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/ra_serf.h Fri Nov 26 18:55:51 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/performance/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_svn/client.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_svn/client.c Fri Nov 26 18:55:51 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/branches/performance/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/fs-wrap.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/fs-wrap.c Fri Nov 26 18:55:51 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/performance/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/replay.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/replay.c Fri Nov 26 18:55:51 2010
@@ -225,8 +225,13 @@ add_subdir(svn_fs_root_t *source_root,
             continue;
           else if (change->change_kind == svn_fs_path_change_replace)
             {
-              /* ### Can this assert fail? */
-              SVN_ERR_ASSERT(change->copyfrom_known);
+              if (! change->copyfrom_known)
+                {
+                  SVN_ERR(svn_fs_copied_from(&change->copyfrom_rev,
+                                             &change->copyfrom_path,
+                                             target_root, new_path, pool));
+                  change->copyfrom_known = TRUE;
+                }
               copyfrom_path = change->copyfrom_path;
               copyfrom_rev = change->copyfrom_rev;
             }

Modified: subversion/branches/performance/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/reporter.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/reporter.c Fri Nov 26 18:55:51 2010
@@ -670,7 +670,7 @@ fake_dirent(const svn_fs_dirent_t **entr
       ent = apr_palloc(pool, sizeof(**entry));
       /* ### All callers should be updated to pass just one of these
              formats */
-      ent->name = (*path == '/') ? svn_uri_basename(path, pool)
+      ent->name = (*path == '/') ? svn_fspath__basename(path, pool)
                                  : svn_relpath_basename(path, pool);
       SVN_ERR(svn_fs_node_id(&ent->id, root, path, pool));
       ent->kind = kind;

Modified: subversion/branches/performance/subversion/libsvn_subr/constructors.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/constructors.c?rev=1039511&r1=1039510&r2=1039511&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/constructors.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/constructors.c Fri Nov 26 18:55:51 2010
@@ -67,6 +67,9 @@ svn_log_changed_path2_create(apr_pool_t 
   svn_log_changed_path2_t *new_changed_path
     = apr_pcalloc(pool, sizeof(*new_changed_path));
 
+  new_changed_path->text_modified = svn_tristate_unknown;
+  new_changed_path->props_modified = svn_tristate_unknown;
+
   return new_changed_path;
 }