You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/09/10 17:26:52 UTC
svn commit: r995827 -
/subversion/branches/atomic-revprop/subversion/libsvn_ra_serf/commit.c
Author: danielsh
Date: Fri Sep 10 15:26:51 2010
New Revision: 995827
URL: http://svn.apache.org/viewvc?rev=995827&view=rev
Log:
On the 'atomic-revprop' branch, re-implement the API over ra_serf.
* subversion/libsvn_ra_serf/commit.c
(proppatch_ctx_t.previous_changed_props,
proppatch_ctx_t.previous_removed_props):
New members.
(get_encoding_and_cdata): Restore previously-reverted logic, unchanged.
(walker_baton_t): New struct.
(derive_old_val): New helper.
(proppatch_walker):
Restore previously-reverted logic for generating the proper tags,
and add new logic for computing the old value (it isn't passed as
a parameter this time) and filtering support (see below).
(create_proppatch_body):
Pass a walker_baton_t to proppatch_walker().
Iterate CTX->removed_props twice, using the filtering mechanism to ensure
that each property is processed exactly once.
(svn_ra_serf__change_rev_prop):
Remove 'not implemented' sentinel.
Store OLD_VALUE_P in PROPPATCH_CTX, via its 'previous_changed_props' and
'previous_removed_props' members.
Modified:
subversion/branches/atomic-revprop/subversion/libsvn_ra_serf/commit.c
Modified: subversion/branches/atomic-revprop/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_ra_serf/commit.c?rev=995827&r1=995826&r2=995827&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_ra_serf/commit.c Fri Sep 10 15:26:51 2010
@@ -109,6 +109,10 @@ typedef struct {
apr_hash_t *changed_props;
apr_hash_t *removed_props;
+ /* Same, for the old value (*old_value_p). */
+ apr_hash_t *previous_changed_props;
+ apr_hash_t *previous_removed_props;
+
/* In HTTP v2, this is the file/directory version we think we're changing. */
svn_revnum_t base_revision;
@@ -639,16 +643,17 @@ checkout_file(file_context_t *file)
/* Helper function for proppatch_walker() below. */
static svn_error_t *
get_encoding_and_cdata(const char **encoding_p,
- serf_bucket_t **cdata_bkt_p,
+ const svn_string_t **encoded_value_p,
serf_bucket_alloc_t *alloc,
const svn_string_t *value,
apr_pool_t *pool)
{
- const char *encoding;
- const char *cdata;
- apr_size_t len; /* of cdata */
-
- SVN_ERR_ASSERT(value);
+ if (value == NULL)
+ {
+ *encoding_p = NULL;
+ *encoded_value_p = NULL;
+ return SVN_NO_ERROR;
+ }
/* If a property is XML-safe, XML-encode it. Else, base64-encode
it. */
@@ -656,23 +661,72 @@ get_encoding_and_cdata(const char **enco
{
svn_stringbuf_t *xml_esc = NULL;
svn_xml_escape_cdata_string(&xml_esc, value, pool);
- encoding = NULL;
- cdata = xml_esc->data;
- len = xml_esc->len;
+ *encoding_p = NULL;
+ *encoded_value_p = svn_string_create_from_buf(xml_esc, pool);
}
else
{
- const svn_string_t *base64ed = svn_base64_encode_string2(value, TRUE,
- pool);
- encoding = "base64";
- cdata = base64ed->data;
- len = base64ed->len;
+ *encoding_p = "base64";
+ *encoded_value_p = svn_base64_encode_string2(value, TRUE, pool);
}
- /* ENCODING, CDATA, and LEN are now set. */
+ return SVN_NO_ERROR;
+}
- *encoding_p = encoding;
- *cdata_bkt_p = SERF_BUCKET_SIMPLE_STRING_LEN(cdata, len, alloc);
+typedef struct walker_baton_t {
+ serf_bucket_t *body_bkt;
+ apr_hash_t *previous_changed_props;
+ apr_hash_t *previous_removed_props;
+ const char *path;
+
+ /* Hack, since change_rev_prop(old_value_p != NULL, value = NULL) uses D:set
+ rather than D:remove... (see notes/http-and-webdav/webdav-protocol) */
+ enum {
+ filter_all_props,
+ filter_props_with_old_value,
+ filter_props_without_old_value
+ } filter;
+
+ /* Is the property being deleted? */
+ svn_boolean_t deleting;
+} walker_baton_t;
+
+static svn_error_t *
+derive_old_val(const svn_string_t *const * *old_val_p_p,
+ walker_baton_t *wb,
+ const char *ns,
+ const char *name,
+ apr_pool_t *pool)
+{
+ const svn_string_t *const *old_val_p;
+
+ old_val_p = NULL;
+
+ if (wb->previous_changed_props)
+ {
+ const svn_string_t *old_val;
+ old_val = svn_ra_serf__get_prop_string(wb->previous_changed_props,
+ wb->path, ns, name);
+ if (old_val)
+ {
+ old_val_p = apr_pcalloc(pool, sizeof(*old_val_p));
+ *(const svn_string_t **)old_val_p = svn_string_dup(old_val, pool);
+ }
+ }
+
+ if (wb->previous_removed_props)
+ {
+ const svn_string_t *old_val;
+ old_val = svn_ra_serf__get_prop_string(wb->previous_removed_props,
+ wb->path, ns, name);
+ if (old_val)
+ {
+ old_val_p = apr_pcalloc(pool, sizeof(*old_val_p));
+ *(const svn_string_t **)old_val_p = NULL;
+ }
+ }
+
+ *old_val_p_p = old_val_p;
return SVN_NO_ERROR;
}
@@ -683,10 +737,13 @@ proppatch_walker(void *baton,
const svn_string_t *val,
apr_pool_t *pool)
{
- serf_bucket_t *body_bkt = baton;
+ walker_baton_t *wb = baton;
+ serf_bucket_t *body_bkt = wb->body_bkt;
serf_bucket_t *cdata_bkt;
serf_bucket_alloc_t *alloc;
const char *encoding;
+ const svn_string_t *const *old_val_p;
+ const svn_string_t *encoded_value;
char *prop_name;
/* Use the namespace prefix instead of adding the xmlns attribute to support
@@ -697,14 +754,82 @@ proppatch_walker(void *baton,
prop_name = apr_pstrcat(pool, "C:", name, NULL);
name_len = strlen(prop_name);
+ SVN_ERR(derive_old_val(&old_val_p, wb, ns, name, pool));
+
+ /* Jump through hoops to work with D:remove and its val = (""-for-NULL)
+ * representation. */
+ if (wb->filter != filter_all_props)
+ {
+ if (wb->filter == filter_props_with_old_value && ! old_val_p)
+ return SVN_NO_ERROR;
+ if (wb->filter == filter_props_without_old_value && old_val_p)
+ return SVN_NO_ERROR;
+ }
+ if (wb->deleting)
+ val = NULL;
+
alloc = body_bkt->allocator;
- SVN_ERR(get_encoding_and_cdata(&encoding, &cdata_bkt, alloc, val, pool));
+ SVN_ERR(get_encoding_and_cdata(&encoding, &encoded_value, alloc, val, pool));
+ if (encoded_value)
+ {
+ cdata_bkt = SERF_BUCKET_SIMPLE_STRING_LEN(encoded_value->data,
+ encoded_value->len,
+ alloc);
+ }
+ else
+ {
+ cdata_bkt = NULL;
+ }
- svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
- "V:encoding", encoding,
- NULL);
- serf_bucket_aggregate_append(body_bkt, cdata_bkt);
+ if (cdata_bkt)
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+ "V:encoding", encoding,
+ NULL);
+ else
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+ "V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
+ NULL);
+
+ if (old_val_p)
+ {
+ const char *encoding2;
+ const svn_string_t *encoded_value2;
+ serf_bucket_t *cdata_bkt2;
+
+ SVN_ERR(get_encoding_and_cdata(&encoding2, &encoded_value2,
+ alloc, *old_val_p, pool));
+
+ if (encoded_value2)
+ {
+ cdata_bkt2 = SERF_BUCKET_SIMPLE_STRING_LEN(encoded_value2->data,
+ encoded_value2->len,
+ alloc);
+ }
+ else
+ {
+ cdata_bkt2 = NULL;
+ }
+
+ if (cdata_bkt2)
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+ "V:" SVN_DAV__OLD_VALUE,
+ "V:encoding", encoding2,
+ NULL);
+ else
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+ "V:" SVN_DAV__OLD_VALUE,
+ "V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
+ NULL);
+
+ if (cdata_bkt2)
+ serf_bucket_aggregate_append(body_bkt, cdata_bkt2);
+
+ svn_ra_serf__add_close_tag_buckets(body_bkt, alloc,
+ "V:" SVN_DAV__OLD_VALUE);
+ }
+ if (cdata_bkt)
+ serf_bucket_aggregate_append(body_bkt, cdata_bkt);
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, prop_name);
return SVN_NO_ERROR;
@@ -753,6 +878,7 @@ create_proppatch_body(serf_bucket_t **bk
{
proppatch_context_t *ctx = baton;
serf_bucket_t *body_bkt;
+ walker_baton_t *wb;
body_bkt = serf_bucket_aggregate_create(alloc);
@@ -764,14 +890,37 @@ create_proppatch_body(serf_bucket_t **bk
"xmlns:S", SVN_DAV_PROP_NS_SVN,
NULL);
+ wb = apr_pcalloc(pool, sizeof(*wb));
+ wb->body_bkt = body_bkt;
+ wb->previous_changed_props = ctx->previous_changed_props;
+ wb->previous_removed_props = ctx->previous_removed_props;
+ wb->path = ctx->path;
+
if (apr_hash_count(ctx->changed_props) > 0)
{
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:set", NULL);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+ wb->filter = filter_all_props;
+ wb->deleting = FALSE;
SVN_ERR(svn_ra_serf__walk_all_props(ctx->changed_props, ctx->path,
SVN_INVALID_REVNUM,
- proppatch_walker, body_bkt, pool));
+ proppatch_walker, wb, pool));
+
+ svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
+ svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:set");
+ }
+
+ if (apr_hash_count(ctx->removed_props) > 0)
+ {
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:set", NULL);
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+
+ wb->filter = filter_props_with_old_value;
+ wb->deleting = TRUE;
+ SVN_ERR(svn_ra_serf__walk_all_props(ctx->removed_props, ctx->path,
+ SVN_INVALID_REVNUM,
+ proppatch_walker, wb, pool));
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:set");
@@ -782,9 +931,11 @@ create_proppatch_body(serf_bucket_t **bk
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:remove", NULL);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+ wb->filter = filter_props_without_old_value;
+ wb->deleting = TRUE;
SVN_ERR(svn_ra_serf__walk_all_props(ctx->removed_props, ctx->path,
SVN_INVALID_REVNUM,
- proppatch_walker, body_bkt, pool));
+ proppatch_walker, wb, pool));
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:remove");
@@ -2229,9 +2380,6 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
/* How did you get past the same check in svn_ra_change_rev_prop2()? */
SVN_ERR_ASSERT(capable);
-
- /* ### server-side support hasn't been implemented yet */
- SVN__NOT_IMPLEMENTED();
}
commit = apr_pcalloc(pool, sizeof(*commit));
@@ -2280,8 +2428,28 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
proppatch_ctx->path = proppatch_target;
proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
proppatch_ctx->removed_props = apr_hash_make(proppatch_ctx->pool);
+ if (old_value_p)
+ {
+ proppatch_ctx->previous_changed_props = apr_hash_make(proppatch_ctx->pool);
+ proppatch_ctx->previous_removed_props = apr_hash_make(proppatch_ctx->pool);
+ }
proppatch_ctx->base_revision = SVN_INVALID_REVNUM;
+ if (old_value_p && *old_value_p)
+ {
+ svn_ra_serf__set_prop(proppatch_ctx->previous_changed_props,
+ proppatch_ctx->path,
+ ns, name, *old_value_p, proppatch_ctx->pool);
+ }
+ else if (old_value_p)
+ {
+ svn_string_t *dummy_value = svn_string_create("", proppatch_ctx->pool);
+
+ svn_ra_serf__set_prop(proppatch_ctx->previous_removed_props,
+ proppatch_ctx->path,
+ ns, name, dummy_value, proppatch_ctx->pool);
+ }
+
if (value)
{
svn_ra_serf__set_prop(proppatch_ctx->changed_props, proppatch_ctx->path,