You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2012/10/06 18:40:58 UTC
svn commit: r1395109 [2/3] - in /subversion/trunk: ./ subversion/include/
subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_ra/
subversion/libsvn_ra_local/ subversion/libsvn_ra_serf/
subversion/libsvn_ra_svn/ subversion/libsvn_rep...
Modified: subversion/trunk/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Sat Oct 6 16:40:55 2012
@@ -200,7 +200,10 @@ update_internal(svn_revnum_t *result_rev
svn_boolean_t sleep_here = FALSE;
svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
svn_boolean_t clean_checkout = FALSE;
+ svn_boolean_t is_not_present;
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;
@@ -353,10 +356,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,
@@ -366,12 +377,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,
@@ -431,6 +461,19 @@ update_internal(svn_revnum_t *result_rev
ctx, pool));
}
+ /* Cache inherited props. */
+ err = svn_wc__node_is_status_not_present(&is_not_present, ctx->wc_ctx,
+ local_abspath, pool);
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ err = SVN_NO_ERROR;
+ is_not_present = TRUE;
+ }
+
if (sleep_here)
svn_io_sleep_for_timestamps(local_abspath, pool);
Modified: subversion/trunk/subversion/libsvn_ra/compat.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/compat.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/compat.c (original)
+++ subversion/trunk/subversion/libsvn_ra/compat.c Sat Oct 6 16:40:55 2012
@@ -871,3 +871,90 @@ svn_ra__get_deleted_rev_from_log(svn_ra_
*revision_deleted = log_path_deleted_baton.revision_deleted;
return SVN_NO_ERROR;
}
+
+
+svn_error_t *
+svn_ra__get_inherited_props_walk(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ apr_array_header_t **inherited_props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *repos_root_url;
+ const char *session_url;
+ const char *parent_url;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+ *inherited_props =
+ apr_array_make(result_pool, 1, sizeof(svn_prop_inherited_item_t *));
+
+ /* Walk to the root of the repository getting inherited
+ props for PATH. */
+ SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, scratch_pool));
+ SVN_ERR(svn_ra_get_session_url(session, &session_url, scratch_pool));
+ parent_url = session_url;
+
+ while (strcmp(repos_root_url, parent_url))
+ {
+ apr_hash_index_t *hi;
+ apr_hash_t *parent_props;
+ apr_hash_t *final_hash = apr_hash_make(result_pool);
+ svn_error_t *err;
+
+ svn_pool_clear(iterpool);
+ parent_url = svn_uri_dirname(parent_url, iterpool);
+ SVN_ERR(svn_ra_reparent(session, parent_url, iterpool));
+ err = session->vtable->get_dir(session, NULL, NULL,
+ &parent_props, "",
+ revision, SVN_DIRENT_ALL,
+ iterpool);
+
+ /* If the user doesn't have read access to a parent path then
+ skip, but allow them to inherit from further up. */
+ if (err)
+ {
+ if ((err->apr_err == SVN_ERR_RA_NOT_AUTHORIZED)
+ || (err->apr_err == SVN_ERR_RA_DAV_FORBIDDEN))
+ {
+ svn_error_clear(err);
+ continue;
+ }
+ else
+ {
+ return svn_error_trace(err);
+ }
+ }
+
+ for (hi = apr_hash_first(scratch_pool, parent_props);
+ 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);
+
+ if (svn_property_kind(NULL, name) == 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);
+ }
+ }
+
+ if (apr_hash_count(final_hash))
+ {
+ svn_prop_inherited_item_t *new_iprop =
+ apr_palloc(result_pool, sizeof(*new_iprop));
+ new_iprop->path_or_url = apr_pstrdup(result_pool, parent_url);
+ new_iprop->prop_hash = final_hash;
+ svn_sort__array_insert(&new_iprop, *inherited_props, 0);
+ }
+ }
+
+ /* Reparent session back to original URL. */
+ SVN_ERR(svn_ra_reparent(session, session_url, scratch_pool));
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/deprecated.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_ra/deprecated.c Sat Oct 6 16:40:55 2012
@@ -417,3 +417,16 @@ svn_error_t *svn_ra_do_status(svn_ra_ses
SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
status_editor, status_baton, pool);
}
+
+svn_error_t *svn_ra_get_dir(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ apr_hash_t **dirents,
+ svn_revnum_t *fetched_rev,
+ apr_hash_t **props,
+ apr_pool_t *pool)
+{
+ SVN_ERR_ASSERT(*path != '/');
+ return session->vtable->get_dir(session, dirents, fetched_rev, props,
+ path, revision, SVN_DIRENT_ALL, pool);
+}
Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.c Sat Oct 6 16:40:55 2012
@@ -43,6 +43,9 @@
#include "svn_xml.h"
#include "svn_path.h"
#include "svn_dso.h"
+#include "svn_props.h"
+#include "svn_sorts.h"
+
#include "svn_config.h"
#include "ra_loader.h"
@@ -748,19 +751,6 @@ svn_error_t *svn_ra_get_file(svn_ra_sess
fetched_rev, props, pool);
}
-svn_error_t *svn_ra_get_dir(svn_ra_session_t *session,
- const char *path,
- svn_revnum_t revision,
- apr_hash_t **dirents,
- svn_revnum_t *fetched_rev,
- apr_hash_t **props,
- apr_pool_t *pool)
-{
- SVN_ERR_ASSERT(*path != '/');
- return session->vtable->get_dir(session, dirents, fetched_rev, props,
- path, revision, SVN_DIRENT_ALL, pool);
-}
-
svn_error_t *svn_ra_get_dir2(svn_ra_session_t *session,
apr_hash_t **dirents,
svn_revnum_t *fetched_rev,
@@ -1269,6 +1259,38 @@ svn_ra_get_deleted_rev(svn_ra_session_t
return err;
}
+svn_error_t *
+svn_ra_get_inherited_props(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t iprop_capable;
+
+ /* Path must be relative. */
+ SVN_ERR_ASSERT(*path != '/');
+
+ SVN_ERR(svn_ra_has_capability(session, &iprop_capable,
+ SVN_RA_CAPABILITY_INHERITED_PROPS,
+ scratch_pool));
+
+ if (iprop_capable)
+ {
+ SVN_ERR(session->vtable->get_inherited_props(session, iprops, path,
+ revision, result_pool,
+ scratch_pool));
+ }
+ else
+ {
+ /* Fallback for legacy servers. */
+ SVN_ERR(svn_ra__get_inherited_props_walk(session, path, revision, iprops,
+ result_pool, scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_ra__get_commit_ev2(svn_editor_t **editor,
@@ -1329,7 +1351,6 @@ svn_ra__get_commit_ev2(svn_editor_t **ed
cancel_func, cancel_baton,
result_pool, scratch_pool));
}
-
svn_error_t *
Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.h?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.h Sat Oct 6 16:40:55 2012
@@ -299,7 +299,13 @@ typedef struct svn_ra__vtable_t {
/* See svn_ra__register_editor_shim_callbacks() */
svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
svn_delta_shim_callbacks_t *callbacks);
-
+ /* See svn_ra_get_inherited_props(). */
+ svn_error_t *(*get_inherited_props)(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* See svn_ra__get_commit_ev2() */
svn_error_t *(*get_commit_ev2)(
svn_editor_t **editor,
@@ -473,6 +479,21 @@ svn_ra__get_deleted_rev_from_log(svn_ra_
apr_pool_t *pool);
+/**
+ * Fallback logic for svn_ra_get_fileX and svn_ra_get_dirX when those APIs
+ * need to find PATH's inherited properties on a legacy server that
+ * doesn't have the SVN_RA_CAPABILITY_INHERITED_PROPS capability.
+ *
+ * All arguments are as per the two aforementioned APIs.
+ */
+svn_error_t *
+svn_ra__get_inherited_props_walk(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ apr_array_header_t **inherited_props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Utility function to provide a shim between a returned Ev2 and an RA
provider's Ev1-based commit editor.
Modified: subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c Sat Oct 6 16:40:55 2012
@@ -1042,41 +1042,70 @@ svn_ra_local__stat(svn_ra_session_t *ses
static svn_error_t *
get_node_props(apr_hash_t **props,
+ apr_array_header_t **inherited_props,
svn_ra_local__session_baton_t *sess,
svn_fs_root_t *root,
const char *path,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_revnum_t cmt_rev;
const char *cmt_date, *cmt_author;
/* Create a hash with props attached to the fs node. */
- SVN_ERR(svn_fs_node_proplist(props, root, path, pool));
+ if (props)
+ {
+ SVN_ERR(svn_fs_node_proplist(props, root, path, result_pool));
+ }
+
+ /* Turn FS-path keys into URLs. */
+ if (inherited_props)
+ {
+ int i;
+
+ SVN_ERR(svn_repos_fs_get_inherited_props(inherited_props, root, path,
+ NULL, NULL,
+ result_pool, scratch_pool));
+
+ for (i = 0; i < (*inherited_props)->nelts; i++)
+ {
+ svn_prop_inherited_item_t *i_props =
+ APR_ARRAY_IDX(*inherited_props, i, svn_prop_inherited_item_t *);
+ i_props->path_or_url = svn_path_url_add_component2(
+ sess->repos_url, i_props->path_or_url, result_pool);
+ }
+ }
/* Now add some non-tweakable metadata to the hash as well... */
- /* The so-called 'entryprops' with info about CR & friends. */
- SVN_ERR(svn_repos_get_committed_info(&cmt_rev, &cmt_date,
- &cmt_author, root, path, pool));
-
- apr_hash_set(*props,
- SVN_PROP_ENTRY_COMMITTED_REV,
- APR_HASH_KEY_STRING,
- svn_string_createf(pool, "%ld", cmt_rev));
- apr_hash_set(*props,
- SVN_PROP_ENTRY_COMMITTED_DATE,
- APR_HASH_KEY_STRING,
- cmt_date ? svn_string_create(cmt_date, pool) : NULL);
- apr_hash_set(*props,
- SVN_PROP_ENTRY_LAST_AUTHOR,
- APR_HASH_KEY_STRING,
- cmt_author ? svn_string_create(cmt_author, pool) : NULL);
- apr_hash_set(*props,
- SVN_PROP_ENTRY_UUID,
- APR_HASH_KEY_STRING,
- svn_string_create(sess->uuid, pool));
+ if (props)
+ {
+ /* The so-called 'entryprops' with info about CR & friends. */
+ SVN_ERR(svn_repos_get_committed_info(&cmt_rev, &cmt_date,
+ &cmt_author, root, path,
+ scratch_pool));
+
+ apr_hash_set(*props,
+ SVN_PROP_ENTRY_COMMITTED_REV,
+ APR_HASH_KEY_STRING,
+ svn_string_createf(result_pool, "%ld", cmt_rev));
+ apr_hash_set(*props,
+ SVN_PROP_ENTRY_COMMITTED_DATE,
+ APR_HASH_KEY_STRING,
+ cmt_date ? svn_string_create(cmt_date,
+ result_pool) : NULL);
+ apr_hash_set(*props,
+ SVN_PROP_ENTRY_LAST_AUTHOR,
+ APR_HASH_KEY_STRING,
+ cmt_author ? svn_string_create(cmt_author,
+ result_pool) : NULL);
+ apr_hash_set(*props,
+ SVN_PROP_ENTRY_UUID,
+ APR_HASH_KEY_STRING,
+ svn_string_create(sess->uuid, result_pool));
- /* We have no 'wcprops' in ra_local, but might someday. */
+ /* We have no 'wcprops' in ra_local, but might someday. */
+ }
return SVN_NO_ERROR;
}
@@ -1148,7 +1177,7 @@ svn_ra_local__get_file(svn_ra_session_t
/* Handle props if requested. */
if (props)
- SVN_ERR(get_node_props(props, sess, root, abs_path, pool));
+ SVN_ERR(get_node_props(props, NULL, sess, root, abs_path, pool, pool));
return SVN_NO_ERROR;
}
@@ -1259,7 +1288,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
/* Handle props if requested. */
if (props)
- SVN_ERR(get_node_props(props, sess, root, abs_path, pool));
+ SVN_ERR(get_node_props(props, NULL, sess, root, abs_path, pool, pool));
return SVN_NO_ERROR;
}
@@ -1493,7 +1522,8 @@ svn_ra_local__has_capability(svn_ra_sess
|| strcmp(capability, SVN_RA_CAPABILITY_LOG_REVPROPS) == 0
|| strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0
|| strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0
- || strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
+ || strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0
+ || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0)
{
*has = TRUE;
}
@@ -1537,6 +1567,44 @@ svn_ra_local__get_deleted_rev(svn_ra_ses
}
static svn_error_t *
+svn_ra_local__get_inherited_props(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_fs_root_t *root;
+ svn_revnum_t youngest_rev;
+ svn_ra_local__session_baton_t *sess = session->priv;
+ const char *abs_path = svn_fspath__join(sess->fs_path->data, path,
+ scratch_pool);
+ svn_node_kind_t node_kind;
+
+ /* Open the revision's root. */
+ if (! SVN_IS_VALID_REVNUM(revision))
+ {
+ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, sess->fs, scratch_pool));
+ SVN_ERR(svn_fs_revision_root(&root, sess->fs, youngest_rev,
+ scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, scratch_pool));
+ }
+
+ SVN_ERR(svn_fs_check_path(&node_kind, root, abs_path, scratch_pool));
+ if (node_kind == svn_node_none)
+ {
+ return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+ _("'%s' path not found"), abs_path);
+ }
+
+ return svn_error_trace(get_node_props(NULL, iprops, sess, root, abs_path,
+ result_pool, scratch_pool));
+}
+
+static svn_error_t *
svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session,
svn_delta_shim_callbacks_t *callbacks)
{
@@ -1649,6 +1717,7 @@ static const svn_ra__vtable_t ra_local_v
svn_ra_local__replay_range,
svn_ra_local__get_deleted_rev,
svn_ra_local__register_editor_shim_callbacks,
+ svn_ra_local__get_inherited_props,
svn_ra_local__get_commit_ev2
};
Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Sat Oct 6 16:40:55 2012
@@ -199,6 +199,12 @@ capabilities_headers_iterator_callback(v
SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
capability_yes);
}
+ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals))
+ {
+ apr_hash_set(session->capabilities,
+ SVN_RA_CAPABILITY_INHERITED_PROPS,
+ APR_HASH_KEY_STRING, capability_yes);
+ }
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals))
{
apr_hash_set(session->capabilities,
@@ -323,6 +329,8 @@ options_response_handler(serf_request_t
APR_HASH_KEY_STRING, capability_no);
apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
APR_HASH_KEY_STRING, capability_no);
+ apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS,
+ APR_HASH_KEY_STRING, capability_no);
apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
APR_HASH_KEY_STRING, capability_no);
Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Sat Oct 6 16:40:55 2012
@@ -1657,6 +1657,14 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+/* Implements the get_inherited_props RA layer function. */
+svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Implements svn_ra__vtable_t.get_repos_root(). */
svn_error_t *
svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
@@ -1668,7 +1676,6 @@ svn_error_t *
svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
svn_delta_shim_callbacks_t *callbacks);
-
/*** Authentication handler declarations ***/
/**
Modified: subversion/trunk/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/serf.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/serf.c Sat Oct 6 16:40:55 2012
@@ -1149,7 +1149,8 @@ static const svn_ra__vtable_t serf_vtabl
svn_ra_serf__has_capability,
svn_ra_serf__replay_range,
svn_ra_serf__get_deleted_rev,
- svn_ra_serf__register_editor_shim_callbacks
+ svn_ra_serf__register_editor_shim_callbacks,
+ svn_ra_serf__get_inherited_props
};
svn_error_t *
Modified: subversion/trunk/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/client.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/client.c Sat Oct 6 16:40:55 2012
@@ -1056,6 +1056,80 @@ static svn_error_t *ra_svn_commit(svn_ra
return SVN_NO_ERROR;
}
+/* Parse IPROPLIST, an array of svn_ra_svn_item_t structures, as a list of
+ const char * repos relative paths and properties for those paths, storing
+ the result as an array of svn_prop_inherited_item_t *items. */
+static svn_error_t *
+parse_iproplist(apr_array_header_t **inherited_props,
+ const apr_array_header_t *iproplist,
+ svn_ra_session_t *session,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+
+{
+ int i;
+ const char *repos_root_url;
+ apr_pool_t *iterpool;
+
+ if (iproplist == NULL)
+ {
+ /* If the server doesn't have the SVN_RA_CAPABILITY_INHERITED_PROPS
+ capability we shouldn't be asking for inherited props, but if we
+ did and the server sent back nothing then we'll want to handle
+ that. */
+ *inherited_props = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(ra_svn_get_repos_root(session, &repos_root_url, scratch_pool));
+
+ *inherited_props = apr_array_make(
+ result_pool, iproplist->nelts, sizeof(svn_prop_inherited_item_t *));
+
+ iterpool = svn_pool_create(scratch_pool);
+
+ for (i = 0; i < iproplist->nelts; i++)
+ {
+ apr_array_header_t *iprop_list;
+ char *parent_rel_path;
+ apr_hash_t *iprops;
+ apr_hash_index_t *hi;
+ svn_prop_inherited_item_t *new_iprop =
+ apr_palloc(result_pool, sizeof(*new_iprop));
+ svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(iproplist, i,
+ svn_ra_svn_item_t);
+ if (elt->kind != SVN_RA_SVN_LIST)
+ return svn_error_create(
+ SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Inherited proplist element not a list"));
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, iterpool, "cl",
+ &parent_rel_path, &iprop_list));
+ SVN_ERR(svn_ra_svn_parse_proplist(iprop_list, iterpool, &iprops));
+ new_iprop->path_or_url = svn_path_url_add_component2(repos_root_url,
+ parent_rel_path,
+ result_pool);
+ new_iprop->prop_hash = apr_hash_make(result_pool);
+ for (hi = apr_hash_first(iterpool, iprops);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_string_t *value = svn__apr_hash_index_val(hi);
+ apr_hash_set(new_iprop->prop_hash,
+ apr_pstrdup(result_pool, name),
+ APR_HASH_KEY_STRING,
+ svn_string_dup(value, result_pool));
+ }
+ APR_ARRAY_PUSH(*inherited_props, svn_prop_inherited_item_t *) =
+ new_iprop;
+ }
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path,
svn_revnum_t rev, svn_stream_t *stream,
svn_revnum_t *fetched_rev,
@@ -2533,6 +2607,9 @@ static svn_error_t *ra_svn_has_capabilit
else if (strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
*has = svn_ra_svn_has_capability(sess->conn,
SVN_RA_SVN_CAP_ATOMIC_REVPROPS);
+ else if (strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0)
+ *has = svn_ra_svn_has_capability(sess->conn,
+ SVN_RA_SVN_CAP_INHERITED_PROPS);
else if (strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0)
*has = svn_ra_svn_has_capability(sess->conn,
SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS);
@@ -2582,6 +2659,27 @@ ra_svn_register_editor_shim_callbacks(sv
return SVN_NO_ERROR;
}
+static svn_error_t *
+ra_svn_get_inherited_props(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_svn__session_baton_t *sess_baton = session->priv;
+ svn_ra_svn_conn_t *conn = sess_baton->conn;
+ apr_array_header_t *iproplist;
+
+ SVN_ERR(svn_ra_svn_write_cmd(conn, scratch_pool, "get-iprops", "c(?r)",
+ path, revision));
+ SVN_ERR(handle_auth_request(sess_baton, scratch_pool));
+ SVN_ERR(svn_ra_svn_read_cmd_response(conn, scratch_pool, "l", &iproplist));
+ SVN_ERR(parse_iproplist(iprops, iproplist, session, result_pool,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
static const svn_ra__vtable_t ra_svn_vtable = {
svn_ra_svn_version,
@@ -2619,7 +2717,8 @@ static const svn_ra__vtable_t ra_svn_vta
ra_svn_has_capability,
ra_svn_replay_range,
ra_svn_get_deleted_rev,
- ra_svn_register_editor_shim_callbacks
+ ra_svn_register_editor_shim_callbacks,
+ ra_svn_get_inherited_props
};
svn_error_t *
Modified: subversion/trunk/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/protocol?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/protocol Sat Oct 6 16:40:55 2012
@@ -202,6 +202,10 @@ capability and C indicates a client capa
[S] atomic-revprops If the server presents this capability, it
supports the change-rev-prop2 command.
See section 3.1.1.
+[S] inherited-props If the server presents this capability, it supports the
+ retrieval of inherited properties via the get-dir and
+ get-file commands and also supports the get-iprops
+ command (see section 3.1.1).
3. Commands
-----------
@@ -222,6 +226,7 @@ responds.
Here are some miscellaneous prototypes used by the command sets:
proplist: ( ( name:string value:string ) ... )
+ iproplist: ( ( name:string proplist ) ... )
propdelta: ( ( name:string [ value:string ] ) ... )
node-kind: none|file|dir|unknown
bool: true|false
@@ -293,8 +298,10 @@ second place for auth-request point as n
? ( post-commit-err:string ) )
get-file
- params: ( path:string [ rev:number ] want-props:bool want-contents:bool )
- response: ( [ checksum:string ] rev:number props:proplist )
+ params: ( path:string [ rev:number ] want-props:bool want-contents:bool
+ [ want-iprops:bool ] )
+ response: ( [ checksum:string ] rev:number props:proplist
+ [ inherited-props:iproplist ] )
If want-contents is specified, then after sending response, server
sends file contents as a series of strings, terminated by the empty
string, followed by a second empty command response to indicate
@@ -302,8 +309,9 @@ second place for auth-request point as n
get-dir
params: ( path:string [ rev:number ] want-props:bool want-contents:bool
- ? ( field:dirent-field ... ) )
- response: ( rev:number props:proplist ( entry:dirent ... ) )]
+ ? ( field:dirent-field ... ) [ want-iprops:bool ] )
+ response: ( rev:number props:proplist ( entry:dirent ... )
+ [ inherited-props:iproplist ] )]
dirent: ( name:string kind:node-kind size:number has-props:bool
created-rev:number [ created-date:string ]
[ last-author:string ] )
@@ -464,6 +472,11 @@ second place for auth-request point as n
params: ( path:string peg-rev:number end-rev:number )
response: ( deleted-rev:number )
+ get-iprops
+ params: ( path:string [ rev:number ] )
+ response: ( inherited-props:iproplist )
+ New in svn 1.8. If rev is not specified, the youngest revision is used.
+
3.1.2. Editor Command Set
An edit operation produces only one response, at close-edit or
Modified: subversion/trunk/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/fs-wrap.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/trunk/subversion/libsvn_repos/fs-wrap.c Sat Oct 6 16:40:55 2012
@@ -31,10 +31,12 @@
#include "svn_props.h"
#include "svn_repos.h"
#include "svn_time.h"
+#include "svn_sorts.h"
#include "repos.h"
#include "svn_private_config.h"
#include "private/svn_repos_private.h"
#include "private/svn_utf_private.h"
+#include "private/svn_fspath.h"
/*** Commit wrappers ***/
@@ -737,7 +739,54 @@ svn_repos_fs_pack2(svn_repos_t *repos,
cancel_func, cancel_baton, pool);
}
+svn_error_t *
+svn_repos_fs_get_inherited_props(apr_array_header_t **inherited_props_p,
+ svn_fs_root_t *root,
+ const char *path,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_array_header_t *inherited_props;
+ const char *parent_path = path;
+
+ inherited_props = apr_array_make(result_pool, 1,
+ sizeof(svn_prop_inherited_item_t *));
+ while (!(parent_path[0] == '/' && parent_path[1] == '\0'))
+ {
+ svn_boolean_t allowed = TRUE;
+ apr_hash_t *parent_properties;
+
+ svn_pool_clear(iterpool);
+ parent_path = svn_fspath__dirname(parent_path, iterpool);
+
+ if (authz_read_func)
+ SVN_ERR(authz_read_func(&allowed, root, parent_path,
+ authz_read_baton, iterpool));
+ if (allowed)
+ {
+ SVN_ERR(svn_fs_node_proplist(&parent_properties, root,
+ parent_path, result_pool));
+ if (parent_properties && apr_hash_count(parent_properties))
+ {
+ svn_prop_inherited_item_t *i_props =
+ apr_pcalloc(result_pool, sizeof(*i_props));
+ i_props->path_or_url =
+ apr_pstrdup(result_pool, parent_path + 1);
+ i_props->prop_hash = parent_properties;
+ /* Build the output array in depth-first order. */
+ svn_sort__array_insert(&i_props, inherited_props, 0);
+ }
+ }
+ }
+ svn_pool_destroy(iterpool);
+
+ *inherited_props_p = inherited_props;
+ return SVN_NO_ERROR;
+}
/*
* vim:ts=4:sw=2:expandtab:tw=80:fo=tcroq
Modified: subversion/trunk/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cmdline.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cmdline.c Sat Oct 6 16:40:55 2012
@@ -642,6 +642,7 @@ void
svn_cmdline__print_xml_prop(svn_stringbuf_t **outstr,
const char* propname,
svn_string_t *propval,
+ svn_boolean_t inherited_prop,
apr_pool_t *pool)
{
const char *xml_safe;
@@ -665,16 +666,22 @@ svn_cmdline__print_xml_prop(svn_stringbu
}
if (encoding)
- svn_xml_make_open_tag(outstr, pool, svn_xml_protect_pcdata,
- "property", "name", propname,
- "encoding", encoding, NULL);
+ svn_xml_make_open_tag(
+ outstr, pool, svn_xml_protect_pcdata,
+ inherited_prop ? "inherited_property" : "property",
+ "name", propname,
+ "encoding", encoding, NULL);
else
- svn_xml_make_open_tag(outstr, pool, svn_xml_protect_pcdata,
- "property", "name", propname, NULL);
+ svn_xml_make_open_tag(
+ outstr, pool, svn_xml_protect_pcdata,
+ inherited_prop ? "inherited_property" : "property",
+ "name", propname, NULL);
svn_stringbuf_appendcstr(*outstr, xml_safe);
- svn_xml_make_close_tag(outstr, pool, "property");
+ svn_xml_make_close_tag(
+ outstr, pool,
+ inherited_prop ? "inherited_property" : "property");
return;
}
Modified: subversion/trunk/subversion/libsvn_subr/log.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/log.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/log.c (original)
+++ subversion/trunk/subversion/libsvn_subr/log.c Sat Oct 6 16:40:55 2012
@@ -380,3 +380,17 @@ svn_log__replay(const char *path, svn_re
log_path = "/";
return apr_psprintf(pool, "replay %s r%ld", log_path, rev);
}
+
+const char *
+svn_log__get_inherited_props(const char *path,
+ svn_revnum_t rev,
+ apr_pool_t *pool)
+{
+ const char *log_path;
+
+ if (path && path[0] != '\0')
+ log_path = svn_path_uri_encode(path, pool);
+ else
+ log_path = "/";
+ return apr_psprintf(pool, "get-inherited-props %s r%ld", log_path, rev);
+}
Modified: subversion/trunk/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/skel.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/skel.c (original)
+++ subversion/trunk/subversion/libsvn_subr/skel.c Sat Oct 6 16:40:55 2012
@@ -23,6 +23,8 @@
#include <string.h>
#include "svn_string.h"
#include "svn_error.h"
+#include "svn_props.h"
+#include "svn_pools.h"
#include "private/svn_skel.h"
#include "private/svn_string_private.h"
@@ -167,6 +169,35 @@ is_valid_proplist_skel(const svn_skel_t
return FALSE;
}
+static svn_boolean_t
+is_valid_iproplist_skel(const svn_skel_t *skel)
+{
+ int len = svn_skel__list_length(skel);
+
+ if ((len >= 0) && (len & 1) == 0)
+ {
+ svn_skel_t *elt;
+
+ for (elt = skel->children; elt; elt = elt->next)
+ {
+ if (!elt->is_atom)
+ return FALSE;
+
+ if (elt->next == NULL)
+ return FALSE;
+
+ elt = elt->next;
+
+ if (! is_valid_proplist_skel(elt))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static svn_skel_t *parse(const char *data, apr_size_t len,
apr_pool_t *pool);
@@ -689,6 +720,34 @@ svn_skel__parse_proplist(apr_hash_t **pr
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_skel__parse_iprops(apr_array_header_t **iprops,
+ const svn_skel_t *skel,
+ apr_pool_t *result_pool)
+{
+ svn_skel_t *elt;
+
+ /* Validate the skel. */
+ if (! is_valid_iproplist_skel(skel))
+ return skel_err("iprops");
+
+ /* Create the returned structure */
+ *iprops = apr_array_make(result_pool, 1,
+ sizeof(svn_prop_inherited_item_t *));
+
+ for (elt = skel->children; elt; elt = elt->next->next)
+ {
+ svn_prop_inherited_item_t *new_iprop = apr_palloc(result_pool,
+ sizeof(*new_iprop));
+ svn_string_t *repos_parent = svn_string_ncreate(elt->data, elt->len,
+ result_pool);
+ SVN_ERR(svn_skel__parse_proplist(&(new_iprop->prop_hash), elt->next,
+ result_pool));
+ new_iprop->path_or_url = repos_parent->data;
+ APR_ARRAY_PUSH(*iprops, svn_prop_inherited_item_t *) = new_iprop;
+ }
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_skel__parse_prop(svn_string_t **propval,
@@ -760,3 +819,65 @@ svn_skel__unparse_proplist(svn_skel_t **
*skel_p = skel;
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_skel__unparse_iproplist(svn_skel_t **skel_p,
+ const apr_array_header_t *inherited_props,
+ apr_pool_t *result_pool)
+{
+ svn_skel_t *skel = svn_skel__make_empty_list(result_pool);
+
+ /* Create the skel. */
+ if (inherited_props)
+ {
+ int i;
+ apr_hash_index_t *hi;
+ apr_pool_t *subpool = svn_pool_create(result_pool);
+
+ 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_skel_t *skel_list = svn_skel__make_empty_list(result_pool);
+ svn_skel_t *skel_atom;
+
+ svn_pool_clear(subpool);
+
+ /* Loop over hash entries */
+ for (hi = apr_hash_first(subpool, iprop->prop_hash);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *key;
+ void *val;
+ apr_ssize_t klen;
+ svn_string_t *value;
+
+ apr_hash_this(hi, &key, &klen, &val);
+ value = val;
+
+ /* VALUE */
+ svn_skel__prepend(svn_skel__mem_atom(value->data, value->len,
+ result_pool), skel_list);
+
+ /* NAME */
+ svn_skel__prepend(svn_skel__mem_atom(key, klen, result_pool),
+ skel_list);
+ }
+
+ skel_atom = svn_skel__str_atom(
+ apr_pstrdup(result_pool, iprop->path_or_url), result_pool);
+ svn_skel__append(skel, skel_atom);
+ svn_skel__append(skel, skel_list);
+ }
+ svn_pool_destroy(subpool);
+ }
+
+ /* Validate and return the skel. */
+ if (! is_valid_iproplist_skel(skel))
+ return skel_err("iproplist");
+
+ *skel_p = skel;
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sqlite.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/trunk/subversion/libsvn_subr/sqlite.c Sat Oct 6 16:40:55 2012
@@ -476,6 +476,27 @@ svn_sqlite__bind_properties(svn_sqlite__
}
svn_error_t *
+svn_sqlite__bind_iprops(svn_sqlite__stmt_t *stmt,
+ int slot,
+ const apr_array_header_t *inherited_props,
+ apr_pool_t *scratch_pool)
+{
+ svn_skel_t *skel;
+ svn_stringbuf_t *properties;
+
+ if (inherited_props == NULL)
+ return svn_error_trace(svn_sqlite__bind_blob(stmt, slot, NULL, 0));
+
+ SVN_ERR(svn_skel__unparse_iproplist(&skel, inherited_props,
+ scratch_pool));
+ properties = svn_skel__unparse(skel, scratch_pool);
+ return svn_error_trace(svn_sqlite__bind_blob(stmt,
+ slot,
+ properties->data,
+ properties->len));
+}
+
+svn_error_t *
svn_sqlite__bind_checksum(svn_sqlite__stmt_t *stmt,
int slot,
const svn_checksum_t *checksum,
@@ -581,6 +602,31 @@ svn_sqlite__column_properties(apr_hash_t
}
svn_error_t *
+svn_sqlite__column_iprops(apr_array_header_t **iprops,
+ svn_sqlite__stmt_t *stmt,
+ int column,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_size_t len;
+ const void *val;
+
+ /* svn_skel__parse_iprops copies everything needed to result_pool */
+ val = svn_sqlite__column_blob(stmt, column, &len, NULL);
+ if (val == NULL)
+ {
+ *iprops = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_skel__parse_iprops(iprops,
+ svn_skel__parse(val, len, scratch_pool),
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_sqlite__column_checksum(const svn_checksum_t **checksum,
svn_sqlite__stmt_t *stmt, int column,
apr_pool_t *result_pool)
Modified: subversion/trunk/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/deprecated.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_wc/deprecated.c Sat Oct 6 16:40:55 2012
@@ -3269,7 +3269,7 @@ svn_wc_get_update_editor4(const svn_delt
target_revision,
wc_ctx,
anchor_abspath,
- target_basename,
+ target_basename, NULL,
use_commit_times,
depth, depth_is_sticky,
allow_unver_obstructions,
@@ -3455,7 +3455,7 @@ svn_wc_get_switch_editor4(const svn_delt
target_revision,
wc_ctx,
anchor_abspath, target_basename,
- switch_url,
+ switch_url, NULL,
use_commit_times,
depth, depth_is_sticky,
allow_unver_obstructions,
Modified: subversion/trunk/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/externals.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/externals.c (original)
+++ subversion/trunk/subversion/libsvn_wc/externals.c Sat Oct 6 16:40:55 2012
@@ -381,6 +381,10 @@ struct edit_baton
/* List of incoming propchanges */
apr_array_header_t *propchanges;
+ /* Array of svn_prop_inherited_item_t * structures representing the
+ properties inherited by the base node at LOCAL_ABSPATH. */
+ apr_array_header_t *iprops;
+
/* The last change information */
svn_revnum_t changed_rev;
apr_time_t changed_date;
@@ -810,6 +814,7 @@ close_file(void *file_baton,
eb->repos_uuid,
*eb->target_revision,
new_pristine_props,
+ eb->iprops,
eb->changed_rev,
eb->changed_date,
eb->changed_author,
@@ -825,6 +830,12 @@ close_file(void *file_baton,
all_work_items,
pool));
+ /* close_edit may also update iprops for switched files, catching
+ those for which close_file is never called (e.g. an update of a
+ file external with no changes). So as a minor optimization we
+ clear the iprops so as not to set them again in close_edit. */
+ eb->iprops = NULL;
+
SVN_ERR(svn_wc__wq_run(eb->db, eb->wri_abspath,
eb->cancel_func, eb->cancel_baton, pool));
}
@@ -864,8 +875,18 @@ close_edit(void *edit_baton,
{
struct edit_baton *eb = edit_baton;
- if (!eb->file_closed)
+ if (!eb->file_closed
+ || eb->iprops)
{
+ apr_hash_t *wcroot_iprops = NULL;
+
+ if (eb->iprops)
+ {
+ wcroot_iprops = apr_hash_make(pool);
+ apr_hash_set(wcroot_iprops, eb->local_abspath, APR_HASH_KEY_STRING,
+ eb->iprops);
+ }
+
/* The node wasn't updated, so we just have to bump its revision */
SVN_ERR(svn_wc__db_op_bump_revisions_post_update(eb->db,
eb->local_abspath,
@@ -873,6 +894,7 @@ close_edit(void *edit_baton,
NULL, NULL, NULL,
*eb->target_revision,
apr_hash_make(pool),
+ wcroot_iprops,
pool));
}
@@ -889,6 +911,7 @@ svn_wc__get_file_external_editor(const s
const char *url,
const char *repos_root_url,
const char *repos_uuid,
+ apr_array_header_t *iprops,
svn_boolean_t use_commit_times,
const char *diff3_cmd,
const apr_array_header_t *preserved_exts,
@@ -924,6 +947,8 @@ svn_wc__get_file_external_editor(const s
eb->repos_root_url = apr_pstrdup(edit_pool, repos_root_url);
eb->repos_uuid = apr_pstrdup(edit_pool, repos_uuid);
+ eb->iprops = iprops;
+
eb->use_commit_times = use_commit_times;
eb->ext_patterns = preserved_exts;
eb->diff3cmd = diff3_cmd;
Modified: subversion/trunk/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/props.c (original)
+++ subversion/trunk/subversion/libsvn_wc/props.c Sat Oct 6 16:40:55 2012
@@ -46,6 +46,7 @@
#include "svn_wc.h"
#include "svn_utf.h"
#include "svn_diff.h"
+#include "svn_sorts.h"
#include "private/svn_wc_private.h"
#include "private/svn_mergeinfo_private.h"
@@ -2332,3 +2333,151 @@ svn_wc__has_magic_property(const apr_arr
}
return FALSE;
}
+
+/* Remove all prop name value pairs from PROP_HASH where the property
+ name is not PROPNAME. */
+static void
+filter_unwanted_props(apr_hash_t *prop_hash,
+ const char * propname,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, prop_hash);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *ipropname = svn__apr_hash_index_key(hi);
+
+ if (strcmp(ipropname, propname) != 0)
+ apr_hash_set(prop_hash, ipropname, APR_HASH_KEY_STRING, NULL);
+ }
+ return;
+}
+
+svn_error_t *
+svn_wc__get_iprops(apr_array_header_t **inherited_props,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+ apr_array_header_t *cached_iprops = NULL;
+ const char *parent_abspath = local_abspath;
+ svn_boolean_t is_wc_root = FALSE;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+ SVN_ERR_ASSERT(inherited_props);
+ *inherited_props = apr_array_make(result_pool, 1,
+ sizeof(svn_prop_inherited_item_t *));
+
+ /* Walk up to the root of the WC looking for inherited properties. When we
+ reach the WC root also check for cached inherited properties. */
+ while (TRUE)
+ {
+ apr_hash_t *actual_props;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_wc_is_wc_root2(&is_wc_root, wc_ctx, parent_abspath,
+ iterpool));
+ if (is_wc_root)
+ {
+ const char *child_repos_relpath;
+
+ SVN_ERR(svn_wc__node_get_repos_relpath(&child_repos_relpath,
+ wc_ctx, parent_abspath,
+ iterpool, iterpool));
+
+ /* If the WC root is also the root of the repository then by
+ definition there are no inheritable properties to be had. */
+ if (child_repos_relpath[0] != '\0')
+ {
+ /* Grab the cached inherited properties for the WC root. */
+ SVN_ERR(svn_wc__db_read_cached_iprops(&cached_iprops,
+ wc_ctx->db,
+ parent_abspath,
+ scratch_pool,
+ iterpool));
+ }
+ }
+
+ /* If PARENT_ABSPATH is a true parent of LOCAL_ABSPATH, then
+ LOCAL_ABSPATH can inherit properties from it. */
+ if (strcmp(local_abspath, parent_abspath) != 0)
+ {
+ SVN_ERR(svn_wc__db_read_props(&actual_props, wc_ctx->db,
+ parent_abspath, result_pool,
+ iterpool));
+ if (actual_props)
+ {
+ /* If we only want PROPNAME filter out any other properties. */
+ if (propname)
+ filter_unwanted_props(actual_props, propname, iterpool);
+
+ if (apr_hash_count(actual_props))
+ {
+ svn_prop_inherited_item_t *iprop_elt =
+ apr_pcalloc(result_pool,
+ sizeof(svn_prop_inherited_item_t));
+ iprop_elt->path_or_url = apr_pstrdup(result_pool,
+ parent_abspath);
+ iprop_elt->prop_hash = actual_props;
+ /* Build the output array in depth-first order. */
+ svn_sort__array_insert(&iprop_elt, *inherited_props, 0);
+ }
+ }
+ }
+
+ /* Inheritance only goes as far as the nearest WC root. */
+ if (is_wc_root)
+ break;
+
+ /* Keep looking for the WC root. */
+ parent_abspath = svn_dirent_dirname(parent_abspath, scratch_pool);
+ }
+
+ if (cached_iprops)
+ {
+ for (i = cached_iprops->nelts - 1; i >= 0; i--)
+ {
+ svn_prop_inherited_item_t *cached_iprop =
+ APR_ARRAY_IDX(cached_iprops, i, svn_prop_inherited_item_t *);
+
+ /* An empty property hash in the iprops cache means there are no
+ inherited properties. */
+ if (apr_hash_count(cached_iprop->prop_hash) == 0)
+ continue;
+
+ if (propname)
+ filter_unwanted_props(cached_iprop->prop_hash, propname,
+ scratch_pool);
+
+ /* If we didn't filter everything then keep this iprop. */
+ if (apr_hash_count(cached_iprop->prop_hash))
+ svn_sort__array_insert(&cached_iprop, *inherited_props, 0);
+ }
+ }
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__get_cached_iprop_children(apr_hash_t **iprop_paths,
+ svn_depth_t depth,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(svn_wc__db_get_children_with_cached_iprops(iprop_paths,
+ depth,
+ local_abspath,
+ wc_ctx->db,
+ result_pool,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Sat Oct 6 16:40:55 2012
@@ -170,6 +170,12 @@ struct edit_baton
generated conflict files. */
const apr_array_header_t *ext_patterns;
+ /* Hash mapping const char * absolute working copy paths to depth-first
+ ordered arrays of svn_prop_inherited_item_t * structures representing
+ the properties inherited by the base node at that working copy path.
+ May be NULL. */
+ apr_hash_t *wcroot_iprops;
+
/* The revision we're targeting...or something like that. This
starts off as a pointer to the revision to which we are updating,
or SVN_INVALID_REVNUM, but by the end of the edit, should be
@@ -2638,6 +2644,7 @@ close_directory(void *dir_baton,
else
{
apr_hash_t *props;
+ apr_array_header_t *iprops = NULL;
/* ### we know a base node already exists. it was created in
### open_directory or add_directory. let's just preserve the
@@ -2697,6 +2704,22 @@ close_directory(void *dir_baton,
scratch_pool);
}
+ /* Any inherited props to be set set for this base node? */
+ if (eb->wcroot_iprops)
+ {
+ iprops = apr_hash_get(eb->wcroot_iprops, db->local_abspath,
+ APR_HASH_KEY_STRING);
+
+ /* close_edit may also update iprops for switched nodes, catching
+ those for which close_directory is never called (e.g. a switch
+ with no changes). So as a minor optimization we remove any
+ iprops from the hash so as not to set them again in
+ close_edit. */
+ if (iprops)
+ apr_hash_set(eb->wcroot_iprops, db->local_abspath,
+ APR_HASH_KEY_STRING, NULL);
+ }
+
/* Update the BASE data for the directory and mark the directory
complete */
SVN_ERR(svn_wc__db_base_add_directory(
@@ -2715,7 +2738,7 @@ close_directory(void *dir_baton,
conflict_skel,
(! db->shadowed) && new_base_props != NULL,
new_actual_props,
- all_work_items,
+ iprops, all_work_items,
scratch_pool));
}
@@ -4391,6 +4414,7 @@ close_edit(void *edit_baton,
eb->repos_uuid,
*(eb->target_revision),
eb->skipped_trees,
+ eb->wcroot_iprops,
eb->pool));
if (*eb->target_basename != '\0')
@@ -4464,6 +4488,7 @@ make_editor(svn_revnum_t *target_revisio
svn_wc__db_t *db,
const char *anchor_abspath,
const char *target_basename,
+ apr_hash_t *wcroot_iprops,
svn_boolean_t use_commit_times,
const char *switch_url,
svn_depth_t depth,
@@ -4529,6 +4554,7 @@ make_editor(svn_revnum_t *target_revisio
eb->db = db;
eb->target_basename = target_basename;
eb->anchor_abspath = anchor_abspath;
+ eb->wcroot_iprops = wcroot_iprops;
SVN_ERR(svn_wc__db_get_wcroot(&eb->wcroot_abspath, db, anchor_abspath,
edit_pool, scratch_pool));
@@ -4750,6 +4776,7 @@ svn_wc__get_update_editor(const svn_delt
svn_wc_context_t *wc_ctx,
const char *anchor_abspath,
const char *target_basename,
+ apr_hash_t *wcroot_iprops,
svn_boolean_t use_commit_times,
svn_depth_t depth,
svn_boolean_t depth_is_sticky,
@@ -4773,7 +4800,7 @@ svn_wc__get_update_editor(const svn_delt
apr_pool_t *scratch_pool)
{
return make_editor(target_revision, wc_ctx->db, anchor_abspath,
- target_basename, use_commit_times,
+ target_basename, wcroot_iprops, use_commit_times,
NULL, depth, depth_is_sticky, allow_unver_obstructions,
adds_as_modification, server_performs_filtering,
clean_checkout,
@@ -4794,6 +4821,7 @@ svn_wc__get_switch_editor(const svn_delt
const char *anchor_abspath,
const char *target_basename,
const char *switch_url,
+ apr_hash_t *wcroot_iprops,
svn_boolean_t use_commit_times,
svn_depth_t depth,
svn_boolean_t depth_is_sticky,
@@ -4817,7 +4845,7 @@ svn_wc__get_switch_editor(const svn_delt
SVN_ERR_ASSERT(switch_url && svn_uri_is_canonical(switch_url, scratch_pool));
return make_editor(target_revision, wc_ctx->db, anchor_abspath,
- target_basename, use_commit_times,
+ target_basename, wcroot_iprops, use_commit_times,
switch_url,
depth, depth_is_sticky, allow_unver_obstructions,
FALSE /* adds_as_modification */,
@@ -5072,7 +5100,7 @@ svn_wc_is_wc_root2(svn_boolean_t *wc_roo
return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, err, err->message);
}
- *wc_root = is_root || (kind == svn_kind_dir && is_switched);
+ *wc_root = is_root || is_switched;
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/upgrade.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/trunk/subversion/libsvn_wc/upgrade.c Sat Oct 6 16:40:55 2012
@@ -1559,6 +1559,47 @@ bump_to_30(void *baton, svn_sqlite__db_t
return SVN_NO_ERROR;
}
+static svn_error_t *
+bump_to_31(void *baton,
+ svn_sqlite__db_t *sdb,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt, *stmt_mark_switch_roots;
+ svn_boolean_t have_row;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_array_header_t *empty_iprops = apr_array_make(
+ scratch_pool, 0, sizeof(svn_prop_inherited_item_t *));
+
+ /* Add the inherited_props column to NODES. */
+ SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31));
+
+ /* Set inherited_props to an empty array for the roots of all
+ switched subtrees in the WC. This allows subsequent updates
+ to recognize these roots as needing an iprops cache. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_SELECT_WCROOT_NODES));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt_mark_switch_roots, sdb,
+ STMT_UPDATE_IPROP));
+ while (have_row)
+ {
+ const char *switched_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+ apr_int64_t wc_id = svn_sqlite__column_int64(stmt, 0);
+
+ SVN_ERR(svn_sqlite__bindf(stmt_mark_switch_roots, "is", wc_id,
+ switched_relpath));
+ SVN_ERR(svn_sqlite__bind_iprops(stmt_mark_switch_roots, 3,
+ empty_iprops, iterpool));
+ SVN_ERR(svn_sqlite__step_done(stmt_mark_switch_roots));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
struct upgrade_data_t {
svn_sqlite__db_t *sdb;
@@ -1832,13 +1873,16 @@ svn_wc__upgrade_sdb(int *result_format,
*result_format = 29;
/* FALLTHROUGH */
-#if SVN_WC__VERSION >= 30
case 29:
SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_30, &bb,
scratch_pool));
*result_format = 30;
+
+ case 30:
+ SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_31, &bb,
+ scratch_pool));
+ *result_format = 31;
/* FALLTHROUGH */
-#endif
/* ### future bumps go here. */
#if 0
case XXX-1:
Modified: subversion/trunk/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-metadata.sql?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-metadata.sql Sat Oct 6 16:40:55 2012
@@ -475,6 +475,10 @@ CREATE TABLE NODES (
### anyway. */
file_external INTEGER,
+ /* serialized skel of this node's inherited properties. NULL if this
+ is not the BASE of a WC root node. */
+ inherited_props BLOB,
+
PRIMARY KEY (wc_id, local_relpath, op_depth)
);
@@ -575,6 +579,8 @@ CREATE UNIQUE INDEX I_EXTERNALS_DEFINED
def_local_relpath,
local_relpath);
+/* ------------------------------------------------------------------------- */
+
/* Format 20 introduces NODES and removes BASE_NODE and WORKING_NODE */
-- STMT_UPGRADE_TO_20
@@ -789,7 +795,11 @@ UPDATE nodes SET presence = "server-excl
working copies that were never updated by 1.7.0+ style clients */
UPDATE nodes SET file_external=1 WHERE file_external IS NOT NULL;
-PRAGMA user_version = 30;
+/* Format 31 adds the inherited_props column to the NODES table. */
+-- STMT_UPGRADE_TO_31
+ALTER TABLE NODES ADD COLUMN inherited_props BLOB;
+
+PRAGMA user_version = 31;
-- STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE
SELECT wc_id, local_relpath,
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Sat Oct 6 16:40:55 2012
@@ -149,9 +149,10 @@ INSERT OR REPLACE INTO nodes (
wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
revision, presence, depth, kind, changed_revision, changed_date,
changed_author, checksum, properties, translated_size, last_mod_time,
- dav_cache, symlink_target, file_external, moved_to, moved_here)
+ dav_cache, symlink_target, file_external, moved_to, moved_here,
+ inherited_props)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
- ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22)
+ ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23)
-- STMT_SELECT_BASE_PRESENT
SELECT local_relpath, kind FROM nodes n
@@ -1128,6 +1129,28 @@ WHERE wc_id = ?1 AND local_relpath = ?2
SELECT 1 FROM nodes WHERE op_depth > 0
LIMIT 1
+-- STMT_SELECT_WCROOT_NODES
+/* Select all base nodes which are the root of a WC, including
+ switched subtrees, but excluding those which map to the root
+ of the repos.
+
+ ### IPROPS: Is this query horribly inefficient? Quite likely,
+ ### but it only runs during an upgrade, so do we care? */
+SELECT l.wc_id, l.local_relpath FROM nodes as l
+LEFT OUTER JOIN nodes as r
+ON l.wc_id = r.wc_id
+ AND l.repos_id = r.repos_id
+ AND r.local_relpath = l.parent_relpath
+WHERE (l.local_relpath == '' AND l.repos_path != '')
+ OR (l.op_depth = 0
+ AND l.local_relpath != ''
+ AND l.repos_path != ltrim(r.repos_path
+ || '/'
+ || ltrim(substr(l.local_relpath,
+ length(l.parent_relpath) + 1),
+ '/'),
+ '/'))
+
/* --------------------------------------------------------------------------
* Complex queries for callback walks, caching results in a temporary table.
*
@@ -1491,6 +1514,40 @@ WHERE wc_id == ?1
/* ------------------------------------------------------------------------- */
+/* Queries for cached inherited properties. */
+
+/* Select the inherited properties of a single base node. */
+-- STMT_SELECT_IPROPS
+SELECT inherited_props FROM nodes
+WHERE wc_id = ?1
+ AND local_relpath = ?2
+ AND op_depth = 0
+
+/* Update the inherited properties of a single base node. */
+-- STMT_UPDATE_IPROP
+UPDATE nodes
+SET inherited_props = ?3
+WHERE (wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0)
+
+/* Select a single path if its base node has cached inherited properties. */
+-- STMT_SELECT_INODES
+SELECT local_relpath FROM nodes
+WHERE wc_id = ?1
+ AND local_relpath = ?2
+ AND op_depth = 0
+ AND (inherited_props not null)
+
+/* Select all paths whose base nodes at or below a given path, which
+ have cached inherited properties. */
+-- STMT_SELECT_INODES_RECURSIVE
+SELECT local_relpath FROM nodes
+WHERE wc_id = ?1
+ AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+ AND op_depth = 0
+ AND (inherited_props not null)
+
+/* ------------------------------------------------------------------------- */
+
/* Grab all the statements related to the schema. */
-- include: wc-metadata
Modified: subversion/trunk/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc.h?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc.h Sat Oct 6 16:40:55 2012
@@ -154,10 +154,13 @@ extern "C" {
* The bump to 30 switched the conflict storage to a skel inside conflict_data.
* Also clears some known invalid state.
*
+ * The bump to 31 added the inherited_props column in the NODES table.
+ * Bumped in r????????.
+ *
* Please document any further format changes here.
*/
-#define SVN_WC__VERSION 30
+#define SVN_WC__VERSION 31
/* Formats <= this have no concept of "revert text-base/props". */
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1395109&r1=1395108&r2=1395109&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sat Oct 6 16:40:55 2012
@@ -176,6 +176,11 @@ typedef struct insert_base_baton_t {
svn_boolean_t update_actual_props;
const apr_hash_t *new_actual_props;
+ /* A depth-first ordered array of svn_prop_inherited_item_t *
+ structures representing the properties inherited by the base
+ node. */
+ apr_array_header_t *iprops;
+
/* maybe we should copy information from a previous record? */
svn_boolean_t keep_recorded_info;
@@ -249,6 +254,7 @@ typedef struct insert_external_baton_t {
/* for file and symlink externals */
const apr_hash_t *props;
+ apr_array_header_t *iprops;
svn_revnum_t changed_rev;
apr_time_t changed_date;
const char *changed_author;
@@ -829,6 +835,10 @@ insert_base_node(void *baton,
SVN_ERR(svn_sqlite__bind_properties(stmt, 15, pibb->props,
scratch_pool));
+
+ SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, pibb->iprops,
+ scratch_pool));
+
if (pibb->dav_cache)
SVN_ERR(svn_sqlite__bind_properties(stmt, 18, pibb->dav_cache,
scratch_pool));
@@ -1676,6 +1686,7 @@ svn_wc__db_base_add_directory(svn_wc__db
const svn_skel_t *conflict,
svn_boolean_t update_actual_props,
apr_hash_t *new_actual_props,
+ apr_array_header_t *new_iprops,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -1710,6 +1721,7 @@ svn_wc__db_base_add_directory(svn_wc__db
ibb.repos_relpath = repos_relpath;
ibb.revision = revision;
+ ibb.iprops = new_iprops;
ibb.props = props;
ibb.changed_rev = changed_rev;
ibb.changed_date = changed_date;
@@ -2973,6 +2985,7 @@ insert_external_node(void *baton,
ibb.revision = ieb->revision;
ibb.props = ieb->props;
+ ibb.iprops = ieb->iprops;
ibb.changed_rev = ieb->changed_rev;
ibb.changed_date = ieb->changed_date;
ibb.changed_author = ieb->changed_author;
@@ -3037,6 +3050,7 @@ svn_wc__db_external_add_file(svn_wc__db_
svn_revnum_t revision,
const apr_hash_t *props,
+ apr_array_header_t *iprops,
svn_revnum_t changed_rev,
apr_time_t changed_date,
@@ -3091,6 +3105,7 @@ svn_wc__db_external_add_file(svn_wc__db_
ieb.revision = revision;
ieb.props = props;
+ ieb.iprops = iprops;
ieb.changed_rev = changed_rev;
ieb.changed_date = changed_date;
@@ -9309,6 +9324,175 @@ svn_wc__db_prop_retrieve_recursive(apr_h
return svn_error_trace(svn_sqlite__reset(stmt));
}
+svn_error_t *
+svn_wc__db_read_cached_iprops(apr_array_header_t **iprops,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ const char *repos_root_url;
+ svn_revnum_t revision;
+ int op_depth;
+ const char *repos_relpath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_read_info(NULL, NULL,
+ &revision, &repos_relpath, &repos_root_url,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, db, local_abspath, result_pool,
+ scratch_pool));
+
+ if (repos_relpath && repos_relpath[0] == '\0')
+ {
+ /* LOCAL_ABSPATH reflects the root of the repository, so there is
+ no parents to inherit from. */
+ *iprops = apr_array_make(result_pool, 0,
+ sizeof(svn_prop_inherited_item_t *));
+ }
+ else
+ {
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+ db, local_abspath,
+ scratch_pool,
+ scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_IPROPS));
+ SVN_ERR(op_depth_of(&op_depth, wcroot, local_relpath));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (!have_row)
+ {
+ /* No cached iprops. */
+ *iprops = NULL;
+ }
+ else
+ {
+ SVN_ERR(svn_sqlite__column_iprops(iprops, stmt, 0, result_pool,
+ scratch_pool));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Recursive body of svn_wc__db_get_children_with_cached_iprops. */
+static svn_error_t *
+get_children_with_cached_iprops(apr_hash_t *iprop_paths,
+ svn_depth_t depth,
+ const char *local_abspath,
+ svn_wc__db_t *db,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+ local_abspath, scratch_pool,
+ scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+ if (depth == svn_depth_empty
+ || depth == svn_depth_files
+ || depth == svn_depth_immediates)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_INODES));
+ }
+ else /* Default to svn_depth_infinity. */
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_INODES_RECURSIVE));
+ }
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ while (have_row)
+ {
+ const char *relpath_with_cache = svn_sqlite__column_text(stmt, 0,
+ NULL);
+ const char *abspath_with_cache = svn_dirent_join(wcroot->abspath,
+ relpath_with_cache,
+ result_pool);
+ apr_hash_set(iprop_paths, abspath_with_cache, APR_HASH_KEY_STRING,
+ abspath_with_cache);
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ if (depth == svn_depth_files || depth == svn_depth_immediates)
+ {
+ const apr_array_header_t *rel_children;
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+ SVN_ERR(svn_wc__db_read_children_of_working_node(&rel_children,
+ db, local_abspath,
+ scratch_pool,
+ scratch_pool));
+ for (i = 0; i < rel_children->nelts; i++)
+ {
+ const char *child_abspath;
+
+ svn_pool_clear(iterpool);
+ child_abspath = svn_dirent_join(
+ local_abspath, APR_ARRAY_IDX(rel_children, i, const char *),
+ iterpool);
+
+ if (depth == svn_depth_files)
+ {
+ svn_kind_t child_kind;
+
+ SVN_ERR(svn_wc__db_read_kind(&child_kind, db, child_abspath,
+ FALSE, FALSE, iterpool));
+ if (child_kind != svn_kind_file)
+ continue;
+ }
+
+ SVN_ERR(get_children_with_cached_iprops(iprop_paths,
+ svn_depth_empty,
+ child_abspath, db,
+ result_pool,
+ iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_get_children_with_cached_iprops(apr_hash_t **iprop_paths,
+ svn_depth_t depth,
+ const char *local_abspath,
+ svn_wc__db_t *db,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *iprop_paths = apr_hash_make(result_pool);
+ SVN_ERR(get_children_with_cached_iprops(*iprop_paths, depth,
+ local_abspath, db, result_pool,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc__db_read_children_of_working_node(const apr_array_header_t **children,
@@ -10153,19 +10337,22 @@ svn_wc__db_global_update(svn_wc__db_t *d
#endif
}
-/* Sets a base nodes revision and/or repository relative path. If
- LOCAL_ABSPATH's rev (REV) is valid, set is revision and if SET_REPOS_RELPATH
- is TRUE set its repository relative path to REPOS_RELPATH (and make sure its
- REPOS_ID is still valid).
+/* Sets a base nodes revision, repository relative path, and/or inherited
+ propertis. If LOCAL_ABSPATH's rev (REV) is valid, set its revision. If
+ SET_REPOS_RELPATH is TRUE set its repository relative path to REPOS_RELPATH
+ (and make sure its REPOS_ID is still valid). If IPROPS is not NULL set its
+ inherited properties to IPROPS, if IPROPS is NULL then clear any the iprops
+ cache for the base node.
*/
static svn_error_t *
-db_op_set_rev_and_repos_relpath(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- svn_revnum_t rev,
- svn_boolean_t set_repos_relpath,
- const char *repos_relpath,
- apr_int64_t repos_id,
- apr_pool_t *scratch_pool)
+db_op_set_rev_repos_relpath_iprops(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_array_header_t *iprops,
+ svn_revnum_t rev,
+ svn_boolean_t set_repos_relpath,
+ const char *repos_relpath,
+ apr_int64_t repos_id,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
@@ -10197,6 +10384,15 @@ db_op_set_rev_and_repos_relpath(svn_wc__
SVN_ERR(svn_sqlite__step_done(stmt));
}
+ /* Set or clear iprops. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_UPDATE_IPROP));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is",
+ wcroot->wc_id,
+ local_relpath));
+ SVN_ERR(svn_sqlite__bind_iprops(stmt, 3, iprops, scratch_pool));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
return SVN_NO_ERROR;
}
@@ -10204,7 +10400,13 @@ db_op_set_rev_and_repos_relpath(svn_wc__
*
* Tweak the information for LOCAL_RELPATH in WCROOT. If NEW_REPOS_RELPATH is
* non-NULL update the entry to the new url specified by NEW_REPOS_RELPATH,
- * NEW_REPOS_ID.. If NEW_REV is valid, make this the node's working revision.
+ * NEW_REPOS_ID. If NEW_REV is valid, make this the node's working revision.
+ *
+ * If WCROOT_IPROPS is not NULL it is a hash mapping const char * absolute
+ * working copy paths to depth-first ordered arrays of
+ * svn_prop_inherited_item_t * structures. If the absolute path equivalent
+ * of LOCAL_RELPATH exists in WCROOT_IPROPS, then set the hashed value as the
+ * node's inherited properties.
*
* Unless S_ROOT is TRUE the tweaks might cause the node for LOCAL_ABSPATH to
* be removed from the WC; if IS_ROOT is TRUE this will not happen.
@@ -10217,6 +10419,7 @@ bump_node_revision(svn_wc__db_wcroot_t *
svn_revnum_t new_rev,
svn_depth_t depth,
apr_hash_t *exclude_relpaths,
+ apr_hash_t *wcroot_iprops,
svn_boolean_t is_root,
svn_boolean_t skip_when_dir,
svn_wc__db_t *db,
@@ -10233,6 +10436,7 @@ bump_node_revision(svn_wc__db_wcroot_t *
svn_boolean_t set_repos_relpath = FALSE;
svn_boolean_t update_root;
svn_depth_t depth_below_here = depth;
+ apr_array_header_t *iprops = NULL;
/* Skip an excluded path and its descendants. */
if (apr_hash_get(exclude_relpaths, local_relpath, APR_HASH_KEY_STRING))
@@ -10278,14 +10482,23 @@ bump_node_revision(svn_wc__db_wcroot_t *
if (new_repos_relpath != NULL && strcmp(repos_relpath, new_repos_relpath))
set_repos_relpath = TRUE;
- if (set_repos_relpath
+ if (wcroot_iprops)
+ iprops = apr_hash_get(wcroot_iprops,
+ svn_dirent_join(wcroot->abspath, local_relpath,
+ scratch_pool),
+ APR_HASH_KEY_STRING);
+
+ if (iprops
+ || set_repos_relpath
|| (SVN_IS_VALID_REVNUM(new_rev) && new_rev != revision))
- SVN_ERR(db_op_set_rev_and_repos_relpath(wcroot, local_relpath,
- new_rev,
- set_repos_relpath,
- new_repos_relpath,
- new_repos_id,
- scratch_pool));
+ {
+ SVN_ERR(db_op_set_rev_repos_relpath_iprops(wcroot, local_relpath,
+ iprops, new_rev,
+ set_repos_relpath,
+ new_repos_relpath,
+ new_repos_id,
+ scratch_pool));
+ }
/* Early out */
if (depth <= svn_depth_empty
@@ -10325,7 +10538,8 @@ bump_node_revision(svn_wc__db_wcroot_t *
SVN_ERR(bump_node_revision(wcroot, child_local_relpath, new_repos_id,
child_repos_relpath, new_rev,
depth_below_here,
- exclude_relpaths, FALSE /* is_root */,
+ exclude_relpaths, wcroot_iprops,
+ FALSE /* is_root */,
(depth < svn_depth_immediates), db,
iterpool));
}
@@ -10345,6 +10559,7 @@ struct bump_revisions_baton_t
const char *new_repos_uuid;
svn_revnum_t new_revision;
apr_hash_t *exclude_relpaths;
+ apr_hash_t *wcroot_iprops;
svn_wc__db_t *db;
};
@@ -10391,6 +10606,7 @@ bump_revisions_post_update(void *baton,
SVN_ERR(bump_node_revision(wcroot, local_relpath, new_repos_id,
brb->new_repos_relpath, brb->new_revision,
brb->depth, brb->exclude_relpaths,
+ brb->wcroot_iprops,
TRUE /* is_root */, FALSE, brb->db,
scratch_pool));
@@ -10406,6 +10622,7 @@ svn_wc__db_op_bump_revisions_post_update
const char *new_repos_uuid,
svn_revnum_t new_revision,
apr_hash_t *exclude_relpaths,
+ apr_hash_t *wcroot_iprops,
apr_pool_t *scratch_pool)
{
const char *local_relpath;
@@ -10429,6 +10646,7 @@ svn_wc__db_op_bump_revisions_post_update
brb.new_repos_uuid = new_repos_uuid;
brb.new_revision = new_revision;
brb.exclude_relpaths = exclude_relpaths;
+ brb.wcroot_iprops = wcroot_iprops;
brb.db = db;
SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath,