You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/12/23 19:34:20 UTC

svn commit: r1425508 [5/17] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ notes/ notes/api-errata/1.8/ notes/obliterate/ notes/tree-conflicts/ subversion/ subversion/bindings/s...

Modified: subversion/branches/javahl-ra/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/mergeinfo.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/mergeinfo.c Sun Dec 23 18:34:14 2012
@@ -1572,6 +1572,44 @@ logs_for_mergeinfo_rangelist(const char 
 
   return SVN_NO_ERROR;
 }
+
+/* Set *OUT_MERGEINFO to a shallow copy of MERGEINFO with each source path
+   converted to a (URI-encoded) URL based on REPOS_ROOT_URL. *OUT_MERGEINFO
+   is declared as 'apr_hash_t *' because its key do not obey the rules of
+   'svn_mergeinfo_t'.
+
+   Allocate *OUT_MERGEINFO and the new keys in RESULT_POOL.  Use
+   SCRATCH_POOL for any temporary allocations. */
+static svn_error_t *
+mergeinfo_relpaths_to_urls(apr_hash_t **out_mergeinfo,
+                           svn_mergeinfo_t mergeinfo,
+                           const char *repos_root_url,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  *out_mergeinfo = NULL;
+  if (mergeinfo)
+    {
+      apr_hash_index_t *hi;
+      apr_hash_t *full_path_mergeinfo = apr_hash_make(result_pool);
+
+      for (hi = apr_hash_first(scratch_pool, mergeinfo);
+           hi; hi = apr_hash_next(hi))
+        {
+          const char *key = svn__apr_hash_index_key(hi);
+          void *val = svn__apr_hash_index_val(hi);
+
+          apr_hash_set(full_path_mergeinfo,
+                       svn_path_url_add_component2(repos_root_url, key + 1,
+                                                   result_pool),
+                       APR_HASH_KEY_STRING, val);
+        }
+      *out_mergeinfo = full_path_mergeinfo;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 /*** Public APIs ***/
 
@@ -1614,8 +1652,8 @@ svn_client_mergeinfo_get_merged(apr_hash
       mergeinfo = NULL;
     }
 
-  SVN_ERR(svn_mergeinfo__relpaths_to_urls(mergeinfo_p, mergeinfo,
-                                          repos_root, pool, pool));
+  SVN_ERR(mergeinfo_relpaths_to_urls(mergeinfo_p, mergeinfo,
+                                     repos_root, pool, pool));
   return SVN_NO_ERROR;
 }
 
@@ -1729,7 +1767,10 @@ svn_client_mergeinfo_log2(svn_boolean_t 
         }
     }
 
-  /* Open RA sessions to the repository for the source and target.
+  /* Fetch the location history as mergeinfo, for the source branch
+   * (between the given start and end revisions), and, if we're finding
+   * merged revisions, then also for the entire target branch.
+   *
    * ### TODO: As the source and target must be in the same repository, we
    * should share a single session, tracking the two URLs separately. */
   {

Modified: subversion/branches/javahl-ra/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/prop_commands.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/prop_commands.c Sun Dec 23 18:34:14 2012
@@ -38,6 +38,7 @@
 #include "svn_pools.h"
 #include "svn_props.h"
 #include "svn_hash.h"
+#include "svn_sorts.h"
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
@@ -594,21 +595,28 @@ pristine_or_working_props(apr_hash_t **p
 
 /* Helper for the remote case of svn_client_propget.
  *
- * Get the value of property PROPNAME in REVNUM, using RA_LIB and
- * SESSION.  Store the value ('svn_string_t *') in PROPS, under the
- * path key "TARGET_PREFIX/TARGET_RELATIVE" ('const char *').
+ * If PROPS is not null, then get the value of property PROPNAME in REVNUM,
+   using RA_LIB and SESSION.  Store the value ('svn_string_t *') in PROPS,
+   under the path key "TARGET_PREFIX/TARGET_RELATIVE" ('const char *').
+ *
+ * If INHERITED_PROPS is not null, then set *INHERITED_PROPS to a
+ * depth-first ordered array of svn_prop_inherited_item_t * structures
+ * representing the PROPNAME properties inherited by the target.  If
+ * INHERITABLE_PROPS in not null and no inheritable properties are found,
+ * then set *INHERITED_PROPS to an empty array.
  *
  * Recurse according to DEPTH, similarly to svn_client_propget3().
  *
  * KIND is the kind of the node at "TARGET_PREFIX/TARGET_RELATIVE".
  * Yes, caller passes this; it makes the recursion more efficient :-).
  *
- * Allocate the keys and values in PERM_POOL, but do all temporary
- * work in WORK_POOL.  The two pools can be the same; recursive
- * calls may use a different WORK_POOL, however.
+ * Allocate PROPS and *INHERITED_PROPS in RESULT_POOL, but do all temporary
+ * work in SCRATCH_POOL.  The two pools can be the same; recursive
+ * calls may use a different SCRATCH_POOL, however.
  */
 static svn_error_t *
 remote_propget(apr_hash_t *props,
+               apr_array_header_t **inherited_props,
                const char *propname,
                const char *target_prefix,
                const char *target_relative,
@@ -616,26 +624,27 @@ remote_propget(apr_hash_t *props,
                svn_revnum_t revnum,
                svn_ra_session_t *ra_session,
                svn_depth_t depth,
-               apr_pool_t *perm_pool,
-               apr_pool_t *work_pool)
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
 {
   apr_hash_t *dirents;
-  apr_hash_t *prop_hash;
+  apr_hash_t *prop_hash = NULL;
   const svn_string_t *val;
   const char *target_full_url =
-    svn_path_url_add_component2(target_prefix, target_relative, work_pool);
+    svn_path_url_add_component2(target_prefix, target_relative,
+                                scratch_pool);
 
   if (kind == svn_node_dir)
     {
       SVN_ERR(svn_ra_get_dir2(ra_session,
                               (depth >= svn_depth_files ? &dirents : NULL),
                               NULL, &prop_hash, target_relative, revnum,
-                              SVN_DIRENT_KIND, work_pool));
+                              SVN_DIRENT_KIND, scratch_pool));
     }
   else if (kind == svn_node_file)
     {
       SVN_ERR(svn_ra_get_file(ra_session, target_relative, revnum,
-                              NULL, NULL, &prop_hash, work_pool));
+                              NULL, NULL, &prop_hash, scratch_pool));
     }
   else if (kind == svn_node_none)
     {
@@ -650,10 +659,52 @@ remote_propget(apr_hash_t *props,
                                target_full_url);
     }
 
-  if ((val = apr_hash_get(prop_hash, propname, APR_HASH_KEY_STRING)))
+  if (inherited_props)
+    {
+      /* We will filter out all but PROPNAME later, making a final copy
+         in RESULT_POOL, so pass SCRATCH_POOL for both pools. */
+      SVN_ERR(svn_ra_get_inherited_props(ra_session, inherited_props,
+                                         target_relative, revnum,
+                                         scratch_pool, scratch_pool));
+    }
+
+  /* Make a copy of any inherited PROPNAME properties in RESULT_POOL. */
+  if (inherited_props)
+    {
+      int i;
+      apr_array_header_t *final_iprops =
+        apr_array_make(result_pool, 1, sizeof(svn_prop_inherited_item_t *));
+
+      for (i = 0; i < (*inherited_props)->nelts; i++)
+        {
+          svn_prop_inherited_item_t *iprop =
+            APR_ARRAY_IDX((*inherited_props), i, svn_prop_inherited_item_t *);
+          svn_string_t *iprop_val = apr_hash_get(iprop->prop_hash, propname,
+                                                 APR_HASH_KEY_STRING);
+
+          if (iprop_val)
+            {
+              svn_prop_inherited_item_t *new_iprop =
+                apr_palloc(result_pool, sizeof(*new_iprop));
+              new_iprop->path_or_url =
+                apr_pstrdup(result_pool, iprop->path_or_url);
+              new_iprop->prop_hash = apr_hash_make(result_pool);
+              apr_hash_set(new_iprop->prop_hash,
+                           apr_pstrdup(result_pool, propname),
+                           APR_HASH_KEY_STRING,
+                           svn_string_dup(iprop_val, result_pool));
+              APR_ARRAY_PUSH(final_iprops, svn_prop_inherited_item_t *) =
+                new_iprop;
+            }
+        }
+      *inherited_props = final_iprops;
+    }
+
+  if (prop_hash
+      && (val = apr_hash_get(prop_hash, propname, APR_HASH_KEY_STRING)))
     {
-      apr_hash_set(props, apr_pstrdup(perm_pool, target_full_url),
-                   APR_HASH_KEY_STRING, svn_string_dup(val, perm_pool));
+      apr_hash_set(props, apr_pstrdup(result_pool, target_full_url),
+                   APR_HASH_KEY_STRING, svn_string_dup(val, result_pool));
     }
 
   if (depth >= svn_depth_files
@@ -661,9 +712,9 @@ remote_propget(apr_hash_t *props,
       && apr_hash_count(dirents) > 0)
     {
       apr_hash_index_t *hi;
-      apr_pool_t *iterpool = svn_pool_create(work_pool);
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
-      for (hi = apr_hash_first(work_pool, dirents);
+      for (hi = apr_hash_first(scratch_pool, dirents);
            hi;
            hi = apr_hash_next(hi))
         {
@@ -683,7 +734,7 @@ remote_propget(apr_hash_t *props,
           new_target_relative = svn_relpath_join(target_relative, this_name,
                                                  iterpool);
 
-          SVN_ERR(remote_propget(props,
+          SVN_ERR(remote_propget(props, NULL,
                                  propname,
                                  target_prefix,
                                  new_target_relative,
@@ -691,7 +742,7 @@ remote_propget(apr_hash_t *props,
                                  revnum,
                                  ra_session,
                                  depth_below_here,
-                                 perm_pool, iterpool));
+                                 result_pool, iterpool));
         }
 
       svn_pool_destroy(iterpool);
@@ -792,7 +843,8 @@ get_prop_from_wc(apr_hash_t **props,
 
 /* Note: this implementation is very similar to svn_client_proplist. */
 svn_error_t *
-svn_client_propget4(apr_hash_t **props,
+svn_client_propget5(apr_hash_t **props,
+                    apr_array_header_t **inherited_props,
                     const char *propname,
                     const char *target,
                     const svn_opt_revision_t *peg_revision,
@@ -805,6 +857,8 @@ svn_client_propget4(apr_hash_t **props,
                     apr_pool_t *scratch_pool)
 {
   svn_revnum_t revnum;
+  svn_boolean_t local_explicit_props;
+  svn_boolean_t local_iprops;
 
   SVN_ERR(error_if_wcprop_name(propname));
   if (!svn_path_is_url(target))
@@ -814,9 +868,19 @@ svn_client_propget4(apr_hash_t **props,
                                                         target);
   revision = svn_cl__rev_default_to_peg(revision, peg_revision);
 
-  if (! svn_path_is_url(target)
-      && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
-      && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
+  local_explicit_props =
+    (! svn_path_is_url(target)
+     && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
+     && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind));
+
+  local_iprops =
+    (local_explicit_props
+     && (peg_revision->kind == svn_opt_revision_working
+         || peg_revision->kind == svn_opt_revision_unspecified )
+     && (revision->kind == svn_opt_revision_working
+         || revision->kind == svn_opt_revision_unspecified ));
+
+  if (local_explicit_props)
     {
       svn_node_kind_t kind;
       svn_boolean_t pristine;
@@ -850,30 +914,120 @@ svn_client_propget4(apr_hash_t **props,
       else if (err)
         return svn_error_trace(err);
 
+      if (inherited_props && local_iprops)
+        SVN_ERR(svn_wc__get_iprops(inherited_props, ctx->wc_ctx,
+                                   target, propname,
+                                   scratch_pool, scratch_pool));
+
       SVN_ERR(get_prop_from_wc(props, propname, target,
                                pristine, kind,
                                depth, changelists, ctx, scratch_pool,
                                result_pool));
     }
-  else
+
+  if ((inherited_props && !local_iprops)
+      || !local_explicit_props)
     {
-      svn_client__pathrev_t *loc;
       svn_ra_session_t *ra_session;
       svn_node_kind_t kind;
+      svn_opt_revision_t new_operative_rev;
+      svn_opt_revision_t new_peg_rev;
+
+      /* Peg or operative revisions may be WC specific for
+         TARGET's explicit props, but still require us to
+         contact the repository for the inherited properties. */
+      if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind)
+          || SVN_CLIENT__REVKIND_NEEDS_WC(revision->kind))
+        {
+          svn_revnum_t origin_rev;
+          const char *repos_relpath;
+          const char *repos_root_url;
+          const char *repos_uuid;
+          const char *local_abspath;
+          const char *copy_root_abspath;
+          svn_boolean_t is_copy;
+
+          SVN_ERR(svn_dirent_get_absolute(&local_abspath, target,
+                                          scratch_pool));
+
+          if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+            {
+              SVN_ERR(svn_wc__node_get_origin(&is_copy,
+                                              &origin_rev,
+                                              &repos_relpath,
+                                              &repos_root_url,
+                                              &repos_uuid,
+                                              &copy_root_abspath,
+                                              ctx->wc_ctx,
+                                              local_abspath,
+                                              FALSE, /* scan_deleted */
+                                              result_pool,
+                                              scratch_pool));
+              if (repos_relpath)
+                {
+                  target = svn_path_url_add_component2(repos_root_url,
+                                                       repos_relpath,
+                                                       scratch_pool);
+                  if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+                    {
+                      svn_revnum_t resolved_peg_rev;
+
+                      SVN_ERR(svn_client__get_revision_number(
+                        &resolved_peg_rev, NULL, ctx->wc_ctx,
+                        local_abspath, NULL, peg_revision, scratch_pool));
+                      new_peg_rev.kind = svn_opt_revision_number;
+                      new_peg_rev.value.number = resolved_peg_rev;
+                      peg_revision = &new_peg_rev;
+                    }
+
+                  if (SVN_CLIENT__REVKIND_NEEDS_WC(revision->kind))
+                    {
+                      svn_revnum_t resolved_operative_rev;
+
+                      SVN_ERR(svn_client__get_revision_number(
+                        &resolved_operative_rev, NULL, ctx->wc_ctx,
+                        local_abspath, NULL, revision, scratch_pool));
+                      new_operative_rev.kind = svn_opt_revision_number;
+                      new_operative_rev.value.number = resolved_operative_rev;
+                      revision = &new_operative_rev;
+                    }
+                }
+              else
+                {
+                  /* TARGET doesn't exist in the repository, so there are
+                     obviously not inherited props to be found there. */
+                  local_iprops = TRUE;
+                  *inherited_props = apr_array_make(
+                    result_pool, 0, sizeof(svn_prop_inherited_item_t *));
+                }
+            }
+        }
 
-      /* Get an RA plugin for this filesystem object. */
-      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
-                                                target, NULL,
-                                                peg_revision,
-                                                revision, ctx, scratch_pool));
-
-      SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, scratch_pool));
-
-      *props = apr_hash_make(result_pool);
-      SVN_ERR(remote_propget(*props, propname, loc->url, "",
-                             kind, loc->rev, ra_session,
-                             depth, result_pool, scratch_pool));
-      revnum = loc->rev;
+      /* Do we still have anything to ask the repository about? */
+      if (!local_explicit_props || !local_iprops)
+        {
+          svn_client__pathrev_t *loc;
+
+          /* Get an RA plugin for this filesystem object. */
+          SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                                    target, NULL,
+                                                    peg_revision,
+                                                    revision, ctx,
+                                                    scratch_pool));
+
+          SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind,
+                                    scratch_pool));
+
+          if (!local_explicit_props)
+            *props = apr_hash_make(result_pool);
+
+          SVN_ERR(remote_propget(!local_explicit_props ? *props : NULL,
+                                 !local_iprops ? inherited_props : NULL,
+                                 propname, loc->url, "",
+                                 kind, loc->rev, ra_session,
+                                 depth, result_pool, scratch_pool));
+          revnum = loc->rev;
+        }
     }
 
   if (actual_revnum)
@@ -907,19 +1061,24 @@ svn_client_revprop_get(const char *propn
 }
 
 
-/* Call RECEIVER for the given PATH and PROP_HASH.
+/* Call RECEIVER for the given PATH and its PROP_HASH and/or
+ * INHERITED_PROPERTIES.
  *
- * If PROP_HASH is null or has zero count, do nothing.
+ * If PROP_HASH is null or has zero count or INHERITED_PROPERTIES is null,
+ * then do nothing.
  */
 static svn_error_t*
 call_receiver(const char *path,
               apr_hash_t *prop_hash,
-              svn_proplist_receiver_t receiver,
+              apr_array_header_t *inherited_properties,
+              svn_proplist_receiver2_t receiver,
               void *receiver_baton,
-              apr_pool_t *pool)
+              apr_pool_t *scratch_pool)
 {
-  if (prop_hash && apr_hash_count(prop_hash))
-    SVN_ERR(receiver(receiver_baton, path, prop_hash, pool));
+  if ((prop_hash && apr_hash_count(prop_hash))
+      || inherited_properties)
+    SVN_ERR(receiver(receiver_baton, path, prop_hash, inherited_properties,
+                     scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -927,20 +1086,23 @@ call_receiver(const char *path,
 
 /* Helper for the remote case of svn_client_proplist.
  *
- * Push a new 'svn_client_proplist_item_t *' item onto PROPLIST,
- * containing the properties for "TARGET_PREFIX/TARGET_RELATIVE" in
- * REVNUM, obtained using RA_LIB and SESSION.  The item->node_name
- * will be "TARGET_PREFIX/TARGET_RELATIVE", and the value will be a
- * hash mapping 'const char *' property names onto 'svn_string_t *'
- * property values.
+ * If GET_EXPLICIT_PROPS is true, then call RECEIVER for paths at or under
+ * "TARGET_PREFIX/TARGET_RELATIVE@REVNUM" (obtained using RA_SESSION) which
+ * have regular properties.  If GET_TARGET_INHERITED_PROPS is true, then send
+ * the target's inherited properties to the callback.
  *
- * Allocate the new item and its contents in POOL.
- * Do all looping, recursion, and temporary work in SCRATCHPOOL.
+ * The 'path' and keys for 'prop_hash' and 'inherited_prop' arguments to
+ * RECEIVER are all URLs.
+ * 
+ * RESULT_POOL is used to allocated the 'path', 'prop_hash', and
+ * 'inherited_prop' arguments to RECEIVER.  SCRATCH_POOL is used for all
+ * other (temporary) allocations.
  *
  * KIND is the kind of the node at "TARGET_PREFIX/TARGET_RELATIVE".
  *
  * If the target is a directory, only fetch properties for the files
- * and directories at depth DEPTH.
+ * and directories at depth DEPTH.  DEPTH has not effect on inherited
+ * properties.
  */
 static svn_error_t *
 remote_proplist(const char *target_prefix,
@@ -948,29 +1110,36 @@ remote_proplist(const char *target_prefi
                 svn_node_kind_t kind,
                 svn_revnum_t revnum,
                 svn_ra_session_t *ra_session,
+                svn_boolean_t get_explicit_props,
+                svn_boolean_t get_target_inherited_props,
                 svn_depth_t depth,
-                svn_proplist_receiver_t receiver,
+                svn_proplist_receiver2_t receiver,
                 void *receiver_baton,
-                apr_pool_t *pool,
-                apr_pool_t *scratchpool)
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
 {
   apr_hash_t *dirents;
-  apr_hash_t *prop_hash, *final_hash;
+  apr_hash_t *prop_hash = NULL;
+  apr_hash_t *final_hash = NULL;
   apr_hash_index_t *hi;
   const char *target_full_url =
-    svn_path_url_add_component2(target_prefix, target_relative, scratchpool);
+    svn_path_url_add_component2(target_prefix, target_relative, scratch_pool);
+  apr_array_header_t *inherited_props;
 
+  /* Note that we pass only the SCRATCH_POOL to svn_ra_get[dir*|file*] because
+     we'll be filtering out non-regular properties from PROP_HASH before we
+     return. */
   if (kind == svn_node_dir)
     {
       SVN_ERR(svn_ra_get_dir2(ra_session,
                               (depth > svn_depth_empty) ? &dirents : NULL,
                               NULL, &prop_hash, target_relative, revnum,
-                              SVN_DIRENT_KIND, scratchpool));
+                              SVN_DIRENT_KIND, scratch_pool));
     }
   else if (kind == svn_node_file)
     {
       SVN_ERR(svn_ra_get_file(ra_session, target_relative, revnum,
-                              NULL, NULL, &prop_hash, scratchpool));
+                              NULL, NULL, &prop_hash, scratch_pool));
     }
   else
     {
@@ -979,38 +1148,50 @@ remote_proplist(const char *target_prefi
                                target_full_url);
     }
 
-  /* Filter out non-regular properties, since the RA layer returns all
-     kinds.  Copy regular properties keys/vals from the prop_hash
-     allocated in SCRATCHPOOL to the "final" hash allocated in POOL. */
-  final_hash = apr_hash_make(pool);
-  for (hi = apr_hash_first(scratchpool, prop_hash);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const char *name = svn__apr_hash_index_key(hi);
-      apr_ssize_t klen = svn__apr_hash_index_klen(hi);
-      svn_string_t *value = svn__apr_hash_index_val(hi);
-      svn_prop_kind_t prop_kind;
-
-      prop_kind = svn_property_kind2(name);
+  if (get_target_inherited_props)
+    SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props,
+                                       target_relative, revnum,
+                                       result_pool, scratch_pool));
+  else
+    inherited_props = NULL;
 
-      if (prop_kind == svn_prop_regular_kind)
+  if (get_explicit_props)
+    {
+      /* Filter out non-regular properties, since the RA layer returns all
+         kinds.  Copy regular properties keys/vals from the prop_hash
+         allocated in SCRATCH_POOL to the "final" hash allocated in
+         RESULT_POOL. */
+      final_hash = apr_hash_make(result_pool);
+      for (hi = apr_hash_first(scratch_pool, prop_hash);
+           hi;
+           hi = apr_hash_next(hi))
         {
-          name = apr_pstrdup(pool, name);
-          value = svn_string_dup(value, pool);
-          apr_hash_set(final_hash, name, klen, value);
-        }
+          const char *name = svn__apr_hash_index_key(hi);
+          apr_ssize_t klen = svn__apr_hash_index_klen(hi);
+          svn_string_t *value = svn__apr_hash_index_val(hi);
+          svn_prop_kind_t prop_kind;
+
+          prop_kind = svn_property_kind2(name);
+
+          if (prop_kind == svn_prop_regular_kind)
+            {
+              name = apr_pstrdup(result_pool, name);
+              value = svn_string_dup(value, result_pool);
+              apr_hash_set(final_hash, name, klen, value);
+            }
+        }  
     }
 
-  SVN_ERR(call_receiver(target_full_url, final_hash, receiver, receiver_baton,
-                        pool));
+  SVN_ERR(call_receiver(target_full_url, final_hash, inherited_props,
+                        receiver, receiver_baton, result_pool));
 
   if (depth > svn_depth_empty
+      && get_explicit_props
       && (kind == svn_node_dir) && (apr_hash_count(dirents) > 0))
     {
-      apr_pool_t *subpool = svn_pool_create(scratchpool);
+      apr_pool_t *subpool = svn_pool_create(scratch_pool);
 
-      for (hi = apr_hash_first(scratchpool, dirents);
+      for (hi = apr_hash_first(scratch_pool, dirents);
            hi;
            hi = apr_hash_next(hi))
         {
@@ -1036,10 +1217,12 @@ remote_proplist(const char *target_prefi
                                       this_ent->kind,
                                       revnum,
                                       ra_session,
+                                      TRUE,
+                                      FALSE,
                                       depth_below_here,
                                       receiver,
                                       receiver_baton,
-                                      pool,
+                                      result_pool,
                                       subpool));
             }
         }
@@ -1055,7 +1238,7 @@ remote_proplist(const char *target_prefi
 struct recursive_proplist_receiver_baton
 {
   svn_wc_context_t *wc_ctx;  /* Working copy context. */
-  svn_proplist_receiver_t wrapped_receiver;  /* Proplist receiver to call. */
+  svn_proplist_receiver2_t wrapped_receiver;  /* Proplist receiver to call. */
   void *wrapped_receiver_baton;    /* Baton for the proplist receiver. */
 
   /* Anchor, anchor_abspath pair for converting to relative paths */
@@ -1086,114 +1269,275 @@ recursive_proplist_receiver(void *baton,
     path = local_abspath;
 
   return svn_error_trace(b->wrapped_receiver(b->wrapped_receiver_baton,
-                                             path, props, scratch_pool));
+                                             path, props, NULL,
+                                             scratch_pool));
 }
 
-svn_error_t *
-svn_client_proplist3(const char *path_or_url,
-                     const svn_opt_revision_t *peg_revision,
-                     const svn_opt_revision_t *revision,
-                     svn_depth_t depth,
-                     const apr_array_header_t *changelists,
-                     svn_proplist_receiver_t receiver,
-                     void *receiver_baton,
-                     svn_client_ctx_t *ctx,
-                     apr_pool_t *pool)
+/* Helper for svn_client_proplist4 when retrieving properties and/or
+   inherited properties from the repository.  Except as noted below,
+   all arguments are as per svn_client_proplist4.
+   
+   GET_EXPLICIT_PROPS controls if explicit props are retrieved. */
+static svn_error_t *
+get_remote_props(const char *path_or_url,
+                 const svn_opt_revision_t *peg_revision,
+                 const svn_opt_revision_t *revision,
+                 svn_depth_t depth,
+                 svn_boolean_t get_explicit_props,
+                 svn_boolean_t get_target_inherited_props,
+                 svn_proplist_receiver2_t receiver,
+                 void *receiver_baton,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
-  peg_revision = svn_cl__rev_default_to_head_or_working(peg_revision,
-                                                        path_or_url);
-  revision = svn_cl__rev_default_to_peg(revision, peg_revision);
+  svn_ra_session_t *ra_session;
+  svn_node_kind_t kind;
+  svn_opt_revision_t new_operative_rev;
+  svn_opt_revision_t new_peg_rev;
+  svn_client__pathrev_t *loc;
+
+  /* Peg or operative revisions may be WC specific for
+     PATH_OR_URL's explicit props, but still require us to
+     contact the repository for the inherited properties. */
+  if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind)
+      || SVN_CLIENT__REVKIND_NEEDS_WC(revision->kind))
+    {
+      svn_revnum_t origin_rev;
+      const char *repos_relpath;
+      const char *repos_root_url;
+      const char *repos_uuid;
+      const char *local_abspath;
+      const char *copy_root_abspath;
+      svn_boolean_t is_copy;
 
-  if (depth == svn_depth_unknown)
-    depth = svn_depth_empty;
+      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url,
+                                      scratch_pool));
 
-  if (! svn_path_is_url(path_or_url)
-      && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
-      && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
-    {
-      svn_boolean_t pristine;
-      svn_node_kind_t kind;
-      apr_hash_t *changelist_hash = NULL;
-      const char *local_abspath;
+      if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+        {
+          SVN_ERR(svn_wc__node_get_origin(&is_copy,
+                                          &origin_rev,
+                                          &repos_relpath,
+                                          &repos_root_url,
+                                          &repos_uuid,
+                                          &copy_root_abspath,
+                                          ctx->wc_ctx,
+                                          local_abspath,
+                                          FALSE, /* scan_deleted */
+                                          result_pool,
+                                          scratch_pool));
+          if (repos_relpath)
+            {
+              path_or_url =
+                svn_path_url_add_component2(repos_root_url,
+                                            repos_relpath,
+                                            scratch_pool);
+              if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+                {
+                  svn_revnum_t resolved_peg_rev;
+
+                  SVN_ERR(svn_client__get_revision_number(&resolved_peg_rev,
+                                                          NULL, ctx->wc_ctx,
+                                                          local_abspath, NULL,
+                                                          peg_revision,
+                                                          scratch_pool));
+                  new_peg_rev.kind = svn_opt_revision_number;
+                  new_peg_rev.value.number = resolved_peg_rev;
+                  peg_revision = &new_peg_rev;
+                }
+
+              if (SVN_CLIENT__REVKIND_NEEDS_WC(revision->kind))
+                {
+                  svn_revnum_t resolved_operative_rev;
+
+                  SVN_ERR(svn_client__get_revision_number(
+                    &resolved_operative_rev,
+                    NULL, ctx->wc_ctx,
+                    local_abspath, NULL,
+                    revision,
+                    scratch_pool));
+                  new_operative_rev.kind = svn_opt_revision_number;
+                  new_operative_rev.value.number = resolved_operative_rev;
+                  revision = &new_operative_rev;
+                }
+            }
+          else
+            {
+                  /* PATH_OR_URL doesn't exist in the repository, so there are
+                     obviously not inherited props to be found there. If we
+                     aren't looking for explicit props then we're done. */
+                  if (!get_explicit_props)
+                    return SVN_NO_ERROR;
+            }
+        }
+    }
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url, pool));
+  /* Get an RA session for this URL. */
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                            path_or_url, NULL,
+                                            peg_revision,
+                                            revision, ctx,
+                                            result_pool));
+
+  SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind,
+                            result_pool));
+
+  SVN_ERR(remote_proplist(loc->url, "", kind, loc->rev, ra_session,
+                          get_explicit_props,
+                          get_target_inherited_props,
+                          depth, receiver, receiver_baton,
+                          result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
 
-      pristine = ((revision->kind == svn_opt_revision_committed)
-                  || (revision->kind == svn_opt_revision_base));
+/* Helper for svn_client_proplist4 when retrieving properties and
+   possibly inherited properties from the WC.  All arguments are as
+   per svn_client_proplist4. */
+static svn_error_t *
+get_local_props(const char *path_or_url,
+                const svn_opt_revision_t *revision,
+                svn_depth_t depth,
+                const apr_array_header_t *changelists,
+                svn_boolean_t get_target_inherited_props,
+                svn_proplist_receiver2_t receiver,
+                void *receiver_baton,
+                svn_client_ctx_t *ctx,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  svn_boolean_t pristine;
+  svn_node_kind_t kind;
+  apr_hash_t *changelist_hash = NULL;
+  const char *local_abspath;
 
-      SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
-                               pool));
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url,
+                                  scratch_pool));
 
-      if (kind == svn_node_unknown || kind == svn_node_none)
-        {
-          /* svn uses SVN_ERR_UNVERSIONED_RESOURCE as warning only
-             for this function. */
-          return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
-                                   _("'%s' is not under version control"),
-                                   svn_dirent_local_style(local_abspath,
-                                                          pool));
-        }
+  pristine = ((revision->kind == svn_opt_revision_committed)
+              || (revision->kind == svn_opt_revision_base));
 
-      if (changelists && changelists->nelts)
-        SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash,
-                                           changelists, pool));
+  SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
+                           scratch_pool));
 
-      /* Fetch, recursively or not. */
-      if (kind == svn_node_dir)
-        {
-          struct recursive_proplist_receiver_baton rb;
+  if (kind == svn_node_unknown || kind == svn_node_none)
+    {
+      /* svn uses SVN_ERR_UNVERSIONED_RESOURCE as warning only
+         for this function. */
+      return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
+                               _("'%s' is not under version control"),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+    }
+
+  if (get_target_inherited_props)
+    {
+      apr_array_header_t *iprops;
 
-          rb.wc_ctx = ctx->wc_ctx;
-          rb.wrapped_receiver = receiver;
-          rb.wrapped_receiver_baton = receiver_baton;
+      SVN_ERR(svn_wc__get_iprops(&iprops, ctx->wc_ctx, local_abspath,
+                                 NULL, scratch_pool, scratch_pool));
+      SVN_ERR(call_receiver(path_or_url, NULL, iprops, receiver,
+                            receiver_baton, scratch_pool));
+    }
 
-          if (strcmp(path_or_url, local_abspath) != 0)
-            {
-              rb.anchor = path_or_url;
-              rb.anchor_abspath = local_abspath;
-            }
-          else
-            {
-              rb.anchor = NULL;
-              rb.anchor_abspath = NULL;
-            }
+  if (changelists && changelists->nelts)
+    SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash,
+                                       changelists, scratch_pool));
 
-          SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL,
-                                              depth, pristine, changelists,
-                                              recursive_proplist_receiver, &rb,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, pool));
+  /* Fetch, recursively or not. */
+  if (kind == svn_node_dir)
+    {
+      struct recursive_proplist_receiver_baton rb;
+
+      rb.wc_ctx = ctx->wc_ctx;
+      rb.wrapped_receiver = receiver;
+      rb.wrapped_receiver_baton = receiver_baton;
+
+      if (strcmp(path_or_url, local_abspath) != 0)
+        {
+          rb.anchor = path_or_url;
+          rb.anchor_abspath = local_abspath;
         }
-      else if (svn_wc__changelist_match(ctx->wc_ctx, local_abspath,
-                                        changelist_hash, pool))
+      else
         {
-          apr_hash_t *hash;
+          rb.anchor = NULL;
+          rb.anchor_abspath = NULL;
+        }
 
-          SVN_ERR(pristine_or_working_props(&hash, ctx->wc_ctx, local_abspath,
-                                            pristine, pool, pool));
-          SVN_ERR(call_receiver(path_or_url, hash,
-                                receiver, receiver_baton, pool));
+      SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL,
+                                          depth, pristine, changelists,
+                                          recursive_proplist_receiver, &rb,
+                                          ctx->cancel_func,
+                                          ctx->cancel_baton, result_pool));
+    }
+  else if (svn_wc__changelist_match(ctx->wc_ctx, local_abspath,
+                                    changelist_hash, scratch_pool))
+    {
+      apr_hash_t *hash;
+
+      SVN_ERR(pristine_or_working_props(&hash, ctx->wc_ctx, local_abspath,
+                                        pristine, result_pool,
+                                        scratch_pool));
+      SVN_ERR(call_receiver(path_or_url, hash, NULL,
+                            receiver, receiver_baton, scratch_pool));
 
-        }
     }
-  else /* remote target */
-    {
-      svn_ra_session_t *ra_session;
-      svn_node_kind_t kind;
-      apr_pool_t *subpool = svn_pool_create(pool);
-      svn_client__pathrev_t *loc;
+  return SVN_NO_ERROR;
+}
 
-      /* Get an RA session for this URL. */
-      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
-                                                path_or_url, NULL,
-                                                peg_revision,
-                                                revision, ctx, pool));
+svn_error_t *
+svn_client_proplist4(const char *path_or_url,
+                     const svn_opt_revision_t *peg_revision,
+                     const svn_opt_revision_t *revision,
+                     svn_depth_t depth,
+                     const apr_array_header_t *changelists,
+                     svn_boolean_t get_target_inherited_props,
+                     svn_proplist_receiver2_t receiver,
+                     void *receiver_baton,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  svn_boolean_t local_explicit_props;
+  svn_boolean_t local_iprops;
 
-      SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, pool));
+  peg_revision = svn_cl__rev_default_to_head_or_working(peg_revision,
+                                                        path_or_url);
+  revision = svn_cl__rev_default_to_peg(revision, peg_revision);
 
-      SVN_ERR(remote_proplist(loc->url, "", kind, loc->rev, ra_session, depth,
-                              receiver, receiver_baton, pool, subpool));
-      svn_pool_destroy(subpool);
+  if (depth == svn_depth_unknown)
+    depth = svn_depth_empty;
+
+  /* Are explicit props available locally? */
+  local_explicit_props =
+    (! svn_path_is_url(path_or_url)
+     && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
+     && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind));
+
+  /* If we want iprops are they avaiable locally? */
+  local_iprops =
+    (get_target_inherited_props /* We want iprops */
+     && local_explicit_props /* No local explicit props means no local iprops. */
+     && (peg_revision->kind == svn_opt_revision_working
+         || peg_revision->kind == svn_opt_revision_unspecified )
+     && (revision->kind == svn_opt_revision_working
+         || revision->kind == svn_opt_revision_unspecified ));
+
+  if ((get_target_inherited_props && !local_iprops)
+      || !local_explicit_props)
+    {
+      SVN_ERR(get_remote_props(path_or_url, peg_revision, revision, depth,
+                               !local_explicit_props,
+                               (get_target_inherited_props && !local_iprops),
+                               receiver, receiver_baton, ctx, result_pool,
+                               scratch_pool));
+    }
+
+  if (local_explicit_props)
+    {
+      SVN_ERR(get_local_props(path_or_url, revision, depth, changelists,
+                              local_iprops, receiver, receiver_baton, ctx,
+                              result_pool, scratch_pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c Sun Dec 23 18:34:14 2012
@@ -1151,6 +1151,13 @@ close_directory(void *dir_baton,
           const char *deleted_path = svn__apr_hash_index_key(hi);
           deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
 
+          /* Ignore paths which are not children of b->path.  (There
+             should be none due to editor ordering constraints, but
+             ra_serf drops the ball here -- see issue #3802 for
+             details.) */
+          if (! svn_relpath_skip_ancestor(b->path, deleted_path))
+            continue;
+
           notify = svn_wc_create_notify(deleted_path, dpn->action, pool);
           notify->kind = dpn->kind;
           notify->content_state = notify->prop_state = dpn->state;

Modified: subversion/branches/javahl-ra/subversion/libsvn_client/revisions.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/revisions.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/revisions.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/revisions.c Sun Dec 23 18:34:14 2012
@@ -96,7 +96,7 @@ svn_client__get_revision_number(svn_revn
                                            scratch_pool, scratch_pool);
 
         /* Return the same error as older code did (before and at r935091).
-           At least svn_client_proplist3 promises SVN_ERR_ENTRY_NOT_FOUND. */
+           At least svn_client_proplist4 promises SVN_ERR_ENTRY_NOT_FOUND. */
         if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
           {
             svn_error_clear(err);

Modified: subversion/branches/javahl-ra/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/switch.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/switch.c Sun Dec 23 18:34:14 2012
@@ -79,6 +79,8 @@ switch_internal(svn_revnum_t *result_rev
   svn_revnum_t revnum;
   svn_error_t *err = SVN_NO_ERROR;
   const char *diff3_cmd;
+  apr_hash_t *wcroot_iprops;
+  apr_array_header_t *inherited_props;
   svn_boolean_t use_commit_times;
   svn_boolean_t sleep_here = FALSE;
   svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
@@ -218,6 +220,62 @@ switch_internal(svn_revnum_t *result_rev
                                  svn_dirent_dirname(local_abspath, pool));
     }
 
+  wcroot_iprops = apr_hash_make(pool);
+  
+  /* Will the base of LOCAL_ABSPATH require an iprop cache post-switch?
+     If we are switching LOCAL_ABSPATH to the root of the repository then
+     we don't need to cache inherited properties.  In all other cases we
+     *might* need to cache iprops. */
+  if (strcmp(switch_loc->repos_root_url, switch_loc->url) != 0)
+    {
+      svn_boolean_t wc_root;
+      svn_boolean_t needs_iprop_cache = TRUE;
+
+      SVN_ERR(svn_wc__strictly_is_wc_root(&wc_root,
+                                          ctx->wc_ctx,
+                                          local_abspath,
+                                          pool));
+
+      /* Switching the WC root to anything but the repos root means
+         we need an iprop cache. */ 
+      if (!wc_root)
+        {
+          /* We know we are switching a subtree to something other than the
+             repos root, but if we are unswitching that subtree we don't
+             need an iprops cache. */
+          const char *target_parent_url;
+          const char *unswitched_url;
+
+          /* Calculate the URL LOCAL_ABSPATH would have if it was unswitched
+             relative to its parent. */
+          SVN_ERR(svn_wc__node_get_url(&target_parent_url, ctx->wc_ctx,
+                                       svn_dirent_dirname(local_abspath,
+                                                          pool),
+                                       pool, pool));
+          unswitched_url = svn_path_url_add_component2(
+            target_parent_url,
+            svn_dirent_basename(local_abspath, pool),
+            pool);
+
+          /* If LOCAL_ABSPATH will be unswitched relative to its parent, then
+             it doesn't need an iprop cache.  Note: It doesn't matter if
+             LOCAL_ABSPATH is withing a switched subtree, only if it's the
+             *root* of a switched subtree.*/
+          if (strcmp(unswitched_url, switch_loc->url) == 0)
+            needs_iprop_cache = FALSE;
+      }
+
+
+      if (needs_iprop_cache)
+        {
+          SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props,
+                                             "", switch_loc->rev, pool,
+                                             pool));
+          apr_hash_set(wcroot_iprops, local_abspath, APR_HASH_KEY_STRING,
+                       inherited_props);
+        }
+    }
+
   SVN_ERR(svn_ra_reparent(ra_session, anchor_url, pool));
 
   /* Fetch the switch (update) editor.  If REVISION is invalid, that's
@@ -231,8 +289,8 @@ switch_internal(svn_revnum_t *result_rev
 
   SVN_ERR(svn_wc__get_switch_editor(&switch_editor, &switch_edit_baton,
                                     &revnum, ctx->wc_ctx, anchor_abspath,
-                                    target, switch_loc->url, use_commit_times,
-                                    depth,
+                                    target, switch_loc->url, wcroot_iprops,
+                                    use_commit_times, depth,
                                     depth_is_sticky, allow_unver_obstructions,
                                     server_supports_depth,
                                     diff3_cmd, preserved_exts,

Modified: subversion/branches/javahl-ra/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/update.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/update.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/update.c Sun Dec 23 18:34:14 2012
@@ -201,6 +201,8 @@ update_internal(svn_revnum_t *result_rev
   svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
   svn_boolean_t clean_checkout = FALSE;
   const char *diff3_cmd;
+  apr_hash_t *wcroot_iprops;
+  svn_opt_revision_t opt_rev;
   svn_ra_session_t *ra_session;
   const char *preserved_exts_str;
   apr_array_header_t *preserved_exts;
@@ -211,6 +213,9 @@ update_internal(svn_revnum_t *result_rev
                                                  SVN_CONFIG_CATEGORY_CONFIG,
                                                  APR_HASH_KEY_STRING) : NULL;
 
+  if (result_rev)
+    *result_rev = SVN_INVALID_REVNUM;
+
   /* An unknown depth can't be sticky. */
   if (depth == svn_depth_unknown)
     depth_is_sticky = FALSE;
@@ -350,10 +355,18 @@ update_internal(svn_revnum_t *result_rev
       anchor_loc->url = corrected_url;
     }
 
+  /* Resolve unspecified REVISION now, because we need to retrieve the
+     correct inherited props prior to the editor drive and we need to
+     use the same value of HEAD for both. */
+  opt_rev.kind = revision->kind;
+  opt_rev.value = revision->value;
+  if (opt_rev.kind == svn_opt_revision_unspecified)
+    opt_rev.kind = svn_opt_revision_head;
+
   /* ### todo: shouldn't svn_client__get_revision_number be able
      to take a URL as easily as a local path?  */
   SVN_ERR(svn_client__get_revision_number(&revnum, NULL, ctx->wc_ctx,
-                                          local_abspath, ra_session, revision,
+                                          local_abspath, ra_session, &opt_rev,
                                           pool));
 
   SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
@@ -363,12 +376,31 @@ update_internal(svn_revnum_t *result_rev
   dfb.target_revision = revnum;
   dfb.anchor_url = anchor_loc->url;
 
+  err = svn_client__get_inheritable_props(&wcroot_iprops, local_abspath,
+                                          revnum, depth, ra_session, ctx,
+                                          pool, pool);
+
+  /* We might be trying to update to a non-existant path-rev. */
+  if (err)
+    {
+      if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
+        {
+          svn_error_clear(err);
+          err = NULL;
+        }
+      else
+        {
+          return svn_error_trace(err);
+        }
+    }
+
   /* Fetch the update editor.  If REVISION is invalid, that's okay;
      the RA driver will call editor->set_target_revision later on. */
   SVN_ERR(svn_wc__get_update_editor(&update_editor, &update_edit_baton,
                                     &revnum, ctx->wc_ctx, anchor_abspath,
-                                    target, use_commit_times, depth,
-                                    depth_is_sticky, allow_unver_obstructions,
+                                    target, wcroot_iprops, use_commit_times,
+                                    depth, depth_is_sticky,
+                                    allow_unver_obstructions,
                                     adds_as_modification,
                                     server_supports_depth,
                                     clean_checkout,

Modified: subversion/branches/javahl-ra/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_delta/compat.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_delta/compat.c Sun Dec 23 18:34:14 2012
@@ -1637,9 +1637,12 @@ apply_change(void **dir_baton,
                                                        change->copyfrom_path,
                                                        scratch_pool);
           else
-            /* ### prefix with "/" ?  */
             copyfrom_url = change->copyfrom_path;
 
+          /* Make this an FS path by prepending "/" */
+          if (copyfrom_url[0] != '/')
+            copyfrom_url = apr_pstrcat(scratch_pool, "/", copyfrom_url, NULL);
+
           copyfrom_rev = change->copyfrom_rev;
         }
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_delta/editor.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_delta/editor.c Sun Dec 23 18:34:14 2012
@@ -77,23 +77,23 @@ struct svn_editor_t
 #define END_CALLBACK(editor) ((editor)->within_callback = FALSE)
 
 /* Marker to indicate no further changes are allowed on this node.  */
-static const int marker_done;
+static const int marker_done = 0;
 #define MARKER_DONE (&marker_done)
 
 /* Marker indicating that add_* may be called for this path, or that it
    can be the destination of a copy or move. For copy/move, the path
    will switch to MARKER_ALLOW_ALTER, to enable further tweaks.  */
-static const int marker_allow_add;
+static const int marker_allow_add = 0;
 #define MARKER_ALLOW_ADD (&marker_allow_add)
 
 /* Marker indicating that alter_* may be called for this path.  */
-static const int marker_allow_alter;
+static const int marker_allow_alter = 0;
 #define MARKER_ALLOW_ALTER (&marker_allow_alter)
 
 /* Just like MARKER_DONE, but also indicates that the node was created
    via add_directory(). This allows us to verify that the CHILDREN param
    was comprehensive.  */
-static const int marker_added_dir;
+static const int marker_added_dir = 0;
 #define MARKER_ADDED_DIR (&marker_added_dir)
 
 #define MARK_FINISHED(editor) ((editor)->finished = TRUE)

Modified: subversion/branches/javahl-ra/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_delta/svndiff.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_delta/svndiff.c Sun Dec 23 18:34:14 2012
@@ -186,18 +186,86 @@ zlib_encode(const char *data,
 }
 
 static svn_error_t *
+send_simple_insertion_window(svn_txdelta_window_t *window,
+                             struct encoder_baton *eb)
+{
+  unsigned char headers[4 + 5 * MAX_ENCODED_INT_LEN + MAX_INSTRUCTION_LEN];
+  unsigned char ibuf[MAX_INSTRUCTION_LEN];
+  unsigned char *header_current;
+  apr_size_t header_len;
+  apr_size_t ip_len, i;
+  apr_size_t len = window->new_data->len;
+
+  /* there is only one target copy op. It must span the whole window */
+  assert(window->ops[0].action_code == svn_txdelta_new);
+  assert(window->ops[0].length == window->tview_len);
+  assert(window->ops[0].offset == 0);
+
+  /* write stream header if necessary */
+  if (eb->header_done == FALSE)
+    {
+      eb->header_done = TRUE;
+      headers[0] = 'S';
+      headers[1] = 'V';
+      headers[2] = 'N';
+      headers[3] = (unsigned char)eb->version;
+      header_current = headers + 4;
+    }
+  else
+    {
+      header_current = headers;
+    }
+    
+  /* Encode the action code and length.  */
+  if (window->tview_len >> 6 == 0)
+    {
+      ibuf[0] = (unsigned char)(window->tview_len + (0x2 << 6));
+      ip_len = 1;
+    }
+  else
+    {
+      ibuf[0] = (0x2 << 6);
+      ip_len = encode_int(ibuf + 1, window->tview_len) - ibuf;
+    }
+
+  /* encode the window header.  */
+  header_current[0] = 0;  /* source offset == 0 */
+  header_current[1] = 0;  /* source length == 0 */
+  header_current = encode_int(header_current + 2, window->tview_len);
+  header_current[0] = (unsigned char)ip_len;  /* 1 instruction */
+  header_current = encode_int(&header_current[1], len);
+
+  /* append instructions (1 to a handful of bytes) */
+  for (i = 0; i < ip_len; ++i)
+    header_current[i] = ibuf[i];
+
+  header_len = header_current - headers + ip_len;
+    
+  /* Write out the window.  */
+  SVN_ERR(svn_stream_write(eb->output, (const char *)headers, &header_len));
+  if (len)
+    SVN_ERR(svn_stream_write(eb->output, window->new_data->data, &len));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 window_handler(svn_txdelta_window_t *window, void *baton)
 {
   struct encoder_baton *eb = baton;
-  apr_pool_t *pool = svn_pool_create(eb->pool);
-  svn_stringbuf_t *instructions = svn_stringbuf_create_empty(pool);
-  svn_stringbuf_t *i1 = svn_stringbuf_create_empty(pool);
-  svn_stringbuf_t *header = svn_stringbuf_create_empty(pool);
+  apr_pool_t *pool;
+  svn_stringbuf_t *instructions;
+  svn_stringbuf_t *i1;
+  svn_stringbuf_t *header;
   const svn_string_t *newdata;
   unsigned char ibuf[MAX_INSTRUCTION_LEN], *ip;
   const svn_txdelta_op_t *op;
   apr_size_t len;
 
+  /* use specialized code if there is no source */
+  if (window && !window->src_ops && window->num_ops == 1 && !eb->version)
+    return svn_error_trace(send_simple_insertion_window(window, eb));
+
   /* Make sure we write the header.  */
   if (eb->header_done == FALSE)
     {
@@ -229,6 +297,12 @@ window_handler(svn_txdelta_window_t *win
       return svn_stream_close(output);
     }
 
+  /* create the necessary data buffers */
+  pool = svn_pool_create(eb->pool);
+  instructions = svn_stringbuf_create_empty(pool);
+  i1 = svn_stringbuf_create_empty(pool);
+  header = svn_stringbuf_create_empty(pool);
+
   /* Encode the instructions.  */
   for (op = window->ops; op < window->ops + window->num_ops; op++)
     {
@@ -450,7 +524,7 @@ decode_size(apr_size_t *val,
  */
 static svn_error_t *
 zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out,
-            apr_size_t limit, svn_boolean_t copyless_allowed)
+            apr_size_t limit)
 {
   apr_size_t len;
   const unsigned char *oldplace = in;
@@ -469,22 +543,10 @@ zlib_decode(const unsigned char *in, apr
   inLen -= (in - oldplace);
   if (inLen == len)
     {
-      if (copyless_allowed)
-        {
-          /* "in" is no longer used but the memory remains allocated for
-           * at least as long as "out" will be used by the caller.
-           */
-          out->data = (char *)in;
-          out->len = len;
-          out->blocksize = len; /* sic! */
-        }
-      else
-        {
-          svn_stringbuf_ensure(out, len);
-          memcpy(out->data, in, len);
-          out->data[len] = 0;
-          out->len = len;
-        }
+      svn_stringbuf_ensure(out, len);
+      memcpy(out->data, in, len);
+      out->data[len] = 0;
+      out->len = len;
 
       return SVN_NO_ERROR;
     }
@@ -661,9 +723,9 @@ decode_window(svn_txdelta_window_t *wind
       /* these may in fact simply return references to insend */
 
       SVN_ERR(zlib_decode(insend, newlen, ndout,
-                          SVN_DELTA_WINDOW_SIZE, TRUE));
+                          SVN_DELTA_WINDOW_SIZE));
       SVN_ERR(zlib_decode(data, insend - data, instout,
-                          MAX_INSTRUCTION_SECTION_LEN, TRUE));
+                          MAX_INSTRUCTION_SECTION_LEN));
 
       newlen = ndout->len;
       data = (unsigned char *)instout->data;
@@ -1008,8 +1070,7 @@ svn__compress(svn_string_t *in,
               svn_stringbuf_t *out,
               int compression_level)
 {
-  return zlib_encode(in->data, in->len, out,
-                     compression_level);
+  return zlib_encode(in->data, in->len, out, compression_level);
 }
 
 svn_error_t *
@@ -1017,6 +1078,5 @@ svn__decompress(svn_string_t *in,
                 svn_stringbuf_t *out,
                 apr_size_t limit)
 {
-  return zlib_decode((const unsigned char*)in->data, in->len, out, limit,
-                     FALSE);
+  return zlib_decode((const unsigned char*)in->data, in->len, out, limit);
 }

Modified: subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c Sun Dec 23 18:34:14 2012
@@ -998,3 +998,42 @@ svn_error_t *svn_txdelta_send_txstream(s
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_txdelta_send_contents(const unsigned char *contents,
+                          apr_size_t len,
+                          svn_txdelta_window_handler_t handler,
+                          void *handler_baton,
+                          apr_pool_t *pool)
+{
+  svn_string_t new_data;
+  svn_txdelta_op_t op = { svn_txdelta_new, 0, 0 };
+  svn_txdelta_window_t window = { 0, 0, 0, 1, 0 };
+  window.ops = &op;
+  window.new_data = &new_data;
+
+  /* send CONTENT as a series of max-sized windows */
+  while (len > 0)
+    {
+      /* stuff next chunk into the window */
+      window.tview_len = len < SVN_DELTA_WINDOW_SIZE
+                       ? len
+                       : SVN_DELTA_WINDOW_SIZE;
+      op.length = window.tview_len;
+      new_data.len = window.tview_len;
+      new_data.data = (const char*)contents;
+
+      /* update remaining */
+      contents += window.tview_len;
+      len -= window.tview_len;
+
+      /* shove it at the handler */
+      SVN_ERR((*handler)(&window, handler_baton));
+    }
+
+  /* indicate end of stream */
+  SVN_ERR((*handler)(NULL, handler_baton));
+
+  return SVN_NO_ERROR;
+}
+

Modified: subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c Sun Dec 23 18:34:14 2012
@@ -340,30 +340,17 @@ is_one_at_eof(struct file_info file[], a
 /* Quickly determine whether there is a eol char in CHUNK.
  * (mainly copy-n-paste from eol.c#svn_eol__find_eol_start).
  */
-#if SVN_UNALIGNED_ACCESS_IS_OK
-#if APR_SIZEOF_VOIDP == 8
-#  define LOWER_7BITS_SET 0x7f7f7f7f7f7f7f7f
-#  define BIT_7_SET       0x8080808080808080
-#  define R_MASK          0x0a0a0a0a0a0a0a0a
-#  define N_MASK          0x0d0d0d0d0d0d0d0d
-#else
-#  define LOWER_7BITS_SET 0x7f7f7f7f
-#  define BIT_7_SET       0x80808080
-#  define R_MASK          0x0a0a0a0a
-#  define N_MASK          0x0d0d0d0d
-#endif
-#endif
 
 #if SVN_UNALIGNED_ACCESS_IS_OK
 static svn_boolean_t contains_eol(apr_uintptr_t chunk)
 {
-  apr_uintptr_t r_test = chunk ^ R_MASK;
-  apr_uintptr_t n_test = chunk ^ N_MASK;
+  apr_uintptr_t r_test = chunk ^ SVN__R_MASK;
+  apr_uintptr_t n_test = chunk ^ SVN__N_MASK;
 
-  r_test |= (r_test & LOWER_7BITS_SET) + LOWER_7BITS_SET;
-  n_test |= (n_test & LOWER_7BITS_SET) + LOWER_7BITS_SET;
+  r_test |= (r_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
+  n_test |= (n_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
 
-  return (r_test & n_test & BIT_7_SET) != BIT_7_SET;
+  return (r_test & n_test & SVN__BIT_7_SET) != SVN__BIT_7_SET;
 }
 #endif
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c Sun Dec 23 18:34:14 2012
@@ -1204,6 +1204,27 @@ svn_fs_file_contents(svn_stream_t **cont
 }
 
 svn_error_t *
+svn_fs_try_process_file_contents(svn_boolean_t *success,
+                                 svn_fs_root_t *root,
+                                 const char *path,
+                                 svn_fs_process_contents_func_t processor,
+                                 void* baton,
+                                 apr_pool_t *pool)
+{
+  /* if the FS doesn't implement this function, report a "failed" attempt */
+  if (root->vtable->try_process_file_contents == NULL)
+    {
+      *success = FALSE;
+      return SVN_NO_ERROR;
+    }
+
+  return svn_error_trace(root->vtable->try_process_file_contents(
+                         success,
+                         root, path,
+                         processor, baton, pool));
+}
+
+svn_error_t *
 svn_fs_make_file(svn_fs_root_t *root, const char *path, apr_pool_t *pool)
 {
   SVN_ERR(svn_fs__path_valid(path, pool));

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h Sun Dec 23 18:34:14 2012
@@ -306,6 +306,12 @@ typedef struct root_vtable_t
   svn_error_t *(*file_contents)(svn_stream_t **contents,
                                 svn_fs_root_t *root, const char *path,
                                 apr_pool_t *pool);
+  svn_error_t *(*try_process_file_contents)(svn_boolean_t *success,
+                                            svn_fs_root_t *target_root,
+                                            const char *target_path,
+                                            svn_fs_process_contents_func_t processor,
+                                            void* baton,
+                                            apr_pool_t *pool);
   svn_error_t *(*make_file)(svn_fs_root_t *root, const char *path,
                             apr_pool_t *pool);
   svn_error_t *(*apply_textdelta)(svn_txdelta_window_handler_t *contents_p,

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c Sun Dec 23 18:34:14 2012
@@ -3676,7 +3676,7 @@ window_consumer(svn_txdelta_window_t *wi
       SVN_ERR(svn_stream_write(tb->target_stream,
                                tb->target_string->data,
                                &len));
-      svn_stringbuf_set(tb->target_string, "");
+      svn_stringbuf_setempty(tb->target_string);
     }
 
   /* Is the window NULL?  If so, we're done. */
@@ -5387,6 +5387,7 @@ static root_vtable_t root_vtable = {
   base_file_length,
   base_file_checksum,
   base_file_contents,
+  NULL,
   base_make_file,
   base_apply_textdelta,
   base_apply_text,

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c Sun Dec 23 18:34:14 2012
@@ -24,6 +24,7 @@
 #include "fs_fs.h"
 #include "id.h"
 #include "dag.h"
+#include "tree.h"
 #include "temp_serializer.h"
 #include "../libsvn_fs/fs-loader.h"
 
@@ -32,6 +33,8 @@
 
 #include "svn_private_config.h"
 #include "svn_hash.h"
+#include "svn_pools.h"
+
 #include "private/svn_debug.h"
 #include "private/svn_subr_private.h"
 
@@ -92,18 +95,34 @@ read_config(svn_memcache_t **memcache_p,
 }
 
 
-/* Implements svn_cache__error_handler_t */
+/* Implements svn_cache__error_handler_t
+ * This variant clears the error after logging it.
+ */
 static svn_error_t *
-warn_on_cache_errors(svn_error_t *err,
-                     void *baton,
-                     apr_pool_t *pool)
+warn_and_continue_on_cache_errors(svn_error_t *err,
+                                  void *baton,
+                                  apr_pool_t *pool)
 {
   svn_fs_t *fs = baton;
   (fs->warning)(fs->warning_baton, err);
   svn_error_clear(err);
+
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_cache__error_handler_t
+ * This variant logs the error and passes it on to the callers.
+ */
+static svn_error_t *
+warn_and_fail_on_cache_errors(svn_error_t *err,
+                              void *baton,
+                              apr_pool_t *pool)
+{
+  svn_fs_t *fs = baton;
+  (fs->warning)(fs->warning_baton, err);
+  return err;
+}
+
 #ifdef SVN_DEBUG_CACHE_DUMP_STATS
 /* Baton to be used for the dump_cache_statistics() pool cleanup function, */
 struct dump_cache_baton_t
@@ -162,13 +181,12 @@ dump_cache_statistics(void *baton_void)
  * not transaction-specific CACHE object in FS, if CACHE is not NULL.
  *
  * All these svn_cache__t instances shall be handled uniformly. Unless
- * NO_HANDLER is true, register an error handler that reports errors
- * as warnings for the given CACHE.
+ * ERROR_HANDLER is NULL, register it for the given CACHE in FS.
  */
 static svn_error_t *
 init_callbacks(svn_cache__t *cache,
                svn_fs_t *fs,
-               svn_boolean_t no_handler,
+               svn_cache__error_handler_t error_handler,
                apr_pool_t *pool)
 {
   if (cache != NULL)
@@ -190,9 +208,9 @@ init_callbacks(svn_cache__t *cache,
                                 apr_pool_cleanup_null);
 #endif
 
-      if (! no_handler)
+      if (error_handler)
         SVN_ERR(svn_cache__set_error_handler(cache,
-                                             warn_on_cache_errors,
+                                             error_handler,
                                              fs,
                                              pool));
 
@@ -207,6 +225,9 @@ init_callbacks(svn_cache__t *cache,
  * MEMBUFFER are NULL and pages is non-zero.  Sets *CACHE_P to NULL
  * otherwise.
  *
+ * Unless NO_HANDLER is true, register an error handler that reports errors
+ * as warnings to the FS warning callback.
+ * 
  * Cache is allocated in POOL.
  * */
 static svn_error_t *
@@ -219,32 +240,43 @@ create_cache(svn_cache__t **cache_p,
              svn_cache__deserialize_func_t deserializer,
              apr_ssize_t klen,
              const char *prefix,
+             svn_fs_t *fs,
+             svn_boolean_t no_handler,
              apr_pool_t *pool)
 {
-    if (memcache)
-      {
-        SVN_ERR(svn_cache__create_memcache(cache_p, memcache,
-                                           serializer, deserializer, klen,
-                                           prefix, pool));
-      }
-    else if (membuffer)
-      {
-        SVN_ERR(svn_cache__create_membuffer_cache(
-                  cache_p, membuffer, serializer, deserializer,
-                  klen, prefix, FALSE, pool));
-      }
-    else if (pages)
-      {
-        SVN_ERR(svn_cache__create_inprocess(
-                  cache_p, serializer, deserializer, klen, pages,
-                  items_per_page, FALSE, prefix, pool));
-      }
-    else
+  svn_cache__error_handler_t error_handler = no_handler
+                                           ? NULL
+                                           : warn_and_fail_on_cache_errors;
+
+  if (memcache)
+    {
+      SVN_ERR(svn_cache__create_memcache(cache_p, memcache,
+                                         serializer, deserializer, klen,
+                                         prefix, pool));
+      error_handler = no_handler
+                    ? NULL
+                    : warn_and_continue_on_cache_errors;
+    }
+  else if (membuffer)
+    {
+      SVN_ERR(svn_cache__create_membuffer_cache(
+                cache_p, membuffer, serializer, deserializer,
+                klen, prefix, FALSE, pool));
+    }
+  else if (pages)
+    {
+      SVN_ERR(svn_cache__create_inprocess(
+                cache_p, serializer, deserializer, klen, pages,
+                items_per_page, FALSE, prefix, pool));
+    }
+  else
     {
       *cache_p = NULL;
     }
 
-    return SVN_NO_ERROR;
+  SVN_ERR(init_callbacks(*cache_p, fs, error_handler, pool));
+
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -290,10 +322,10 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        svn_fs_fs__deserialize_id,
                        sizeof(svn_revnum_t),
                        apr_pstrcat(pool, prefix, "RRI", (char *)NULL),
+                       fs,
+                       no_handler,
                        fs->pool));
 
-  SVN_ERR(init_callbacks(ffd->rev_root_id_cache, fs, no_handler, pool));
-
   /* Rough estimate: revision DAG nodes have size around 320 bytes, so
    * let's put 16 on a page. */
   SVN_ERR(create_cache(&(ffd->rev_node_cache),
@@ -304,9 +336,12 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        svn_fs_fs__dag_deserialize,
                        APR_HASH_KEY_STRING,
                        apr_pstrcat(pool, prefix, "DAG", (char *)NULL),
+                       fs,
+                       no_handler,
                        fs->pool));
 
-  SVN_ERR(init_callbacks(ffd->rev_node_cache, fs, no_handler, pool));
+  /* 1st level DAG node cache */
+  ffd->dag_node_cache = svn_fs_fs__create_dag_cache(pool);
 
   /* Very rough estimate: 1K per directory. */
   SVN_ERR(create_cache(&(ffd->dir_cache),
@@ -317,10 +352,10 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        svn_fs_fs__deserialize_dir_entries,
                        APR_HASH_KEY_STRING,
                        apr_pstrcat(pool, prefix, "DIR", (char *)NULL),
+                       fs,
+                       no_handler,
                        fs->pool));
 
-  SVN_ERR(init_callbacks(ffd->dir_cache, fs, no_handler, pool));
-
   /* Only 16 bytes per entry (a revision number + the corresponding offset).
      Since we want ~8k pages, that means 512 entries per page. */
   SVN_ERR(create_cache(&(ffd->packed_offset_cache),
@@ -332,12 +367,37 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        sizeof(svn_revnum_t),
                        apr_pstrcat(pool, prefix, "PACK-MANIFEST",
                                    (char *)NULL),
+                       fs,
+                       no_handler,
                        fs->pool));
 
-  SVN_ERR(init_callbacks(ffd->packed_offset_cache, fs, no_handler, pool));
+  /* initialize node revision cache, if caching has been enabled */
+  SVN_ERR(create_cache(&(ffd->node_revision_cache),
+                       NULL,
+                       membuffer,
+                       0, 0, /* Do not use inprocess cache */
+                       svn_fs_fs__serialize_node_revision,
+                       svn_fs_fs__deserialize_node_revision,
+                       sizeof(pair_cache_key_t),
+                       apr_pstrcat(pool, prefix, "NODEREVS", (char *)NULL),
+                       fs,
+                       no_handler,
+                       fs->pool));
 
-  /* initialize fulltext cache as configured */
-  ffd->fulltext_cache = NULL;
+  /* initialize node change list cache, if caching has been enabled */
+  SVN_ERR(create_cache(&(ffd->changes_cache),
+                       NULL,
+                       membuffer,
+                       0, 0, /* Do not use inprocess cache */
+                       svn_fs_fs__serialize_changes,
+                       svn_fs_fs__deserialize_changes,
+                       sizeof(svn_revnum_t),
+                       apr_pstrcat(pool, prefix, "CHANGES", (char *)NULL),
+                       fs,
+                       no_handler,
+                       fs->pool));
+
+  /* if enabled, cache fulltext and other derived information */
   if (cache_fulltexts)
     {
       SVN_ERR(create_cache(&(ffd->fulltext_cache),
@@ -346,12 +406,58 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                            0, 0, /* Do not use inprocess cache */
                            /* Values are svn_stringbuf_t */
                            NULL, NULL,
-                           APR_HASH_KEY_STRING,
+                           sizeof(pair_cache_key_t),
                            apr_pstrcat(pool, prefix, "TEXT", (char *)NULL),
+                           fs,
+                           no_handler,
+                           fs->pool));
+      
+      SVN_ERR(create_cache(&(ffd->properties_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use inprocess cache */
+                           svn_fs_fs__serialize_properties,
+                           svn_fs_fs__deserialize_properties,
+                           sizeof(pair_cache_key_t),
+                           apr_pstrcat(pool, prefix, "PROP",
+                                       (char *)NULL),
+                           fs,
+                           no_handler,
+                           fs->pool));
+      
+      SVN_ERR(create_cache(&(ffd->mergeinfo_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use inprocess cache */
+                           svn_fs_fs__serialize_mergeinfo,
+                           svn_fs_fs__deserialize_mergeinfo,
+                           APR_HASH_KEY_STRING,
+                           apr_pstrcat(pool, prefix, "MERGEINFO",
+                                       (char *)NULL),
+                           fs,
+                           no_handler,
+                           fs->pool));
+      
+      SVN_ERR(create_cache(&(ffd->mergeinfo_existence_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use inprocess cache */
+                           /* Values are svn_stringbuf_t */
+                           NULL, NULL,
+                           APR_HASH_KEY_STRING,
+                           apr_pstrcat(pool, prefix, "HAS_MERGEINFO",
+                                       (char *)NULL),
+                           fs,
+                           no_handler,
                            fs->pool));
     }
-
-  SVN_ERR(init_callbacks(ffd->fulltext_cache, fs, no_handler, pool));
+  else
+    {
+      ffd->fulltext_cache = NULL;
+      ffd->properties_cache = NULL;
+      ffd->mergeinfo_cache = NULL;
+      ffd->mergeinfo_existence_cache = NULL;
+    }
 
   /* initialize revprop cache, if full-text caching has been enabled */
   if (cache_revprops)
@@ -362,9 +468,11 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                            0, 0, /* Do not use inprocess cache */
                            svn_fs_fs__serialize_properties,
                            svn_fs_fs__deserialize_properties,
-                           APR_HASH_KEY_STRING,
+                           sizeof(pair_cache_key_t),
                            apr_pstrcat(pool, prefix, "REVPROP",
                                        (char *)NULL),
+                           fs,
+                           no_handler,
                            fs->pool));
     }
   else
@@ -372,9 +480,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
       ffd->revprop_cache = NULL;
     }
 
-  SVN_ERR(init_callbacks(ffd->revprop_cache, fs, no_handler, pool));
-
-  /* initialize txdelta window cache, if that has been enabled */
+  /* if enabled, cache text deltas and their combinations */
   if (cache_txdeltas)
     {
       SVN_ERR(create_cache(&(ffd->txdelta_window_cache),
@@ -386,18 +492,10 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                            APR_HASH_KEY_STRING,
                            apr_pstrcat(pool, prefix, "TXDELTA_WINDOW",
                                        (char *)NULL),
+                           fs,
+                           no_handler,
                            fs->pool));
-    }
-  else
-    {
-      ffd->txdelta_window_cache = NULL;
-    }
-
-  SVN_ERR(init_callbacks(ffd->txdelta_window_cache, fs, no_handler, pool));
 
-  /* initialize txdelta window cache, if that has been enabled */
-  if (cache_txdeltas)
-    {
       SVN_ERR(create_cache(&(ffd->combined_window_cache),
                            NULL,
                            membuffer,
@@ -407,41 +505,16 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                            APR_HASH_KEY_STRING,
                            apr_pstrcat(pool, prefix, "COMBINED_WINDOW",
                                        (char *)NULL),
+                           fs,
+                           no_handler,
                            fs->pool));
     }
   else
     {
+      ffd->txdelta_window_cache = NULL;
       ffd->combined_window_cache = NULL;
     }
 
-  SVN_ERR(init_callbacks(ffd->combined_window_cache, fs, no_handler, pool));
-
-  /* initialize node revision cache, if caching has been enabled */
-  SVN_ERR(create_cache(&(ffd->node_revision_cache),
-                       NULL,
-                       membuffer,
-                       0, 0, /* Do not use inprocess cache */
-                       svn_fs_fs__serialize_node_revision,
-                       svn_fs_fs__deserialize_node_revision,
-                       APR_HASH_KEY_STRING,
-                       apr_pstrcat(pool, prefix, "NODEREVS", (char *)NULL),
-                       fs->pool));
-
-  SVN_ERR(init_callbacks(ffd->node_revision_cache, fs, no_handler, pool));
-
-  /* initialize node change list cache, if caching has been enabled */
-  SVN_ERR(create_cache(&(ffd->changes_cache),
-                       NULL,
-                       membuffer,
-                       0, 0, /* Do not use inprocess cache */
-                       svn_fs_fs__serialize_changes,
-                       svn_fs_fs__deserialize_changes,
-                       sizeof(svn_revnum_t),
-                       apr_pstrcat(pool, prefix, "CHANGES", (char *)NULL),
-                       fs->pool));
-
-  SVN_ERR(init_callbacks(ffd->changes_cache, fs, no_handler, pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -535,6 +608,8 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
                        APR_HASH_KEY_STRING,
                        apr_pstrcat(pool, prefix, "TXNDIR",
                                    (char *)NULL),
+                       fs,
+                       TRUE,
                        pool));
 
   /* reset the transaction-specific cache if the pool gets cleaned up. */

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c Sun Dec 23 18:34:14 2012
@@ -947,6 +947,24 @@ svn_fs_fs__dag_get_file_delta_stream(svn
 
 
 svn_error_t *
+svn_fs_fs__dag_try_process_file_contents(svn_boolean_t *success,
+                                         dag_node_t *node,
+                                         svn_fs_process_contents_func_t processor,
+                                         void* baton,
+                                         apr_pool_t *pool)
+{
+  node_revision_t *noderev;
+
+  /* Go get fresh node-revisions for the nodes. */
+  SVN_ERR(get_node_revision(&noderev, node));
+
+  return svn_fs_fs__try_process_file_contents(success, node->fs,
+                                              noderev,
+                                              processor, baton, pool);
+}
+
+
+svn_error_t *
 svn_fs_fs__dag_file_length(svn_filesize_t *length,
                            dag_node_t *file,
                            apr_pool_t *pool)

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.h?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.h Sun Dec 23 18:34:14 2012
@@ -403,6 +403,19 @@ svn_error_t *svn_fs_fs__dag_get_contents
                                          dag_node_t *file,
                                          apr_pool_t *pool);
 
+/* Attempt to fetch the contents of NODE and pass it along with the BATON
+   to the PROCESSOR.   Set *SUCCESS only of the data could be provided
+   and the processor had been called.
+
+   Use POOL for all allocations.
+ */
+svn_error_t *
+svn_fs_fs__dag_try_process_file_contents(svn_boolean_t *success,
+                                         dag_node_t *node,
+                                         svn_fs_process_contents_func_t processor,
+                                         void* baton,
+                                         apr_pool_t *pool);
+
 
 /* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into
    the contents of TARGET, allocated in POOL.  If SOURCE is null, the empty

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h?rev=1425508&r1=1425507&r2=1425508&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h Sun Dec 23 18:34:14 2012
@@ -217,6 +217,17 @@ typedef struct fs_fs_shared_data_t
   apr_pool_t *common_pool;
 } fs_fs_shared_data_t;
 
+/* Data structure for the 1st level DAG node cache. */
+typedef struct fs_fs_dag_cache_t fs_fs_dag_cache_t;
+
+/* Key type for all caches that use revision + offset / counter as key. */
+typedef struct pair_cache_key_t
+{
+  svn_revnum_t revision;
+
+  apr_int64_t second;
+} pair_cache_key_t;
+
 /* Private (non-shared) FSFS-specific data for each svn_fs_t object.
    Any caches in here may be NULL. */
 typedef struct fs_fs_data_t
@@ -241,8 +252,11 @@ typedef struct fs_fs_data_t
      (svn_fs_id_t *).  (Not threadsafe.) */
   svn_cache__t *rev_root_id_cache;
 
+  /* Caches native dag_node_t* instances and acts as a 1st level cache */
+  fs_fs_dag_cache_t *dag_node_cache;
+
   /* DAG node cache for immutable nodes.  Maps (revision, fspath)
-     to (dag_node_t *). */
+     to (dag_node_t *). This is the 2nd level cache for DAG nodes. */
   svn_cache__t *rev_node_cache;
 
   /* A cache of the contents of immutable directories; maps from
@@ -269,6 +283,9 @@ typedef struct fs_fs_data_t
   /* Revision property cache.  Maps from (rev,generation) to apr_hash_t. */
   svn_cache__t *revprop_cache;
 
+  /* Node properties cache.  Maps from rep key to apr_hash_t. */
+  svn_cache__t *properties_cache;
+
   /* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to
      a manifest; and a manifest is a mapping from (svn_revnum_t) revision
      number offset within a shard to (apr_off_t) byte-offset in the
@@ -289,6 +306,15 @@ typedef struct fs_fs_data_t
      is the revision */
   svn_cache__t *changes_cache;
 
+  /* Cache for svn_mergeinfo_t objects; the key is a combination of
+     revision, inheritance flags and path. */
+  svn_cache__t *mergeinfo_cache;
+
+  /* Cache for presence of svn_mergeinfo_t on a noderev; the key is a
+     combination of revision, inheritance flags and path; value is "1"
+     if the node has mergeinfo, "0" if it doesn't. */
+  svn_cache__t *mergeinfo_existence_cache;
+
   /* If set, there are or have been more than one concurrent transaction */
   svn_boolean_t concurrent_transactions;