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,
+ ©_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,
+ ©_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;