subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pbu...@apache.org
Subject svn commit: r1394915 [3/7] - in /subversion/branches/inheritable-props: ./ build/ build/ac-macros/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/bindings/swig/perl/libsvn_swig_perl/ subversion/bindings/swig/perl/native/ subvers...
Date Sat, 06 Oct 2012 03:59:38 GMT
Modified: subversion/branches/inheritable-props/subversion/include/svn_ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/svn_ra_svn.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/svn_ra_svn.h (original)
+++ subversion/branches/inheritable-props/subversion/include/svn_ra_svn.h Sat Oct  6 03:59:33 2012
@@ -64,6 +64,8 @@ extern "C" {
 #define SVN_RA_SVN_CAP_ATOMIC_REVPROPS "atomic-revprops"
 /* maps to SVN_RA_CAPABILITY_INHERITED_PROPERTIES: */
 #define SVN_RA_SVN_CAP_INHERITED_PROPS "inherited-props"
+/* maps to SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS */
+#define SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS "ephemeral-txnprops"
 
 /** ra_svn passes @c svn_dirent_t fields over the wire as a list of
  * words, these are the values used to represent each field.
@@ -160,6 +162,64 @@ typedef struct svn_ra_svn_item_t
 typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton);
 
 /**
+ * List of all commands supported by the SVN:// protocol.
+ *
+ * @since New in 1.8
+ */
+typedef enum svn_ra_svn_cmd_t
+{
+  svn_ra_svn_cmd_target_rev,
+  svn_ra_svn_cmd_open_root,
+  svn_ra_svn_cmd_delete_entry,
+  svn_ra_svn_cmd_add_dir,
+  svn_ra_svn_cmd_open_dir,
+  svn_ra_svn_cmd_change_dir_prop,
+  svn_ra_svn_cmd_close_dir,
+  svn_ra_svn_cmd_absent_dir,
+  svn_ra_svn_cmd_add_file,
+  svn_ra_svn_cmd_open_file,
+  svn_ra_svn_cmd_change_file_prop,
+  svn_ra_svn_cmd_close_file,
+  svn_ra_svn_cmd_absent_file,
+  svn_ra_svn_cmd_textdelta_chunk,
+  svn_ra_svn_cmd_textdelta_end,
+  svn_ra_svn_cmd_apply_textdelta,
+  svn_ra_svn_cmd_close_edit,
+  svn_ra_svn_cmd_abort_edit,
+  
+  svn_ra_svn_cmd_set_path,
+  svn_ra_svn_cmd_delete_path,
+  svn_ra_svn_cmd_link_path,
+  svn_ra_svn_cmd_finish_report,
+  svn_ra_svn_cmd_abort_report,
+
+  svn_ra_svn_cmd_reparent,
+  svn_ra_svn_cmd_get_latest_rev,
+  svn_ra_svn_cmd_get_dated_rev,
+  svn_ra_svn_cmd_change_rev_prop2,
+  svn_ra_svn_cmd_change_rev_prop,
+  svn_ra_svn_cmd_rev_proplist,
+  svn_ra_svn_cmd_rev_prop,
+  svn_ra_svn_cmd_get_file,
+  svn_ra_svn_cmd_update,
+  svn_ra_svn_cmd_switch,
+  svn_ra_svn_cmd_status,
+  svn_ra_svn_cmd_diff,
+  svn_ra_svn_cmd_check_path,
+  svn_ra_svn_cmd_stat,
+  svn_ra_svn_cmd_get_file_revs,
+  svn_ra_svn_cmd_lock,
+  svn_ra_svn_cmd_unlock,
+  svn_ra_svn_cmd_get_lock,
+  svn_ra_svn_cmd_get_locks,
+  svn_ra_svn_cmd_replay,
+  svn_ra_svn_cmd_replay_range,
+  svn_ra_svn_cmd_get_deleted_rev,
+
+  svn_ra_svn_cmd__last
+} svn_ra_svn_cmd_t;
+
+/**
  * Set the shim callbacks to be used by @a conn to @a shim_callbacks.
  *
  * @note This is a private API, external consumers should not use it.
@@ -172,10 +232,32 @@ svn_ra_svn__set_shim_callbacks(svn_ra_sv
  * input/output files.
  *
  * Either @a sock or @a in_file/@a out_file must be set, not both.
- * Specify the desired network data compression level (zlib) from
- * 0 (no compression) to 9 (best but slowest).
+ * @a compression_level specifies the desired network data compression
+ * level (zlib) from 0 (no compression) to 9 (best but slowest).
+ *
+ * To reduce the overhead of checking for cancellation requests from the
+ * data receiver, set @a error_check_interval to some non-zero value.
+ * It defines the number of bytes that must have been sent since the last
+ * check before the next check will be made.
+ *
+ * Allocate the result in @a pool.
+ *
+ * @since New in 1.8
+ */
+svn_ra_svn_conn_t *svn_ra_svn_create_conn3(apr_socket_t *sock,
+                                           apr_file_t *in_file,
+                                           apr_file_t *out_file,
+                                           int compression_level,
+                                           apr_size_t zero_copy_limit,
+                                           apr_size_t error_check_interval,
+                                           apr_pool_t *pool);
+
+/** Similar to svn_ra_svn_create_conn3() but disables the zero copy code
+ * path and sets the error checking interval to 0.
  *
  * @since New in 1.7.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
 svn_ra_svn_conn_t *
 svn_ra_svn_create_conn2(apr_socket_t *sock,
@@ -184,7 +266,7 @@ svn_ra_svn_create_conn2(apr_socket_t *so
                         int compression_level,
                         apr_pool_t *pool);
 
-/** Similar to svn_ra_svn_create_conn2() but uses default
+/** Similar to svn_ra_svn_create_conn2() but uses the default
  * compression level (#SVN_DELTA_COMPRESSION_LEVEL_DEFAULT) for network
  * transmissions.
  *
@@ -221,6 +303,13 @@ svn_ra_svn_has_capability(svn_ra_svn_con
 int
 svn_ra_svn_compression_level(svn_ra_svn_conn_t *conn);
 
+/** Return the zero-copy data block limit to use for network transmissions
+ *
+ * @since New in 1.8.
+ */
+apr_size_t
+svn_ra_svn_zero_copy_limit(svn_ra_svn_conn_t *conn);
+
 /** Returns the remote address of the connection as a string, if known,
  *  or NULL if inapplicable. */
 const char *
@@ -450,13 +539,28 @@ svn_ra_svn_handle_commands(svn_ra_svn_co
 
 /** Write a command over the network, using the same format string notation
  * as svn_ra_svn_write_tuple().
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
+ * Use svn_ra_svn_write_templated_cmd instead.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_ra_svn_write_cmd(svn_ra_svn_conn_t *conn,
                      apr_pool_t *pool,
                      const char *cmdname,
                      const char *fmt, ...);
 
+/** Write a command of type @a cmd over the network connection @a conn.
+ * The parameters to be provided are command-specific.  @a pool will be
+ * used for allocations.
+ * 
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_ra_svn_write_templated_cmd(svn_ra_svn_conn_t *conn,
+                               apr_pool_t *pool,
+                               svn_ra_svn_cmd_t cmd, ...);
+
 /** Write a successful command response over the network, using the
  * same format string notation as svn_ra_svn_write_tuple().  Do not use
  * partial tuples with this function; if you need to use partial

Modified: subversion/branches/inheritable-props/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/svn_repos.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/svn_repos.h (original)
+++ subversion/branches/inheritable-props/subversion/include/svn_repos.h Sat Oct  6 03:59:33 2012
@@ -842,6 +842,13 @@ svn_repos_hooks_setenv(svn_repos_t *repo
  * avoid sending data through @a editor/@a edit_baton which is not
  * authorized for transmission.
  *
+ * @a zero_copy_limit controls up to which size in bytes data blocks may
+ * be sent using the zero-copy code path.  On that path, a number of
+ * in-memory copy operations have been eliminated to maximize throughput.
+ * However, until the whole block has been pushed to the network stack,
+ * other clients may get blocked.  Thus, be careful when using larger
+ * values here.  0 disables the optimization.
+ *
  * All allocation for the context and collected state will occur in
  * @a pool.
  *
@@ -874,7 +881,33 @@ svn_repos_hooks_setenv(svn_repos_t *repo
  * than or equal to the depth of the working copy, then the editor
  * operations will affect only paths at or above @a depth.
  *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_repos_begin_report3(void **report_baton,
+                        svn_revnum_t revnum,
+                        svn_repos_t *repos,
+                        const char *fs_base,
+                        const char *target,
+                        const char *tgt_path,
+                        svn_boolean_t text_deltas,
+                        svn_depth_t depth,
+                        svn_boolean_t ignore_ancestry,
+                        svn_boolean_t send_copyfrom_args,
+                        const svn_delta_editor_t *editor,
+                        void *edit_baton,
+                        svn_repos_authz_func_t authz_read_func,
+                        void *authz_read_baton,
+                        apr_size_t zero_copy_limit,
+                        apr_pool_t *pool);
+
+/**
+ * The same as svn_repos_begin_report3(), but setting the @a zero_copy_limit
+ * to 0.
+ *
  * @since New in 1.5.
+ * 
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
 svn_error_t *
 svn_repos_begin_report2(void **report_baton,
@@ -926,7 +959,7 @@ svn_repos_begin_report(void **report_bat
 
 
 /**
- * Given a @a report_baton constructed by svn_repos_begin_report2(),
+ * Given a @a report_baton constructed by svn_repos_begin_report3(),
  * record the presence of @a path, at @a revision with depth @a depth,
  * in the current tree.
  *
@@ -997,7 +1030,7 @@ svn_repos_set_path(void *report_baton,
                    apr_pool_t *pool);
 
 /**
- * Given a @a report_baton constructed by svn_repos_begin_report2(),
+ * Given a @a report_baton constructed by svn_repos_begin_report3(),
  * record the presence of @a path in the current tree, containing the contents
  * of @a link_path at @a revision with depth @a depth.
  *
@@ -1063,7 +1096,7 @@ svn_repos_link_path(void *report_baton,
                     svn_boolean_t start_empty,
                     apr_pool_t *pool);
 
-/** Given a @a report_baton constructed by svn_repos_begin_report2(),
+/** Given a @a report_baton constructed by svn_repos_begin_report3(),
  * record the non-existence of @a path in the current tree.
  *
  * @a path may not be underneath a path on which svn_repos_set_path3()
@@ -1079,7 +1112,7 @@ svn_repos_delete_path(void *report_baton
                       const char *path,
                       apr_pool_t *pool);
 
-/** Given a @a report_baton constructed by svn_repos_begin_report2(),
+/** Given a @a report_baton constructed by svn_repos_begin_report3(),
  * finish the report and drive the editor as specified when the report
  * baton was constructed.
  *
@@ -1096,7 +1129,7 @@ svn_repos_finish_report(void *report_bat
                         apr_pool_t *pool);
 
 
-/** Given a @a report_baton constructed by svn_repos_begin_report2(),
+/** Given a @a report_baton constructed by svn_repos_begin_report3(),
  * abort the report.  This function can be called anytime before
  * svn_repos_finish_report() is called.
  *
@@ -1170,7 +1203,7 @@ svn_repos_abort_report(void *report_bato
  * the total size of the delta.
  *
  * ### svn_repos_dir_delta2 is mostly superseded by the reporter
- * ### functionality (svn_repos_begin_report2 and friends).
+ * ### functionality (svn_repos_begin_report3 and friends).
  * ### svn_repos_dir_delta2 does allow the roots to be transaction
  * ### roots rather than just revision roots, and it has the
  * ### entry_props flag.  Almost all of Subversion's own code uses the
@@ -2316,7 +2349,7 @@ svn_repos_fs_change_txn_props(svn_fs_txn
  * @{
  *
  * As it turns out, the svn_repos_replay2(), svn_repos_dir_delta2() and
- * svn_repos_begin_report2() interfaces can be extremely useful for
+ * svn_repos_begin_report3() interfaces can be extremely useful for
  * examining the repository, or more exactly, changes to the repository.
  * These drivers allows for differences between two trees to be
  * described using an editor.
@@ -2369,7 +2402,7 @@ typedef struct svn_repos_node_t
  * repos's filesystem.
  *
  * The editor can also be driven by svn_repos_dir_delta2() or
- * svn_repos_begin_report2(), but unless you have special needs,
+ * svn_repos_begin_report3(), but unless you have special needs,
  * svn_repos_replay2() is preferred.
  *
  * Invoke svn_repos_node_from_baton() on @a edit_baton to obtain the root

Modified: subversion/branches/inheritable-props/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/svn_wc.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/svn_wc.h (original)
+++ subversion/branches/inheritable-props/subversion/include/svn_wc.h Sat Oct  6 03:59:33 2012
@@ -3851,7 +3851,7 @@ typedef struct svn_wc_status2_t
 
 
 /**
- * Same as #svn_wc_status2_t, but without the #svn_lock_t 'repos_lock' field.
+ * Same as #svn_wc_status2_t, but without the #svn_lock_t 'repos_lock', const char 'url', #svn_revnum_t 'ood_last_cmt_rev', apr_time_t 'ood_last_cmt_date', #svn_node_kind_t 'ood_kind', const char 'ood_last_cmt_author', #svn_wc_conflict_description_t 'tree_conflict', #svn_boolean_t 'file_external', #svn_wc_status_kind 'pristine_text_status', and #svn_wc_status_kind 'pristine_prop_status' fields.
  *
  * @deprecated Provided for backward compatibility with the 1.1 API.
  */
@@ -3989,11 +3989,6 @@ svn_wc_status(svn_wc_status_t **status,
  *
  * @a scratch_pool will be cleared between invocations to the callback.
  *
- * ### we might be revamping the status infrastructure, and this callback
- * ### could totally disappear by the end of 1.7 development. however, we
- * ### need to mark the STATUS parameter as "const" so that it is easier
- * ### to reason about who/what can modify those structures.
- *
  * @since New in 1.7.
  */
 typedef svn_error_t *(*svn_wc_status_func4_t)(void *baton,
@@ -4410,6 +4405,8 @@ svn_wc_copy(const char *src,
  * Use @a scratch_pool for temporary allocations.
  *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
+ * @see svn_client_move7()
  */
 svn_error_t *
 svn_wc_move(svn_wc_context_t *wc_ctx,

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/add.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/add.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/add.c Sat Oct  6 03:59:33 2012
@@ -671,6 +671,9 @@ svn_client_add4(const char *path,
   const char *parent_abspath;
   const char *local_abspath;
   const char *existing_parent_abspath;
+  svn_node_kind_t disk_kind;
+  svn_boolean_t is_wc_root = FALSE;
+  svn_error_t *err;
 
   if (svn_path_is_url(path))
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -678,6 +681,38 @@ svn_client_add4(const char *path,
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
+  /* See if we're being asked to add a wc-root.  That's typically not
+     okay, unless we're in "force" mode.  We'll check the node kind
+     first, because wc-roots must be directories.  But also,
+     svn_wc_is_wc_root2() will return TRUE even if LOCAL_ABSPATH is a
+     *symlink* to a working copy root, which is a scenario we want to
+     treat differently.  */
+  SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, pool));
+  if (disk_kind == svn_node_dir)
+    {
+      err = svn_wc_is_wc_root2(&is_wc_root, ctx->wc_ctx,
+                               local_abspath, pool);
+      if (err)
+        {
+          if (err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
+            {
+              svn_error_clear(err);
+              err = SVN_NO_ERROR;
+              is_wc_root = FALSE;
+            }
+          else
+            {
+              return err;
+            }
+        }
+    }
+  if (is_wc_root && (! force))
+    {
+      return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,
+                               _("'%s' is already under version control"),
+                               svn_dirent_local_style(local_abspath, pool));
+    }
+  
   /* ### this is a hack.
      ### before we switched to absolute paths, if a user tried to do
      ### 'svn add .', PATH would be "" and PARENT_PATH would also be "",
@@ -708,7 +743,9 @@ svn_client_add4(const char *path,
     add(local_abspath, depth, force, no_ignore, existing_parent_abspath,
         ctx, pool),
     ctx->wc_ctx,
-    existing_parent_abspath ? existing_parent_abspath : parent_abspath,
+    is_wc_root ? local_abspath
+               : (existing_parent_abspath ? existing_parent_abspath 
+                                          : parent_abspath),
     FALSE /* lock_anchor */, pool);
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/client.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/client.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/client.h Sat Oct  6 03:59:33 2012
@@ -217,40 +217,6 @@ svn_client__get_youngest_common_ancestor
                                          apr_pool_t *result_pool,
                                          apr_pool_t *scratch_pool);
 
-/* Given PATH_OR_URL, which contains either a working copy path or an
-   absolute URL, a peg revision PEG_REVISION, and a desired revision
-   REVISION, create an RA connection to that object as it exists in
-   that revision, following copy history if necessary.  If REVISION is
-   younger than PEG_REVISION, then PATH_OR_URL will be checked to see
-   that it is the same node in both PEG_REVISION and REVISION.  If it
-   is not, then @c SVN_ERR_CLIENT_UNRELATED_RESOURCES is returned.
-
-   BASE_DIR_ABSPATH is the working copy path the ra_session corresponds to,
-   and should only be used if PATH_OR_URL is a url
-     ### else NULL? what's it for?
-
-   If PEG_REVISION->kind is 'unspecified', the peg revision is 'head'
-   for a URL or 'working' for a WC path.  If REVISION->kind is
-   'unspecified', the operative revision is the peg revision.
-
-   Store the resulting ra_session in *RA_SESSION_P.  Store the final
-   resolved location of the object in *RESOLVED_LOC_P.  RESOLVED_LOC_P
-   may be NULL if not wanted.
-
-   Use authentication baton cached in CTX to authenticate against the
-   repository.
-
-   Use POOL for all allocations. */
-svn_error_t *
-svn_client__ra_session_from_path2(svn_ra_session_t **ra_session_p,
-                                 svn_client__pathrev_t **resolved_loc_p,
-                                 const char *path_or_url,
-                                 const char *base_dir_abspath,
-                                 const svn_opt_revision_t *peg_revision,
-                                 const svn_opt_revision_t *revision,
-                                 svn_client_ctx_t *ctx,
-                                 apr_pool_t *pool);
-
 /* Ensure that RA_SESSION's session URL matches SESSION_URL,
    reparenting that session if necessary.
    Store the previous session URL in *OLD_SESSION_URL (so that if the
@@ -1061,21 +1027,6 @@ svn_client__get_shim_callbacks(svn_wc_co
                                apr_hash_t *relpath_map,
                                apr_pool_t *result_pool);
 
-/* Return true if KIND is a revision kind that is dependent on the working
- * copy. Otherwise, return false. */
-#define SVN_CLIENT__REVKIND_NEEDS_WC(kind)                                 \
-  ((kind) == svn_opt_revision_base ||                                      \
-   (kind) == svn_opt_revision_previous ||                                  \
-   (kind) == svn_opt_revision_working ||                                   \
-   (kind) == svn_opt_revision_committed)                                   \
-
-/* Return true if KIND is a revision kind that the WC can supply without
- * contacting the repository. Otherwise, return false. */
-#define SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(kind)                           \
-  ((kind) == svn_opt_revision_base ||                                      \
-   (kind) == svn_opt_revision_working ||                                   \
-   (kind) == svn_opt_revision_committed)
-
 /* Return REVISION unless its kind is 'unspecified' in which case return
  * a pointer to a statically allocated revision structure of kind 'head'
  * if PATH_OR_URL is a URL or 'base' if it is a WC path. */

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/commit.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/commit.c Sat Oct  6 03:59:33 2012
@@ -1770,9 +1770,16 @@ svn_client_commit6(const apr_array_heade
   cb.info = &commit_info;
   cb.pool = pool;
 
+  /* Get the RA editor from the first lock target, rather than BASE_ABSPATH.
+   * When committing from multiple WCs, BASE_ABSPATH might be an unrelated
+   * parent of nested working copies. We don't support commits to multiple
+   * repositories so using the first WC to get the RA session is safe. */
   cmt_err = svn_error_trace(
               svn_client__open_ra_session_internal(&ra_session, NULL, base_url,
-                                                   base_abspath, commit_items,
+                                                   APR_ARRAY_IDX(lock_targets,
+                                                                 0,
+                                                                 const char *),
+                                                   commit_items,
                                                    TRUE, FALSE, ctx, pool));
 
   if (cmt_err)

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/copy.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/copy.c Sat Oct  6 03:59:33 2012
@@ -244,6 +244,7 @@ do_wc_to_wc_moves_with_locks2(svn_client
                               const char *dst_parent_abspath,
                               svn_boolean_t lock_src,
                               svn_boolean_t lock_dst,
+                              svn_boolean_t allow_mixed_revisions,
                               svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
@@ -252,11 +253,12 @@ do_wc_to_wc_moves_with_locks2(svn_client
   dst_abspath = svn_dirent_join(dst_parent_abspath, pair->base_name,
                                 scratch_pool);
 
-  SVN_ERR(svn_wc_move(ctx->wc_ctx, pair->src_abspath_or_url,
-                     dst_abspath, FALSE /* metadata_only */,
-                     ctx->cancel_func, ctx->cancel_baton,
-                     ctx->notify_func2, ctx->notify_baton2,
-                     scratch_pool));
+  SVN_ERR(svn_wc__move2(ctx->wc_ctx, pair->src_abspath_or_url,
+                        dst_abspath, FALSE /* metadata_only */,
+                        allow_mixed_revisions,
+                        ctx->cancel_func, ctx->cancel_baton,
+                        ctx->notify_func2, ctx->notify_baton2,
+                        scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -267,17 +269,20 @@ do_wc_to_wc_moves_with_locks1(svn_client
                               const char *dst_parent_abspath,
                               svn_boolean_t lock_src,
                               svn_boolean_t lock_dst,
+                              svn_boolean_t allow_mixed_revisions,
                               svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
   if (lock_dst)
     SVN_WC__CALL_WITH_WRITE_LOCK(
       do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src,
-                                    lock_dst, ctx, scratch_pool),
+                                    lock_dst, allow_mixed_revisions, ctx,
+                                    scratch_pool),
       ctx->wc_ctx, dst_parent_abspath, FALSE, scratch_pool);
   else
     SVN_ERR(do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src,
-                                          lock_dst, ctx, scratch_pool));
+                                          lock_dst, allow_mixed_revisions,
+                                          ctx, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -287,6 +292,7 @@ do_wc_to_wc_moves_with_locks1(svn_client
 static svn_error_t *
 do_wc_to_wc_moves(const apr_array_header_t *copy_pairs,
                   const char *dst_path,
+                  svn_boolean_t allow_mixed_revisions,
                   svn_client_ctx_t *ctx,
                   apr_pool_t *pool)
 {
@@ -341,13 +347,15 @@ do_wc_to_wc_moves(const apr_array_header
       if (lock_src)
         SVN_WC__CALL_WITH_WRITE_LOCK(
           do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
-                                        lock_src, lock_dst, ctx, iterpool),
+                                        lock_src, lock_dst,
+                                        allow_mixed_revisions, ctx, iterpool),
           ctx->wc_ctx, src_parent_abspath,
           FALSE, iterpool);
       else
         SVN_ERR(do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
-                                              lock_src, lock_dst, ctx,
-                                              iterpool));
+                                              lock_src, lock_dst,
+                                              allow_mixed_revisions,
+                                              ctx, iterpool));
 
     }
   svn_pool_destroy(iterpool);
@@ -1856,6 +1864,7 @@ static svn_error_t *
 try_copy(const apr_array_header_t *sources,
          const char *dst_path_in,
          svn_boolean_t is_move,
+         svn_boolean_t allow_mixed_revisions,
          svn_boolean_t make_parents,
          svn_boolean_t ignore_externals,
          const apr_hash_t *revprop_table,
@@ -2145,8 +2154,9 @@ try_copy(const apr_array_header_t *sourc
 
       /* Copy or move all targets. */
       if (is_move)
-        return svn_error_trace(do_wc_to_wc_moves(copy_pairs, dst_path_in, ctx,
-                                                 pool));
+        return svn_error_trace(do_wc_to_wc_moves(copy_pairs, dst_path_in,
+                                                 allow_mixed_revisions,
+                                                 ctx, pool));
       else
         return svn_error_trace(do_wc_to_wc_copies(copy_pairs, ctx, pool));
     }
@@ -2195,6 +2205,7 @@ svn_client_copy6(const apr_array_header_
 
   err = try_copy(sources, dst_path,
                  FALSE /* is_move */,
+                 TRUE /* allow_mixed_revisions */,
                  make_parents,
                  ignore_externals,
                  revprop_table,
@@ -2226,6 +2237,7 @@ svn_client_copy6(const apr_array_header_
                                                        subpool)
                          : svn_dirent_join(dst_path, src_basename, subpool),
                      FALSE /* is_move */,
+                     TRUE /* allow_mixed_revisions */,
                      make_parents,
                      ignore_externals,
                      revprop_table,
@@ -2240,10 +2252,11 @@ svn_client_copy6(const apr_array_header_
 
 
 svn_error_t *
-svn_client_move6(const apr_array_header_t *src_paths,
+svn_client_move7(const apr_array_header_t *src_paths,
                  const char *dst_path,
                  svn_boolean_t move_as_child,
                  svn_boolean_t make_parents,
+                 svn_boolean_t allow_mixed_revisions,
                  const apr_hash_t *revprop_table,
                  svn_commit_callback2_t commit_callback,
                  void *commit_baton,
@@ -2277,6 +2290,7 @@ svn_client_move6(const apr_array_header_
 
   err = try_copy(sources, dst_path,
                  TRUE /* is_move */,
+                 allow_mixed_revisions,
                  make_parents,
                  FALSE,
                  revprop_table,
@@ -2307,6 +2321,7 @@ svn_client_move6(const apr_array_header_
                                                        src_basename, pool)
                          : svn_dirent_join(dst_path, src_basename, pool),
                      TRUE /* is_move */,
+                     allow_mixed_revisions,
                      make_parents,
                      FALSE,
                      revprop_table,

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/deprecated.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/deprecated.c Sat Oct  6 03:59:33 2012
@@ -699,6 +699,25 @@ svn_client_copy(svn_client_commit_info_t
 }
 
 svn_error_t *
+svn_client_move6(const apr_array_header_t *src_paths,
+                 const char *dst_path,
+                 svn_boolean_t move_as_child,
+                 svn_boolean_t make_parents,
+                 const apr_hash_t *revprop_table,
+                 svn_commit_callback2_t commit_callback,
+                 void *commit_baton,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *pool)
+{
+  return svn_error_trace(svn_client_move7(src_paths, dst_path,
+                                          move_as_child, make_parents,
+                                          TRUE, /* allow_mixed_revisions */
+                                          revprop_table,
+                                          commit_callback, commit_baton,
+                                          ctx, pool));
+}
+
+svn_error_t *
 svn_client_move5(svn_commit_info_t **commit_info_p,
                  const apr_array_header_t *src_paths,
                  const char *dst_path,

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/merge.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/merge.c Sat Oct  6 03:59:33 2012
@@ -1607,8 +1607,8 @@ merge_file_changed(svn_wc_notify_state_t
      way svn_wc_merge5() can do the merge. */
   if (wc_kind != svn_node_file || is_deleted)
     {
-      const char *moved_to_abspath;
-      svn_error_t *err;
+      svn_boolean_t moved_away;
+      svn_wc_conflict_reason_t reason;
 
       /* Maybe the node is excluded via depth filtering? */
 
@@ -1638,44 +1638,23 @@ merge_file_changed(svn_wc_notify_state_t
       /* This is use case 4 described in the paper attached to issue
        * #2282.  See also notes/tree-conflicts/detection.txt
        */
-      err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
-                                        ctx->wc_ctx, local_abspath,
-                                        scratch_pool, scratch_pool);
-      if (err)
-        {
-          if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-            {
-              svn_error_clear(err);
-              moved_to_abspath = NULL;
-            }
-          else
-            return svn_error_trace(err);
-        }
-
-      if (moved_to_abspath)
-        {
-          /* File has been moved away locally -- apply incoming
-           * changes at the new location. */
-          local_abspath = moved_to_abspath;
-        }
+      SVN_ERR(check_moved_away(&moved_away, ctx->wc_ctx,
+                               local_abspath, scratch_pool));
+      if (moved_away)
+        reason = svn_wc_conflict_reason_moved_away;
+      else if (is_deleted)
+        reason = svn_wc_conflict_reason_deleted;
       else
-        {
-          svn_wc_conflict_reason_t reason;
-
-          if (is_deleted)
-            reason = svn_wc_conflict_reason_deleted;
-          else
-            reason = svn_wc_conflict_reason_missing;
-          SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file,
-                                svn_wc_conflict_action_edit, reason));
-          if (tree_conflicted)
-            *tree_conflicted = TRUE;
-          if (content_state)
-            *content_state = svn_wc_notify_state_missing;
-          if (prop_state)
-            *prop_state = svn_wc_notify_state_missing;
-          return SVN_NO_ERROR;
-        }
+        reason = svn_wc_conflict_reason_missing;
+      SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file,
+                            svn_wc_conflict_action_edit, reason));
+      if (tree_conflicted)
+        *tree_conflicted = TRUE;
+      if (content_state)
+        *content_state = svn_wc_notify_state_missing;
+      if (prop_state)
+        *prop_state = svn_wc_notify_state_missing;
+      return SVN_NO_ERROR;
     }
 
   /* ### TODO: Thwart attempts to merge into a path that has
@@ -11813,4 +11792,4 @@ svn_client__symmetric_merge_get_location
   if (target)
     *target = svn_client__pathrev_dup(merge->target, result_pool);
   return SVN_NO_ERROR;
-}
\ No newline at end of file
+}

Modified: subversion/branches/inheritable-props/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_client/repos_diff.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_client/repos_diff.c Sat Oct  6 03:59:33 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/inheritable-props/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_delta/svndiff.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_delta/svndiff.c Sat Oct  6 03:59:33 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] = 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++)
     {

Modified: subversion/branches/inheritable-props/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_delta/text_delta.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_delta/text_delta.c Sat Oct  6 03:59:33 2012
@@ -998,3 +998,40 @@ 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, &op, &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/inheritable-props/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs/fs-loader.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs/fs-loader.c Sat Oct  6 03:59:33 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/inheritable-props/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs/fs-loader.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs/fs-loader.h Sat Oct  6 03:59:33 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/inheritable-props/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_base/tree.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_base/tree.c Sat Oct  6 03:59:33 2012
@@ -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/inheritable-props/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/caching.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/caching.c Sat Oct  6 03:59:33 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,10 +367,10 @@ 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 fulltext cache as configured */
   ffd->fulltext_cache = NULL;
   if (cache_fulltexts)
@@ -346,12 +381,33 @@ 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(init_callbacks(ffd->fulltext_cache, fs, no_handler, pool));
+  /* initialize node properties cache, if that has been enabled */
+  if (cache_fulltexts)
+    {
+      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));
+    }
+  else
+    {
+      ffd->properties_cache = NULL;
+    }
 
   /* initialize revprop cache, if full-text caching has been enabled */
   if (cache_revprops)
@@ -362,9 +418,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,8 +430,6 @@ 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 (cache_txdeltas)
     {
@@ -386,6 +442,8 @@ 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
@@ -393,8 +451,6 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
       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)
     {
@@ -407,6 +463,8 @@ 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
@@ -414,8 +472,6 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
       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,
@@ -425,10 +481,10 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        svn_fs_fs__deserialize_node_revision,
                        APR_HASH_KEY_STRING,
                        apr_pstrcat(pool, prefix, "NODEREVS", (char *)NULL),
+                       fs,
+                       no_handler, 
                        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,
@@ -438,10 +494,10 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        svn_fs_fs__deserialize_changes,
                        sizeof(svn_revnum_t),
                        apr_pstrcat(pool, prefix, "CHANGES", (char *)NULL),
+                       fs,
+                       no_handler,
                        fs->pool));
 
-  SVN_ERR(init_callbacks(ffd->changes_cache, fs, no_handler, pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -535,6 +591,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/inheritable-props/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/dag.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/dag.c Sat Oct  6 03:59:33 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/inheritable-props/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/dag.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/dag.h Sat Oct  6 03:59:33 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/inheritable-props/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs.h Sat Oct  6 03:59:33 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

Modified: subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c Sat Oct  6 03:59:33 2012
@@ -3366,12 +3366,10 @@ parse_revprop(apr_hash_t **properties,
   SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, pool));
   if (has_revprop_cache(fs, pool))
     {
-      const char *key;
+      pair_cache_key_t key = {revision, generation};
       fs_fs_data_t *ffd = fs->fsap_data;
 
-      key = svn_fs_fs__combine_two_numbers(revision, generation,
-                                           scratch_pool);
-      SVN_ERR(svn_cache__set(ffd->revprop_cache, key, *properties,
+      SVN_ERR(svn_cache__set(ffd->revprop_cache, &key, *properties,
                              scratch_pool));
     }
 
@@ -3670,13 +3668,13 @@ get_revision_proplist(apr_hash_t **propl
   if (has_revprop_cache(fs, pool))
     {
       svn_boolean_t is_cached;
-      const char *key;
+      pair_cache_key_t key = { rev, 0};
 
       SVN_ERR(read_revprop_generation(&generation, fs, pool));
 
-      key = svn_fs_fs__combine_two_numbers(rev, generation, pool);
+      key.second = generation;
       SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
-                             ffd->revprop_cache, key, pool));
+                             ffd->revprop_cache, &key, pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
@@ -4364,7 +4362,7 @@ struct rep_read_baton
 
   /* The key for the fulltext cache for this rep, if there is a
      fulltext cache. */
-  const char *fulltext_cache_key;
+  pair_cache_key_t fulltext_cache_key;
   /* The text we've been reading, if we're going to cache it. */
   svn_stringbuf_t *current_fulltext;
 
@@ -4555,11 +4553,15 @@ set_cached_combined_window(svn_stringbuf
    ID, and representation REP.
    Also, set *WINDOW_P to the base window content for *LIST, if it
    could be found in cache. Otherwise, *LIST will contain the base
-   representation for the whole delta chain.  */
+   representation for the whole delta chain.
+   Finally, return the expanded size of the representation in 
+   *EXPANDED_SIZE. It will take care of cases where only the on-disk
+   size is known.  */
 static svn_error_t *
 build_rep_list(apr_array_header_t **list,
                svn_stringbuf_t **window_p,
                struct rep_state **src_state,
+               svn_filesize_t *expanded_size,
                svn_fs_t *fs,
                representation_t *first_rep,
                apr_pool_t *pool)
@@ -4574,10 +4576,24 @@ build_rep_list(apr_array_header_t **list
   *list = apr_array_make(pool, 1, sizeof(struct rep_state *));
   rep = *first_rep;
 
+  /* The value as stored in the data struct.
+     0 is either for unknown length or actually zero length. */
+  *expanded_size = first_rep->expanded_size;
   while (1)
     {
       SVN_ERR(create_rep_state(&rs, &rep_args, &last_file,
                                &last_revision, &rep, fs, pool));
+
+      /* Unknown size or empty representation?
+         That implies the this being the first iteration.
+         Usually size equals on-disk size, except for empty,
+         compressed representations (delta, size = 4).
+         Please note that for all non-empty deltas have
+         a 4-byte header _plus_ some data. */
+      if (*expanded_size == 0)
+        if (! rep_args->is_delta || first_rep->size != 4)
+          *expanded_size = first_rep->size;
+        
       SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool));
       if (is_cached)
         {
@@ -4621,7 +4637,7 @@ static svn_error_t *
 rep_read_get_baton(struct rep_read_baton **rb_p,
                    svn_fs_t *fs,
                    representation_t *rep,
-                   const char *fulltext_cache_key,
+                   pair_cache_key_t fulltext_cache_key,
                    apr_pool_t *pool)
 {
   struct rep_read_baton *b;
@@ -4634,23 +4650,23 @@ rep_read_get_baton(struct rep_read_baton
   b->md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool);
   b->checksum_finalized = FALSE;
   b->md5_checksum = svn_checksum_dup(rep->md5_checksum, pool);
-  b->len = rep->expanded_size ? rep->expanded_size : rep->size;
+  b->len = rep->expanded_size;
   b->off = 0;
   b->fulltext_cache_key = fulltext_cache_key;
   b->pool = svn_pool_create(pool);
   b->filehandle_pool = svn_pool_create(pool);
 
-  if (fulltext_cache_key)
+  SVN_ERR(build_rep_list(&b->rs_list, &b->base_window,
+                         &b->src_state, &b->len, fs, rep,
+                         b->filehandle_pool));
+
+  if (SVN_IS_VALID_REVNUM(fulltext_cache_key.revision))
     b->current_fulltext = svn_stringbuf_create_ensure
                             ((apr_size_t)b->len,
                              b->filehandle_pool);
   else
     b->current_fulltext = NULL;
 
-  SVN_ERR(build_rep_list(&b->rs_list, &b->base_window,
-                         &b->src_state, fs, rep,
-                         b->filehandle_pool));
-
   /* Save our output baton. */
   *rb_p = b;
 
@@ -4935,7 +4951,7 @@ rep_read_contents(void *baton,
   if (rb->off == rb->len && rb->current_fulltext)
     {
       fs_fs_data_t *ffd = rb->fs->fsap_data;
-      SVN_ERR(svn_cache__set(ffd->fulltext_cache, rb->fulltext_cache_key,
+      SVN_ERR(svn_cache__set(ffd->fulltext_cache, &rb->fulltext_cache_key,
                              rb->current_fulltext, rb->pool));
       rb->current_fulltext = NULL;
     }
@@ -4966,7 +4982,7 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      const char *fulltext_cache_key = NULL;
+      pair_cache_key_t fulltext_cache_key = {rep->revision, rep->offset};
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
@@ -4975,11 +4991,8 @@ read_representation(svn_stream_t **conte
         {
           svn_stringbuf_t *fulltext;
           svn_boolean_t is_cached;
-          fulltext_cache_key = svn_fs_fs__combine_two_numbers(rep->revision,
-                                                              rep->offset,
-                                                              pool);
           SVN_ERR(svn_cache__get((void **) &fulltext, &is_cached,
-                                 ffd->fulltext_cache, fulltext_cache_key,
+                                 ffd->fulltext_cache, &fulltext_cache_key,
                                  pool));
           if (is_cached)
             {
@@ -4987,6 +5000,8 @@ read_representation(svn_stream_t **conte
               return SVN_NO_ERROR;
             }
         }
+      else
+        fulltext_cache_key.revision = SVN_INVALID_REVNUM;
 
       SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_cache_key, pool));
 
@@ -5095,6 +5110,70 @@ svn_fs_fs__get_file_delta_stream(svn_txd
   return SVN_NO_ERROR;
 }
 
+/* Baton for cache_access_wrapper. Wraps the original parameters of
+ * svn_fs_fs__try_process_file_content().
+ */
+typedef struct cache_access_wrapper_baton_t
+{
+  svn_fs_process_contents_func_t func;
+  void* baton;
+} cache_access_wrapper_baton_t;
+
+/* Wrapper to translate between svn_fs_process_contents_func_t and
+ * svn_cache__partial_getter_func_t.
+ */
+static svn_error_t *
+cache_access_wrapper(void **out,
+                     const void *data,
+                     apr_size_t data_len,
+                     void *baton,
+                     apr_pool_t *pool)
+{
+  cache_access_wrapper_baton_t *wrapper_baton = baton;
+
+  SVN_ERR(wrapper_baton->func((const unsigned char *)data,
+                              data_len - 1, /* cache adds terminating 0 */
+                              wrapper_baton->baton,
+                              pool));
+  
+  /* non-NULL value to signal the calling cache that all went well */
+  *out = baton;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__try_process_file_contents(svn_boolean_t *success,
+                                     svn_fs_t *fs,
+                                     node_revision_t *noderev,
+                                     svn_fs_process_contents_func_t processor,
+                                     void* baton,
+                                     apr_pool_t *pool)
+{
+  representation_t *rep = noderev->data_rep;
+  if (rep)
+    {
+      fs_fs_data_t *ffd = fs->fsap_data;
+      pair_cache_key_t fulltext_cache_key = {rep->revision, rep->offset};
+
+      if (ffd->fulltext_cache && SVN_IS_VALID_REVNUM(rep->revision)
+          && fulltext_size_is_cachable(ffd, rep->expanded_size))
+        {
+          cache_access_wrapper_baton_t wrapper_baton = {processor, baton};
+          void *dummy = NULL;
+
+          return svn_cache__get_partial(&dummy, success,
+                                        ffd->fulltext_cache,
+                                        &fulltext_cache_key,
+                                        cache_access_wrapper,
+                                        &wrapper_baton,
+                                        pool);
+        }
+    }
+
+  *success = FALSE;
+  return SVN_NO_ERROR;
+}
 
 /* Fetch the contents of a directory into ENTRIES.  Values are stored
    as filename to string mappings; further conversion is necessary to
@@ -5365,11 +5444,10 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
   apr_hash_t *proplist;
   svn_stream_t *stream;
 
-  proplist = apr_hash_make(pool);
-
   if (noderev->prop_rep && noderev->prop_rep->txn_id)
     {
       const char *filename = path_txn_node_props(fs, noderev->id, pool);
+      proplist = apr_hash_make(pool);
 
       SVN_ERR(svn_stream_open_readonly(&stream, filename, pool, pool));
       SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool));
@@ -5377,9 +5455,31 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
     }
   else if (noderev->prop_rep)
     {
+      fs_fs_data_t *ffd = fs->fsap_data;
+      representation_t *rep = noderev->prop_rep;
+      
+      pair_cache_key_t key = { rep->revision, rep->offset };
+      if (ffd->properties_cache && SVN_IS_VALID_REVNUM(rep->revision))
+        {
+          svn_boolean_t is_cached;
+          SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
+                                 ffd->properties_cache, &key, pool));
+          if (is_cached)
+            return SVN_NO_ERROR;
+        }
+
+      proplist = apr_hash_make(pool);
       SVN_ERR(read_representation(&stream, fs, noderev->prop_rep, pool));
       SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool));
       SVN_ERR(svn_stream_close(stream));
+      
+      if (ffd->properties_cache && SVN_IS_VALID_REVNUM(rep->revision))
+        SVN_ERR(svn_cache__set(ffd->properties_cache, &key, proplist, pool));
+    }
+  else
+    {
+      /* return an empty prop list if the node doesn't have any props */
+      proplist = apr_hash_make(pool);
     }
 
   *proplist_p = proplist;
@@ -6532,25 +6632,20 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
   if (!rep || !rep->txn_id)
     {
       const char *unique_suffix;
+      apr_hash_t *entries;
 
-      {
-        apr_hash_t *entries;
-
-        svn_pool_clear(subpool);
-
-        /* Before we can modify the directory, we need to dump its old
-           contents into a mutable representation file. */
-        SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, parent_noderev,
-                                            subpool));
-        SVN_ERR(unparse_dir_entries(&entries, entries, subpool));
-        SVN_ERR(svn_io_file_open(&file, filename,
-                                 APR_WRITE | APR_CREATE | APR_BUFFERED,
-                                 APR_OS_DEFAULT, pool));
-        out = svn_stream_from_aprfile2(file, TRUE, pool);
-        SVN_ERR(svn_hash_write2(entries, out, SVN_HASH_TERMINATOR, subpool));
+      /* Before we can modify the directory, we need to dump its old
+         contents into a mutable representation file. */
+      SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, parent_noderev,
+                                          subpool));
+      SVN_ERR(unparse_dir_entries(&entries, entries, subpool));
+      SVN_ERR(svn_io_file_open(&file, filename,
+                               APR_WRITE | APR_CREATE | APR_BUFFERED,
+                               APR_OS_DEFAULT, pool));
+      out = svn_stream_from_aprfile2(file, TRUE, pool);
+      SVN_ERR(svn_hash_write2(entries, out, SVN_HASH_TERMINATOR, subpool));
 
-        svn_pool_clear(subpool);
-      }
+      svn_pool_clear(subpool);
 
       /* Mark the node-rev's data rep as mutable. */
       rep = apr_pcalloc(pool, sizeof(*rep));
@@ -6571,7 +6666,6 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
     }
 
   /* if we have a directory cache for this transaction, update it */
-  svn_pool_clear(subpool);
   if (ffd->txn_dir_cache)
     {
       /* build parameters: (name, new entry) pair */

Modified: subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h?rev=1394915&r1=1394914&r2=1394915&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h Sat Oct  6 03:59:33 2012
@@ -150,6 +150,20 @@ svn_error_t *svn_fs_fs__get_contents(svn
                                      node_revision_t *noderev,
                                      apr_pool_t *pool);
 
+/* Attempt to fetch the text representation of node-revision NODEREV as
+   seen in filesystem FS and pass it along with the BATON to the PROCESSOR.
+   Set *SUCCESS only of the data could be provided and the processing
+   had been called.
+   Use POOL for all allocations.
+ */
+svn_error_t *
+svn_fs_fs__try_process_file_contents(svn_boolean_t *success,
+                                     svn_fs_t *fs,
+                                     node_revision_t *noderev,
+                                     svn_fs_process_contents_func_t processor,
+                                     void* baton,
+                                     apr_pool_t *pool);
+
 /* Set *STREAM_P to a delta stream turning the contents of the file SOURCE into
    the contents of the file TARGET, allocated in POOL.
    If SOURCE is null, the empty string will be used. */



Mime
View raw message