Author: cmpilato
Date: Thu Oct 11 15:33:08 2012
New Revision: 1397110
URL: http://svn.apache.org/viewvc?rev=1397110&view=rev
Log:
On the 'http-dynamic-prop-namespaces' branch: teach libsvn_ra_serf to
transmit properties using the extensible property XML namespace as
necessary and available. (Though, it's currently always unavailable.
We need to parse the capability stuff from the server.)
* subversion/libsvn_ra_serf/ra_serf.h,
* subversion/libsvn_ra_serf/property.c
(svn_ra_serf__wirename_from_svnname): New function.
* subversion/libsvn_ra_serf/commit.c
(file_context_t): Add 'use_ext_prop_ns' flag. Also, add
'propname_to_xmlname' and 'xmlprefix_to_xmlns' mapping hashes.
(populate_prop_maps): New helper function.
(walker_baton_t): Add 'propname_to_xmlname' mapping hash.
(proppatch_walker): Lookup property wire names in the mapping hash.
(create_proppatch_body): Define XML namespaces as necessary, and
initialize walker_baton_t's new member.
(change_file_prop, change_dir_prop): Convert the property name into
a wire namespace and bare name, and populate the mapping hashes.
Modified:
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/commit.c
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/property.c
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/ra_serf.h
Modified:
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/commit.c
URL:
http://svn.apache.org/viewvc/subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/commit.c?rev=1397110&r1=1397109&r2=1397110&view=diff
==============================================================================
---
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/commit.c
(original)
+++
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/commit.c
Thu Oct 11 15:33:08 2012
@@ -61,6 +61,11 @@ typedef struct commit_context_t {
svn_boolean_t keep_locks;
apr_hash_t *deleted_entries; /* deleted files (for delete+add detection) */
+ /* Stuff for extensible property XML namespaces. */
+ svn_boolean_t use_ext_prop_ns;
+ apr_hash_t *propname_to_xmlname; /* svn propname -> xml tag name */
+ apr_hash_t *xmlprefix_to_xmlns; /* xml prefix -> xml namespace */
+
/* HTTP v2 stuff */
const char *txn_url; /* txn URL (!svn/txn/TXN_NAME) */
const char *txn_root_url; /* commit anchor txn root URL */
@@ -199,6 +204,54 @@ typedef struct file_context_t {
} file_context_t;
+/* Property name/XML name/namespace map management. */
+
+
+/* Examine Subversion property name SVNNAME and its wire components NS
+ and NAME, adding them as necessary to the mapping hashes associated
+ with COMMIT_CTX. */
+static void
+populate_prop_maps(commit_context_t *commit_ctx,
+ const char *svnname,
+ const char *ns,
+ const char *name)
+{
+ apr_pool_t *p2x_pool = apr_hash_pool_get(commit_ctx->propname_to_xmlname);
+ apr_pool_t *x2x_pool = apr_hash_pool_get(commit_ctx->xmlprefix_to_xmlns);
+
+ /* If we've already mapped this property name, don't do it
+ again. */
+ if (apr_hash_get(commit_ctx->propname_to_xmlname, svnname,
+ APR_HASH_KEY_STRING))
+ return;
+
+ if (strncmp(ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ const char *xmlprefix =
+ apr_psprintf(x2x_pool, "svn%d",
+ apr_hash_count(commit_ctx->xmlprefix_to_xmlns));
+ apr_hash_set(commit_ctx->xmlprefix_to_xmlns, xmlprefix,
+ APR_HASH_KEY_STRING, apr_pstrdup(x2x_pool, ns));
+ apr_hash_set(commit_ctx->propname_to_xmlname,
+ apr_pstrdup(p2x_pool, svnname), APR_HASH_KEY_STRING,
+ apr_pstrcat(p2x_pool, xmlprefix, name, NULL));
+ }
+ else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
+ {
+ apr_hash_set(commit_ctx->propname_to_xmlname,
+ apr_pstrdup(p2x_pool, svnname), APR_HASH_KEY_STRING,
+ apr_pstrcat(p2x_pool, "S:", name, NULL));
+ }
+ else
+ {
+ apr_hash_set(commit_ctx->propname_to_xmlname,
+ apr_pstrdup(p2x_pool, svnname), APR_HASH_KEY_STRING,
+ apr_pstrcat(p2x_pool, "C:", name, NULL));
+ }
+}
+
+
/* Setup routines and handlers for various requests we'll invoke. */
static svn_error_t *
@@ -614,6 +667,10 @@ typedef struct walker_baton_t {
/* Is the property being deleted? */
svn_boolean_t deleting;
+
+ /* Mapping of actual property name to XML property name. */
+ apr_hash_t *propname_to_xmlname;
+
} walker_baton_t;
/* If we have (recorded in WB) the old value of the property named NS:NAME,
@@ -703,10 +760,7 @@ proppatch_walker(void *baton,
/* Use the namespace prefix instead of adding the xmlns attribute to support
property names containing ':' */
- if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
- prop_name = apr_pstrcat(wb->body_pool, "S:", name, (char *)NULL);
- else if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
- prop_name = apr_pstrcat(wb->body_pool, "C:", name, (char *)NULL);
+ prop_name = apr_hash_get(wb->propname_to_xmlname, name, APR_HASH_KEY_STRING);
if (cdata_bkt)
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
@@ -841,22 +895,44 @@ create_proppatch_body(serf_bucket_t **bk
proppatch_context_t *ctx = pbb->proppatch;
serf_bucket_t *body_bkt;
walker_baton_t wb = { 0 };
+ apr_hash_t *xmlns_attrs = apr_hash_make(scratch_pool);
+ apr_hash_index_t *hi;
body_bkt = serf_bucket_aggregate_create(alloc);
+ /* Add our four stock xmlns prefix mappings. */
+ apr_hash_set(xmlns_attrs, "xmlns:D", APR_HASH_KEY_STRING,
+ "DAV:");
+ apr_hash_set(xmlns_attrs, "xmlns:V", APR_HASH_KEY_STRING,
+ SVN_DAV_PROP_NS_DAV);
+ apr_hash_set(xmlns_attrs, "xmlns:C", APR_HASH_KEY_STRING,
+ SVN_DAV_PROP_NS_CUSTOM);
+ apr_hash_set(xmlns_attrs, "xmlns:S", APR_HASH_KEY_STRING,
+ SVN_DAV_PROP_NS_SVN);
+ for (hi = apr_hash_first(scratch_pool,
+ ctx->commit->xmlprefix_to_xmlns);
+ hi; hi = apr_hash_next(hi))
+ {
+ const void *key;
+ apr_ssize_t klen;
+ void *val;
+
+ apr_hash_this(hi, &key, &klen, &val);
+ apr_hash_set(xmlns_attrs,
+ apr_pstrcat(scratch_pool, "xmlns:", key, NULL),
+ klen + 6, val);
+ }
+
svn_ra_serf__add_xml_header_buckets(body_bkt, alloc);
- svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:propertyupdate",
- "xmlns:D", "DAV:",
- "xmlns:V", SVN_DAV_PROP_NS_DAV,
- "xmlns:C", SVN_DAV_PROP_NS_CUSTOM,
- "xmlns:S", SVN_DAV_PROP_NS_SVN,
- NULL);
+ svn_ra_serf__add_open_tag_attrs_buckets(body_bkt, alloc, "D:propertyupdate",
+ xmlns_attrs);
wb.body_bkt = body_bkt;
wb.body_pool = pbb->body_pool;
wb.previous_changed_props = ctx->previous_changed_props;
wb.previous_removed_props = ctx->previous_removed_props;
wb.path = ctx->path;
+ wb.propname_to_xmlname = ctx->commit->propname_to_xmlname;
if (apr_hash_count(ctx->changed_props) > 0)
{
@@ -1739,12 +1815,12 @@ open_directory(const char *path,
static svn_error_t *
change_dir_prop(void *dir_baton,
- const char *name,
+ const char *propname,
const svn_string_t *value,
apr_pool_t *pool)
{
dir_context_t *dir = dir_baton;
- const char *ns;
+ const char *ns, *name;
const char *proppatch_target;
@@ -1760,16 +1836,13 @@ change_dir_prop(void *dir_baton,
proppatch_target = dir->working_url;
}
- name = apr_pstrdup(dir->pool, name);
- if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
- {
- ns = SVN_DAV_PROP_NS_SVN;
- name += sizeof(SVN_PROP_PREFIX) - 1;
- }
- else
- {
- ns = SVN_DAV_PROP_NS_CUSTOM;
- }
+ /* Calculate the wirename bits for this property name. */
+ svn_ra_serf__wirename_from_svnname(&ns, &name, propname,
+ dir->commit->use_ext_prop_ns,
+ dir->pool);
+
+ /* Register this property name with the mapping system. */
+ populate_prop_maps(dir->commit, propname, ns, name);
if (value)
{
@@ -1993,24 +2066,20 @@ apply_textdelta(void *file_baton,
static svn_error_t *
change_file_prop(void *file_baton,
- const char *name,
+ const char *propname,
const svn_string_t *value,
apr_pool_t *pool)
{
file_context_t *file = file_baton;
- const char *ns;
+ const char *ns, *name;
- name = apr_pstrdup(file->pool, name);
+ /* Calculate the wirename bits for this property name. */
+ svn_ra_serf__wirename_from_svnname(&ns, &name, propname,
+ file->commit->use_ext_prop_ns,
+ file->pool);
- if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
- {
- ns = SVN_DAV_PROP_NS_SVN;
- name += sizeof(SVN_PROP_PREFIX) - 1;
- }
- else
- {
- ns = SVN_DAV_PROP_NS_CUSTOM;
- }
+ /* Register this property name with the mapping system. */
+ populate_prop_maps(file->commit, propname, ns, name);
if (value)
{
@@ -2315,6 +2384,10 @@ svn_ra_serf__get_commit_editor(svn_ra_se
ctx->deleted_entries = apr_hash_make(ctx->pool);
+ ctx->use_ext_prop_ns = FALSE; /* temporary */
+ ctx->propname_to_xmlname = apr_hash_make(ctx->pool);
+ ctx->xmlprefix_to_xmlns = apr_hash_make(ctx->pool);
+
editor = svn_delta_default_editor(pool);
editor->open_root = open_root;
editor->delete_entry = delete_entry;
Modified:
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/property.c
URL:
http://svn.apache.org/viewvc/subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/property.c?rev=1397110&r1=1397109&r2=1397110&view=diff
==============================================================================
---
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/property.c
(original)
+++
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/property.c
Thu Oct 11 15:33:08 2012
@@ -832,6 +832,64 @@ svn_ra_serf__walk_all_paths(apr_hash_t *
}
+void
+svn_ra_serf__wirename_from_svnname(const char **ns,
+ const char **name,
+ const char *svnname,
+ svn_boolean_t use_ext_prop_ns,
+ apr_pool_t *result_pool)
+{
+ /* If we're allowed to use the extensible property namespace... */
+ if (use_ext_prop_ns)
+ {
+ const char *colon;
+
+ /* If there's no colon in this property name, it's a custom
+ property (C:name). */
+ colon = strrchr(svnname, ':');
+ if (! colon)
+ {
+ *ns = SVN_DAV_PROP_NS_CUSTOM;
+ *name = apr_pstrdup(result_pool, svnname);
+ }
+ /* Otherwise... */
+ else
+ {
+ /* If the property name prefix is merely "svn:", it's a
+ Subversion property (S:name-without-the-prefix). */
+ if (strncmp(svnname, "svn:", colon - svnname) == 0)
+ {
+ *ns = SVN_DAV_PROP_NS_SVN;
+ }
+ /* ...but anything else requires the extensible namespace. */
+ else
+ {
+ *ns = svn_path_url_add_component2(SVN_DAV_PROP_NS_EXTENSIBLE,
+ apr_pstrndup(result_pool,
+ svnname,
+ colon - svnname),
+ result_pool);
+ }
+
+ /* Either way, the base name begins after the colon. */
+ *name = apr_pstrdup(result_pool, colon + 1);
+ }
+ }
+ else
+ {
+ if (strncmp(svnname, "svn:", 4) == 0)
+ {
+ *ns = SVN_DAV_PROP_NS_SVN;
+ *name = apr_pstrdup(result_pool, svnname + 4);
+ }
+ else
+ {
+ *ns = SVN_DAV_PROP_NS_CUSTOM;
+ *name = apr_pstrdup(result_pool, svnname);
+ }
+ }
+}
+
const char *
svn_ra_serf__svnname_from_wirename(const char *ns,
const char *name,
Modified:
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/ra_serf.h
URL:
http://svn.apache.org/viewvc/subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/ra_serf.h?rev=1397110&r1=1397109&r2=1397110&view=diff
==============================================================================
---
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/ra_serf.h
(original)
+++
subversion/branches/http-dynamic-prop-namespaces/subversion/libsvn_ra_serf/ra_serf.h
Thu Oct 11 15:33:08 2012
@@ -1203,6 +1203,19 @@ svn_ra_serf__walk_all_paths(apr_hash_t *
apr_pool_t *pool);
+/* Map a property SVNNAME as referred to internally by Subversion to
+ its corresponding wire namespace (*NS) and *NAME.
+
+ If USE_EXT_PROP_NS is set, the function may make use of the
+ extensible property XML namespace (SVN_DAV_PROP_NS_EXTENSIBLE). */
+void
+svn_ra_serf__wirename_from_svnname(const char **ns,
+ const char **name,
+ const char *svnname,
+ svn_boolean_t use_ext_prop_ns,
+ apr_pool_t *result_pool);
+
+
/* Map a property name, as passed over the wire, into its corresponding
Subversion-internal name. The returned name will be a static value,
or allocated within RESULT_POOL.