You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/11/04 21:48:30 UTC
svn commit: r1031230 [6/21] - in /subversion/branches/py-tests-as-modules:
./ build/ build/ac-macros/ build/win32/ contrib/client-side/ notes/
notes/http-and-webdav/ notes/wc-ng/ subversion/bindings/ctypes-python/csvn/
subversion/bindings/javahl/native...
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/props.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/props.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/props.c Thu Nov 4 20:48:21 2010
@@ -441,7 +441,7 @@ static svn_error_t * end_element(void *b
if (state == ELEM_unknown)
{
- name = apr_pstrcat(pc->pool, nspace, name, NULL);
+ name = apr_pstrcat(pc->pool, nspace, name, (char *)NULL);
}
else
{
@@ -529,7 +529,8 @@ svn_error_t * svn_ra_neon__get_props(apr
svn_pool_clear(iterpool);
svn_stringbuf_appendcstr
(body, apr_pstrcat(iterpool, "<", which_props[n].name, " xmlns=\"",
- which_props[n].nspace, "\"/>" DEBUG_CR, NULL));
+ which_props[n].nspace, "\"/>" DEBUG_CR,
+ (char *)NULL));
}
svn_stringbuf_appendcstr(body, "</prop></propfind>" DEBUG_CR);
svn_pool_destroy(iterpool);
@@ -626,7 +627,7 @@ svn_error_t * svn_ra_neon__get_one_prop(
SVN_ERR(svn_ra_neon__get_props_resource(&rsrc, sess, url, label, props,
pool));
- name = apr_pstrcat(pool, propname->nspace, propname->name, NULL);
+ name = apr_pstrcat(pool, propname->nspace, propname->name, (char *)NULL);
value = apr_hash_get(rsrc->propset, name, APR_HASH_KEY_STRING);
if (value == NULL)
{
@@ -1075,30 +1076,66 @@ get_encoding_and_cdata(const char **enco
static svn_error_t *
append_setprop(svn_stringbuf_t *body,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
{
const char *encoding;
const char *xml_safe;
const char *xml_tag_name;
+ const char *old_value_tag;
/* Map property names to namespaces */
#define NSLEN (sizeof(SVN_PROP_PREFIX) - 1)
if (strncmp(name, SVN_PROP_PREFIX, NSLEN) == 0)
{
- xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, NULL);
+ xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, (char *)NULL);
}
#undef NSLEN
else
{
- xml_tag_name = apr_pstrcat(pool, "C:", name, NULL);
+ xml_tag_name = apr_pstrcat(pool, "C:", name, (char *)NULL);
}
- SVN_ERR(get_encoding_and_cdata(&encoding, &xml_safe, value, pool));
+ if (old_value_p)
+ {
+ if (*old_value_p)
+ {
+ const char *encoding2;
+ const char *xml_safe2;
+ SVN_ERR(get_encoding_and_cdata(&encoding2, &xml_safe2,
+ *old_value_p, pool));
+ old_value_tag = apr_psprintf(pool, "<%s %s>%s</%s>",
+ "V:" SVN_DAV__OLD_VALUE, encoding2,
+ xml_safe2, "V:" SVN_DAV__OLD_VALUE);
+ }
+ else
+ {
+#define OLD_VALUE_ABSENT_TAG \
+ "<" "V:" SVN_DAV__OLD_VALUE \
+ " V:" SVN_DAV__OLD_VALUE__ABSENT "=\"1\" " \
+ "/>"
+ old_value_tag = OLD_VALUE_ABSENT_TAG;
+ }
+ }
+ else
+ {
+ old_value_tag = "";
+ }
+
+ if (old_value_p && !value)
+ {
+ encoding = "V:" SVN_DAV__OLD_VALUE__ABSENT "=\"1\"" ;
+ xml_safe = "";
+ }
+ else
+ {
+ SVN_ERR(get_encoding_and_cdata(&encoding, &xml_safe, value, pool));
+ }
svn_stringbuf_appendcstr(body,
- apr_psprintf(pool,"<%s %s>%s</%s>",
- xml_tag_name, encoding,
+ apr_psprintf(pool,"<%s %s>%s%s</%s>",
+ xml_tag_name, encoding, old_value_tag,
xml_safe, xml_tag_name));
return SVN_NO_ERROR;
}
@@ -1109,6 +1146,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
const char *url,
apr_hash_t *prop_changes,
const apr_array_header_t *prop_deletes,
+ apr_hash_t *prop_old_values,
apr_hash_t *extra_headers,
apr_pool_t *pool)
{
@@ -1118,7 +1156,8 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
/* just punt if there are no changes to make. */
if ((prop_changes == NULL || (! apr_hash_count(prop_changes)))
- && (prop_deletes == NULL || prop_deletes->nelts == 0))
+ && (prop_deletes == NULL || prop_deletes->nelts == 0)
+ && (prop_old_values == NULL || (! apr_hash_count(prop_old_values))))
return SVN_NO_ERROR;
/* easier to roll our own PROPPATCH here than use ne_proppatch(), which
@@ -1130,6 +1169,22 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
SVN_DAV_PROP_NS_CUSTOM "\" xmlns:S=\""
SVN_DAV_PROP_NS_SVN "\">" DEBUG_CR, pool);
+ /* Handle property changes/deletions with expected old values. */
+ if (prop_old_values)
+ {
+ apr_hash_index_t *hi;
+ svn_stringbuf_appendcstr(body, "<D:set><D:prop>");
+ for (hi = apr_hash_first(pool, prop_old_values); hi; hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_dav__two_props_t *both_values = svn__apr_hash_index_val(hi);
+ svn_pool_clear(subpool);
+ SVN_ERR(append_setprop(body, name, both_values->old_value_p,
+ both_values->new_value, subpool));
+ }
+ svn_stringbuf_appendcstr(body, "</D:prop></D:set>");
+ }
+
/* Handle property changes. */
if (prop_changes)
{
@@ -1141,7 +1196,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
void *val;
svn_pool_clear(subpool);
apr_hash_this(hi, &key, NULL, &val);
- SVN_ERR(append_setprop(body, key, val, subpool));
+ SVN_ERR(append_setprop(body, key, NULL, val, subpool));
}
svn_stringbuf_appendcstr(body, "</D:prop></D:set>");
}
@@ -1155,7 +1210,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
{
const char *name = APR_ARRAY_IDX(prop_deletes, n, const char *);
svn_pool_clear(subpool);
- SVN_ERR(append_setprop(body, name, NULL, subpool));
+ SVN_ERR(append_setprop(body, name, NULL, NULL, subpool));
}
svn_stringbuf_appendcstr(body, "</D:prop></D:remove>");
}
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/ra_neon.h?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/ra_neon.h Thu Nov 4 20:48:21 2010
@@ -254,6 +254,7 @@ svn_error_t *svn_ra_neon__get_dated_revi
svn_error_t *svn_ra_neon__change_rev_prop(svn_ra_session_t *session,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool);
@@ -575,12 +576,15 @@ svn_error_t *svn_ra_neon__get_vcc(const
/* Issue a PROPPATCH request on URL, transmitting PROP_CHANGES (a hash
of const svn_string_t * values keyed on Subversion user-visible
property names) and PROP_DELETES (an array of property names to
- delete). Send any extra request headers in EXTRA_HEADERS. Use POOL
- for all allocations. */
+ delete). PROP_OLD_VALUES is a hash of Subversion user-visible property
+ names mapped to svn_dav__two_props_t * values. Send any extra
+ request headers in EXTRA_HEADERS. Use POOL for all allocations.
+ */
svn_error_t *svn_ra_neon__do_proppatch(svn_ra_neon__session_t *ras,
const char *url,
apr_hash_t *prop_changes,
const apr_array_header_t *prop_deletes,
+ apr_hash_t *prop_old_values,
apr_hash_t *extra_headers,
apr_pool_t *pool);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/session.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/session.c Thu Nov 4 20:48:21 2010
@@ -799,7 +799,8 @@ svn_ra_neon__open(svn_ra_session_t *sess
callbacks->get_client_string(callback_baton, &client_string, pool);
if (client_string)
- useragent = apr_pstrcat(pool, "SVN/" SVN_VERSION "/", client_string, NULL);
+ useragent = apr_pstrcat(pool, "SVN/" SVN_VERSION "/", client_string,
+ (char *)NULL);
else
useragent = "SVN/" SVN_VERSION;
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/util.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_neon/util.c Thu Nov 4 20:48:21 2010
@@ -167,6 +167,7 @@ typedef struct
svn_ra_neon__request_t *req;
svn_stringbuf_t *description;
svn_boolean_t contains_error;
+ svn_boolean_t contains_precondition_error;
} multistatus_baton_t;
/* Implements svn_ra_neon__startelm_cb_t. */
@@ -231,6 +232,9 @@ end_207_element(void *baton, int state,
return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("The request response contained at least "
"one error"));
+ else if (b->contains_precondition_error)
+ return svn_error_create(SVN_ERR_FS_PROP_BASEVALUE_MISMATCH, NULL,
+ b->description->data);
else
return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
b->description->data);
@@ -260,6 +264,10 @@ end_207_element(void *baton, int state,
else
b->propstat_has_error = (status.klass != 2);
+ /* Handle "412 Precondition Failed" specially */
+ if (status.code == 412)
+ b->contains_precondition_error = TRUE;
+
free(status.reason_phrase);
}
else
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/commit.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/commit.c Thu Nov 4 20:48:21 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;
@@ -376,7 +380,7 @@ checkout_dir(dir_context_t *dir)
dir->checkout->activity_url_len = dir->commit->activity_url_len;
dir->checkout->resource_url =
svn_path_url_add_component2(dir->parent_dir->checkout->resource_url,
- svn_relpath_basename(dir->name, dir->pool),
+ svn_relpath_basename(dir->name, NULL),
dir->pool);
apr_hash_set(dir->commit->copied_entries,
@@ -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);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+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);
+ }
}
- /* ENCODING, CDATA, and LEN are now set. */
+ 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;
+ }
+ }
- *encoding_p = encoding;
- *cdata_bkt_p = SERF_BUCKET_SIMPLE_STRING_LEN(cdata, len, alloc);
+ *old_val_p_p = old_val_p;
return SVN_NO_ERROR;
}
@@ -683,28 +737,99 @@ 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
property names containing ':' */
if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
- prop_name = apr_pstrcat(pool, "S:", name, NULL);
+ prop_name = apr_pstrcat(pool, "S:", name, (char *)NULL);
else if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
- prop_name = apr_pstrcat(pool, "C:", name, NULL);
+ prop_name = apr_pstrcat(pool, "C:", name, (char *)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;
@@ -735,7 +860,7 @@ setup_proppatch_headers(serf_bucket_t *h
{
const char *token_header;
- token_header = apr_pstrcat(pool, "(<", token, ">)", NULL);
+ token_header = apr_pstrcat(pool, "(<", token, ">)", (char *)NULL);
serf_bucket_headers_set(headers, "If", token_header);
}
@@ -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");
@@ -912,7 +1063,7 @@ setup_put_headers(serf_bucket_t *headers
{
const char *token_header;
- token_header = apr_pstrcat(pool, "(<", token, ">)", NULL);
+ token_header = apr_pstrcat(pool, "(<", token, ">)", (char *)NULL);
serf_bucket_headers_set(headers, "If", token_header);
}
@@ -1007,7 +1158,7 @@ setup_delete_headers(serf_bucket_t *head
const char *token_header;
token_header = apr_pstrcat(pool, "<", ctx->path, "> (<",
- ctx->lock_token, ">)", NULL);
+ ctx->lock_token, ">)", (char *)NULL);
serf_bucket_headers_set(headers, "If", token_header);
@@ -2208,6 +2359,7 @@ svn_error_t *
svn_ra_serf__change_rev_prop(svn_ra_session_t *ra_session,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
{
@@ -2219,6 +2371,17 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
apr_hash_t *props;
svn_error_t *err;
+ if (old_value_p)
+ {
+ svn_boolean_t capable;
+ SVN_ERR(svn_ra_serf__has_capability(ra_session, &capable,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
+
+ /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+ SVN_ERR_ASSERT(capable);
+ }
+
commit = apr_pcalloc(pool, sizeof(*commit));
commit->pool = pool;
@@ -2265,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,
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/getlocks.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/getlocks.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/getlocks.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/getlocks.c Thu Nov 4 20:48:21 2010
@@ -336,7 +336,7 @@ svn_ra_serf__get_locks(svn_ra_session_t
lock_ctx = apr_pcalloc(pool, sizeof(*lock_ctx));
lock_ctx->pool = pool;
- lock_ctx->path = apr_pstrcat(pool, "/", rel_path, NULL);
+ lock_ctx->path = apr_pstrcat(pool, "/", rel_path, (char *)NULL);
lock_ctx->requested_depth = depth;
lock_ctx->hash = apr_hash_make(pool);
lock_ctx->done = FALSE;
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/locks.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/locks.c Thu Nov 4 20:48:21 2010
@@ -732,7 +732,7 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
}
unlock_ctx.force = force;
- unlock_ctx.token = apr_pstrcat(subpool, "<", token, ">", NULL);
+ unlock_ctx.token = apr_pstrcat(subpool, "<", token, ">", (char *)NULL);
req_url = svn_path_url_add_component2(session->repos_url.path, path,
subpool);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/mergeinfo.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/mergeinfo.c Thu Nov 4 20:48:21 2010
@@ -184,7 +184,6 @@ create_mergeinfo_body(serf_bucket_t **bk
{
mergeinfo_context_t *mergeinfo_ctx = baton;
serf_bucket_t *body_bkt;
- int i;
body_bkt = serf_bucket_aggregate_create(alloc);
@@ -209,6 +208,8 @@ create_mergeinfo_body(serf_bucket_t **bk
if (mergeinfo_ctx->paths)
{
+ int i;
+
for (i = 0; i < mergeinfo_ctx->paths->nelts; i++)
{
const char *this_path = APR_ARRAY_IDX(mergeinfo_ctx->paths,
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/options.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/options.c Thu Nov 4 20:48:21 2010
@@ -313,6 +313,13 @@ capabilities_headers_iterator_callback(v
SVN_RA_CAPABILITY_LOG_REVPROPS,
APR_HASH_KEY_STRING, capability_yes);
}
+ if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS,
+ vals))
+ {
+ apr_hash_set(orc->session->capabilities,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ APR_HASH_KEY_STRING, capability_yes);
+ }
if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
{
apr_hash_set(orc->session->capabilities,
@@ -404,6 +411,8 @@ options_response_handler(serf_request_t
APR_HASH_KEY_STRING, capability_no);
apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
APR_HASH_KEY_STRING, capability_no);
+ apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ APR_HASH_KEY_STRING, capability_no);
/* Then see which ones we can discover. */
serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, orc);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/property.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/property.c Thu Nov 4 20:48:21 2010
@@ -862,9 +862,9 @@ set_bare_props(svn_ra_serf__prop_set_t s
if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
prop_name = name;
else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
- prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+ prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
else if (strcmp(ns, SVN_PROP_PREFIX) == 0)
- prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+ prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
else if (strcmp(ns, "") == 0)
prop_name = name;
else
@@ -888,9 +888,9 @@ svn_ra_serf__set_baton_props(svn_ra_serf
if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
prop_name = name;
else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
- prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+ prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
else if (strcmp(ns, SVN_PROP_PREFIX) == 0)
- prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+ prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
else if (strcmp(ns, "") == 0)
prop_name = name;
else if (strcmp(name, SVN_DAV__VERSION_NAME) == 0)
@@ -915,7 +915,7 @@ svn_ra_serf__set_baton_props(svn_ra_serf
else
{
/* An unknown namespace, must be a custom property. */
- prop_name = apr_pstrcat(pool, ns, name, NULL);
+ prop_name = apr_pstrcat(pool, ns, name, (char *)NULL);
}
return setprop(baton, prop_name, val, pool);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/ra_serf.h?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/ra_serf.h Thu Nov 4 20:48:21 2010
@@ -673,6 +673,9 @@ typedef struct svn_ra_serf__server_error
/* Have we seen an error tag? */
svn_boolean_t in_error;
+ /* Have we seen a HTTP "412 Precondition Failed" error? */
+ svn_boolean_t contains_precondition_error;
+
/* Should we be collecting the XML cdata? */
svn_boolean_t collect_cdata;
@@ -1322,6 +1325,7 @@ svn_error_t *
svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/replay.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/replay.c Thu Nov 4 20:48:21 2010
@@ -90,7 +90,7 @@ typedef struct {
replay_info_t *parent;
} prop_info_t;
-typedef struct {
+typedef struct replay_context_t {
apr_pool_t *src_rev_pool;
apr_pool_t *dst_rev_pool;
@@ -118,6 +118,10 @@ typedef struct {
/* Cached report target url */
const char *report_target;
+ /* Target and revision to fetch revision properties on */
+ const char *revprop_target;
+ svn_revnum_t revprop_rev;
+
/* Revision properties for this revision. */
apr_hash_t *revs_props;
apr_hash_t *props;
@@ -125,6 +129,9 @@ typedef struct {
/* Keep a reference to the XML parser ctx to report any errors. */
svn_ra_serf__xml_parser_t *parser_ctx;
+ /* The propfind for the revision properties of the current revision */
+ svn_ra_serf__propfind_context_t *prop_ctx;
+
} replay_context_t;
@@ -180,11 +187,15 @@ start_replay(svn_ra_serf__xml_parser_t *
{
push_state(parser, ctx, REPORT);
+ /* Before we can continue, we need the revision properties. */
+ SVN_ERR_ASSERT(!ctx->prop_ctx
+ || svn_ra_serf__propfind_is_done(ctx->prop_ctx));
+
/* Create a pool for the commit editor. */
ctx->dst_rev_pool = svn_pool_create(ctx->src_rev_pool);
ctx->props = apr_hash_make(ctx->dst_rev_pool);
- SVN_ERR(svn_ra_serf__walk_all_props(ctx->revs_props, ctx->report_target,
- ctx->revision,
+ SVN_ERR(svn_ra_serf__walk_all_props(ctx->revs_props, ctx->revprop_target,
+ ctx->revprop_rev,
svn_ra_serf__set_bare_props,
ctx->props, ctx->dst_rev_pool));
if (ctx->revstart_func)
@@ -751,13 +762,30 @@ svn_ra_serf__replay_range(svn_ra_session
/* Request all properties of a certain revision. */
replay_ctx->report_target = report_target;
replay_ctx->revs_props = apr_hash_make(replay_ctx->src_rev_pool);
+
+ if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
+ {
+ replay_ctx->revprop_target = apr_psprintf(pool, "%s/%ld",
+ session->rev_stub, rev);
+ replay_ctx->revprop_rev = SVN_INVALID_REVNUM;
+ }
+ else
+ {
+ replay_ctx->revprop_target = report_target;
+ replay_ctx->revprop_rev = rev;
+ }
+
SVN_ERR(svn_ra_serf__deliver_props(&prop_ctx,
replay_ctx->revs_props, session,
- session->conns[0], report_target,
- rev, "0", all_props,
+ session->conns[0],
+ replay_ctx->revprop_target,
+ replay_ctx->revprop_rev,
+ "0", all_props,
TRUE, NULL,
replay_ctx->src_rev_pool));
+ replay_ctx->prop_ctx = prop_ctx;
+
/* Send the replay report request. */
handler = apr_pcalloc(replay_ctx->src_rev_pool, sizeof(*handler));
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/serf.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/serf.c Thu Nov 4 20:48:21 2010
@@ -433,7 +433,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
if (client_string)
serf_sess->conns[0]->useragent = apr_pstrcat(pool, USER_AGENT, "/",
- client_string, NULL);
+ client_string, (char *)NULL);
else
serf_sess->conns[0]->useragent = USER_AGENT;
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/update.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/update.c Thu Nov 4 20:48:21 2010
@@ -2135,7 +2135,7 @@ link_path(void *report_baton,
SVN_ERR(svn_ra_serf__get_relative_path(&link, uri.path, report->sess,
NULL, pool));
- link = apr_pstrcat(pool, "/", link, NULL);
+ link = apr_pstrcat(pool, "/", link, (char *)NULL);
svn_xml_make_open_tag(&buf, pool, svn_xml_protect_pcdata, "S:entry",
"rev", apr_ltoa(pool, revision),
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/util.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_serf/util.c Thu Nov 4 20:48:21 2010
@@ -836,6 +836,7 @@ svn_ra_serf__handle_discard_body(serf_re
{
server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
server_err->has_xml_response = TRUE;
+ server_err->contains_precondition_error = FALSE;
server_err->cdata = svn_stringbuf_create("", pool);
server_err->collect_cdata = FALSE;
server_err->parser.pool = server_err->error->pool;
@@ -945,6 +946,34 @@ svn_ra_serf__handle_status_only(serf_req
return svn_error_return(err);
}
+/* Given a string like "HTTP/1.1 500 (status)" in BUF, parse out the numeric
+ status code into *STATUS_CODE_OUT. Ignores leading whitespace. */
+static svn_error_t *
+parse_dav_status(int *status_code_out, svn_stringbuf_t *buf,
+ apr_pool_t *scratch_pool)
+{
+ svn_error_t *err;
+ const char *token;
+ char *tok_status;
+ svn_stringbuf_t *temp_buf = svn_stringbuf_dup(buf, scratch_pool);
+
+ svn_stringbuf_strip_whitespace(temp_buf);
+ token = apr_strtok(temp_buf->data, " \t\r\n", &tok_status);
+ if (token)
+ token = apr_strtok(NULL, " \t\r\n", &tok_status);
+ if (!token)
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ "Malformed DAV:status CDATA '%s'",
+ buf->data);
+ err = svn_cstring_atoi(status_code_out, token);
+ if (err)
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, err,
+ "Malformed DAV:status CDATA '%s'",
+ buf->data);
+
+ return SVN_NO_ERROR;
+}
+
/*
* Expat callback invoked on a start element tag for a 207 response.
*/
@@ -968,6 +997,14 @@ start_207(svn_ra_serf__xml_parser_t *par
svn_stringbuf_setempty(ctx->cdata);
ctx->collect_cdata = TRUE;
}
+ else if (ctx->in_error &&
+ strcmp(name.namespace, "DAV:") == 0 &&
+ strcmp(name.name, "status") == 0)
+ {
+ /* Start collecting cdata. */
+ svn_stringbuf_setempty(ctx->cdata);
+ ctx->collect_cdata = TRUE;
+ }
return SVN_NO_ERROR;
}
@@ -993,7 +1030,22 @@ end_207(svn_ra_serf__xml_parser_t *parse
ctx->collect_cdata = FALSE;
ctx->error->message = apr_pstrmemdup(ctx->error->pool, ctx->cdata->data,
ctx->cdata->len);
- ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+ if (ctx->contains_precondition_error)
+ ctx->error->apr_err = SVN_ERR_FS_PROP_BASEVALUE_MISMATCH;
+ else
+ ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+ }
+ else if (ctx->in_error &&
+ strcmp(name.namespace, "DAV:") == 0 &&
+ strcmp(name.name, "status") == 0)
+ {
+ int status_code;
+
+ ctx->collect_cdata = FALSE;
+
+ SVN_ERR(parse_dav_status(&status_code, ctx->cdata, parser->pool));
+ if (status_code == 412)
+ ctx->contains_precondition_error = TRUE;
}
return SVN_NO_ERROR;
@@ -1044,6 +1096,7 @@ svn_ra_serf__handle_multistatus_only(ser
{
server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
server_err->has_xml_response = TRUE;
+ server_err->contains_precondition_error = FALSE;
server_err->cdata = svn_stringbuf_create("", pool);
server_err->collect_cdata = FALSE;
server_err->parser.pool = server_err->error->pool;
@@ -1053,7 +1106,7 @@ svn_ra_serf__handle_multistatus_only(ser
server_err->parser.cdata = cdata_207;
server_err->parser.done = &ctx->done;
server_err->parser.ignore_errors = TRUE;
- }
+ }
else
{
ctx->done = TRUE;
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/client.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/client.c Thu Nov 4 20:48:21 2010
@@ -622,6 +622,7 @@ static svn_error_t *open_session(svn_ra_
/* In protocol version 2, we send back our protocol version, our
* capability list, and the URL, and subsequently there is an auth
* request. */
+ /* Client-side capabilities list: */
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "n(wwwwww)cc(?c)",
(apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
@@ -813,16 +814,49 @@ static svn_error_t *ra_svn_get_dated_rev
return SVN_NO_ERROR;
}
+/* Forward declaration. */
+static svn_error_t *ra_svn_has_capability(svn_ra_session_t *session,
+ svn_boolean_t *has,
+ const char *capability,
+ apr_pool_t *pool);
+
static svn_error_t *ra_svn_change_rev_prop(svn_ra_session_t *session, svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
+ svn_boolean_t dont_care;
+ const svn_string_t *old_value;
+ svn_boolean_t has_atomic_revprops;
+
+ SVN_ERR(ra_svn_has_capability(session, &has_atomic_revprops,
+ SVN_RA_SVN_CAP_ATOMIC_REVPROPS,
+ pool));
+
+ if (old_value_p)
+ {
+ /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+ SVN_ERR_ASSERT(has_atomic_revprops);
+
+ dont_care = FALSE;
+ old_value = *old_value_p;
+ }
+ else
+ {
+ dont_care = TRUE;
+ old_value = NULL;
+ }
+
+ if (has_atomic_revprops)
+ SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop2", "rc(?s)(b?s)",
+ rev, name, value, dont_care, old_value));
+ else
+ SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
+ rev, name, value));
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
- rev, name, value));
SVN_ERR(handle_auth_request(sess_baton, pool));
SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
return SVN_NO_ERROR;
@@ -2257,7 +2291,7 @@ static svn_error_t *ra_svn_get_locks(svn
/* Figure out the repository abspath from PATH. */
abs_path = svn_path_url_add_component2(sess->url, path, pool);
SVN_ERR(path_relative_to_root(session, &abs_path, abs_path, pool));
- abs_path = apr_pstrcat(pool, "/", abs_path, NULL);
+ abs_path = apr_pstrcat(pool, "/", abs_path, (char *)NULL);
SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-locks", "c(w)", path,
svn_depth_to_word(depth)));
@@ -2420,6 +2454,9 @@ static svn_error_t *ra_svn_has_capabilit
else if (strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
*has = svn_ra_svn_has_capability(sess->conn,
SVN_RA_SVN_CAP_COMMIT_REVPROPS);
+ 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 /* Don't know any other capabilities, so error. */
{
return svn_error_createf
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/cyrus_auth.c Thu Nov 4 20:48:21 2010
@@ -410,7 +410,7 @@ static svn_error_t *try_auth(svn_ra_svn_
pmech - mechstring);
const char *tail = pmech + strlen(mech);
- mechstring = apr_pstrcat(pool, head, tail, NULL);
+ mechstring = apr_pstrcat(pool, head, tail, (char *)NULL);
again = TRUE;
}
}
@@ -632,10 +632,11 @@ svn_error_t *svn_ra_svn__enable_sasl_enc
apr_pool_t *pool)
{
const sasl_ssf_t *ssfp;
- int result;
if (! conn->encrypted)
{
+ int result;
+
/* Get the strength of the security layer. */
result = sasl_getprop(sasl_ctx, SASL_SSF, (void*) &ssfp);
if (result != SASL_OK)
@@ -718,9 +719,11 @@ svn_error_t *svn_ra_svn__get_addresses(c
/* Format the IP address and port number like this: a.b.c.d;port */
*local_addrport = apr_pstrcat(pool, local_addr, ";",
- apr_itoa(pool, (int)local_sa->port), NULL);
+ apr_itoa(pool, (int)local_sa->port),
+ (char *)NULL);
*remote_addrport = apr_pstrcat(pool, remote_addr, ";",
- apr_itoa(pool, (int)remote_sa->port), NULL);
+ apr_itoa(pool, (int)remote_sa->port),
+ (char *)NULL);
}
return SVN_NO_ERROR;
}
@@ -761,7 +764,7 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__se
mechstring = apr_pstrcat(pool,
mechstring,
i == 0 ? "" : " ",
- elt->u.word, NULL);
+ elt->u.word, (char *)NULL);
}
}
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/editorp.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/editorp.c Thu Nov 4 20:48:21 2010
@@ -904,7 +904,9 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
svn_error_clear(editor->abort_edit(edit_baton, subpool));
svn_ra_svn__set_block_handler(conn, blocked_write, &state);
}
- write_err = svn_ra_svn_write_cmd_failure(conn, subpool, err->child);
+ write_err = svn_ra_svn_write_cmd_failure(
+ conn, subpool,
+ svn_ra_svn__locate_real_error_child(err));
if (!write_err)
write_err = svn_ra_svn_flush(conn, subpool);
svn_ra_svn__set_block_handler(conn, NULL, NULL);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/marshal.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/marshal.c Thu Nov 4 20:48:21 2010
@@ -44,6 +44,12 @@
#define svn_iswhitespace(c) ((c) == ' ' || (c) == '\n')
+/* If we receive data that *claims* to be followed by a very long string,
+ * we should not trust that claim right away. But everything up to 1 MB
+ * should be too small to be instrumental for a DOS attack. */
+
+#define SUSPICIOUSLY_HUGE_STRING_SIZE_THRESHOLD (0x100000)
+
/* --- CONNECTION INITIALIZATION --- */
svn_ra_svn_conn_t *svn_ra_svn_create_conn(apr_socket_t *sock,
@@ -296,8 +302,8 @@ static svn_error_t *readbuf_fill(svn_ra_
return SVN_NO_ERROR;
}
-static svn_error_t *readbuf_getchar(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- char *result)
+static APR_INLINE svn_error_t *
+readbuf_getchar(svn_ra_svn_conn_t *conn, apr_pool_t *pool, char *result)
{
if (conn->read_ptr == conn->read_end)
SVN_ERR(readbuf_fill(conn, pool));
@@ -537,15 +543,14 @@ svn_error_t *svn_ra_svn_write_tuple(svn_
/* --- READING DATA ITEMS --- */
-/* Read LEN bytes from CONN into already-allocated structure ITEM.
- * Afterwards, *ITEM is of type 'SVN_RA_SVN_STRING', and its string
- * data is allocated in POOL. */
-static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- svn_ra_svn_item_t *item, apr_uint64_t len)
+/* Read LEN bytes from CONN into a supposedly empty STRINGBUF.
+ * POOL will be used for temporary allocations. */
+static svn_error_t *
+read_long_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+ svn_stringbuf_t *stringbuf, apr_uint64_t len)
{
char readbuf[4096];
apr_size_t readbuf_len;
- svn_stringbuf_t *stringbuf = svn_stringbuf_create("", pool);
/* We can't store strings longer than the maximum size of apr_size_t,
* so check for wrapping */
@@ -565,6 +570,57 @@ static svn_error_t *read_string(svn_ra_s
len -= readbuf_len;
}
+ return SVN_NO_ERROR;
+}
+
+/* Read LEN bytes from CONN into already-allocated structure ITEM.
+ * Afterwards, *ITEM is of type 'SVN_RA_SVN_STRING', and its string
+ * data is allocated in POOL. */
+static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+ svn_ra_svn_item_t *item, apr_uint64_t len)
+{
+ svn_stringbuf_t *stringbuf;
+
+ /* We should not use large strings in our protocol. However, we may
+ * receive a claim that a very long string is going to follow. In that
+ * case, we start small and wait for all that data to actually show up.
+ * This does not fully prevent DOS attacs but makes them harder (you
+ * have to actually send gigabytes of data).
+ */
+ if (len > SUSPICIOUSLY_HUGE_STRING_SIZE_THRESHOLD)
+ {
+ /* This string might take a large amount of memory. Don't allocate
+ * the whole buffer at once, so to prevent OOM issues by corrupted
+ * network data.
+ */
+ stringbuf = svn_stringbuf_create("", pool);
+ SVN_ERR(read_long_string(conn, pool, stringbuf, len));
+ }
+ else
+ {
+ /* This is a reasonably sized string. So, provide a buffer large
+ * enough to prevent re-allocation as long as the data transmission
+ * is not flawed.
+ */
+ stringbuf = svn_stringbuf_create_ensure(len, pool);
+
+ /* Read the string data directly into the string structure.
+ * Do it iteratively, if necessary.
+ */
+ while (len)
+ {
+ apr_size_t readbuf_len = (apr_size_t)len;
+ char *dest = stringbuf->data + stringbuf->len;
+ SVN_ERR(readbuf_read(conn, pool, dest, readbuf_len));
+
+ stringbuf->len += readbuf_len;
+ stringbuf->data[stringbuf->len] = '\0';
+ len -= readbuf_len;
+ }
+ }
+
+ /* Return the string properly wrapped into an RA_SVN item.
+ */
item->kind = SVN_RA_SVN_STRING;
item->u.string = apr_palloc(pool, sizeof(*item->u.string));
item->u.string->data = stringbuf->data;
@@ -582,7 +638,7 @@ static svn_error_t *read_item(svn_ra_svn
int level)
{
char c = first_char;
- apr_uint64_t val, prev_val=0;
+ apr_uint64_t val;
svn_stringbuf_t *str;
svn_ra_svn_item_t *listitem;
@@ -600,7 +656,7 @@ static svn_error_t *read_item(svn_ra_svn
val = c - '0';
while (1)
{
- prev_val = val;
+ apr_uint64_t prev_val = val;
SVN_ERR(readbuf_getchar(conn, pool, &c));
if (!svn_ctype_isdigit(c))
break;
@@ -625,7 +681,8 @@ static svn_error_t *read_item(svn_ra_svn
else if (svn_ctype_isalpha(c))
{
/* It's a word. */
- str = svn_stringbuf_ncreate(&c, 1, pool);
+ str = svn_stringbuf_create_ensure(16, pool);
+ svn_stringbuf_appendbyte(str, c);
while (1)
{
SVN_ERR(readbuf_getchar(conn, pool, &c));
@@ -640,7 +697,7 @@ static svn_error_t *read_item(svn_ra_svn
{
/* Read in the list items. */
item->kind = SVN_RA_SVN_LIST;
- item->u.list = apr_array_make(pool, 0, sizeof(svn_ra_svn_item_t));
+ item->u.list = apr_array_make(pool, 4, sizeof(svn_ra_svn_item_t));
while (1)
{
SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c));
@@ -832,6 +889,21 @@ svn_error_t *svn_ra_svn_parse_proplist(c
/* --- READING AND WRITING COMMANDS AND RESPONSES --- */
+svn_error_t *svn_ra_svn__locate_real_error_child(svn_error_t *err)
+{
+ svn_error_t *this_link;
+
+ SVN_ERR_ASSERT(err);
+
+ for (this_link = err;
+ this_link && (this_link->apr_err == SVN_ERR_RA_SVN_CMD_ERR);
+ this_link = this_link->child)
+ ;
+
+ SVN_ERR_ASSERT(this_link);
+ return this_link;
+}
+
svn_error_t *svn_ra_svn__handle_failure_status(const apr_array_header_t *params,
apr_pool_t *pool)
{
@@ -860,12 +932,27 @@ svn_error_t *svn_ra_svn__handle_failure_
easily change that, so "" means a nonexistent message. */
if (!*message)
message = NULL;
- err = svn_error_create((apr_status_t)apr_err, err, message);
- err->file = apr_pstrdup(err->pool, file);
- err->line = (long)line;
+
+ /* Skip over links in the error chain that were intended only to
+ exist on the server (to wrap real errors intended for the
+ client) but accidentally got included in the server's actual
+ response. */
+ if ((apr_status_t)apr_err != SVN_ERR_RA_SVN_CMD_ERR)
+ {
+ err = svn_error_create((apr_status_t)apr_err, err, message);
+ err->file = apr_pstrdup(err->pool, file);
+ err->line = (long)line;
+ }
}
svn_pool_destroy(subpool);
+
+ /* If we get here, then we failed to find a real error in the error
+ chain that the server proported to be sending us. That's bad. */
+ if (! err)
+ err = svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Malformed error list"));
+
return err;
}
@@ -941,7 +1028,9 @@ svn_error_t *svn_ra_svn_handle_commands2
if (err && err->apr_err == SVN_ERR_RA_SVN_CMD_ERR)
{
- write_err = svn_ra_svn_write_cmd_failure(conn, iterpool, err->child);
+ write_err = svn_ra_svn_write_cmd_failure(
+ conn, iterpool,
+ svn_ra_svn__locate_real_error_child(err));
svn_error_clear(err);
if (write_err)
return write_err;
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/protocol?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/protocol Thu Nov 4 20:48:21 2010
@@ -199,6 +199,9 @@ capability and C indicates a client capa
[S] depth If the server presents this capability, it understands
requested operational depth (see section 3.1.1) and
per-path ambient depth (see section 3.1.3).
+[S] atomic-revprops If the server presents this capability, it
+ supports the change-rev-prop2 command.
+ See section 3.1.1.
3. Commands
-----------
@@ -261,6 +264,16 @@ second place for auth-request point as n
changed to be optional without creating an optional tuple for
that one parameter as we normally do.)
+ change-rev-prop2
+ params: ( rev:number name:string [ value:string ]
+ ( dont-care:bool ? previous-value:string ) )
+ response: ( )
+ If value is not specified, the rev-prop is removed. If dont-care is false,
+ then the rev-prop is changed only if it is currently set as previous-value
+ indicates. (If dont-care is false and previous-value is unspecified, then
+ the revision property must be previously unset.) If dont-care is true,
+ then previous-value must not be specified.
+
rev-proplist
params: ( rev:number )
response: ( props:proplist )
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/ra_svn.h?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_ra_svn/ra_svn.h Thu Nov 4 20:48:21 2010
@@ -122,6 +122,11 @@ svn_error_t *svn_ra_svn__cram_client(svn
const char *user, const char *password,
const char **message);
+/* Return a pointer to the error chain child of ERR which contains the
+ * first "real" error message, not merely one of the
+ * SVN_ERR_RA_SVN_CMD_ERR wrapper errors. */
+svn_error_t *svn_ra_svn__locate_real_error_child(svn_error_t *err);
+
/* Return an error chain based on @a params (which contains a
* command response indicating failure). The error chain will be
* in the same order as the errors indicated in @a params. Use
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_repos/authz.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_repos/authz.c Thu Nov 4 20:48:21 2010
@@ -333,7 +333,7 @@ authz_get_path_access(svn_config_t *cfg,
baton.user = user;
/* Try to locate a repository-specific block first. */
- qualified_path = apr_pstrcat(pool, repos_name, ":", path, NULL);
+ qualified_path = apr_pstrcat(pool, repos_name, ":", path, (char *)NULL);
svn_config_enumerate2(cfg, qualified_path,
authz_parse_line, &baton, pool);
@@ -376,7 +376,7 @@ authz_get_tree_access(svn_config_t *cfg,
baton.required_access = required_access;
baton.repos_path = path;
baton.qualified_repos_path = apr_pstrcat(pool, repos_name,
- ":", path, NULL);
+ ":", path, (char *)NULL);
/* Default to access granted if no rules say otherwise. */
baton.access = TRUE;
@@ -433,7 +433,7 @@ authz_get_global_access(svn_config_t *cf
baton.user = user;
baton.required_access = required_access;
baton.access = FALSE; /* Deny access by default. */
- baton.repos_path = apr_pstrcat(pool, repos_name, ":/", NULL);
+ baton.repos_path = apr_pstrcat(pool, repos_name, ":/", (char *)NULL);
svn_config_enumerate_sections2(cfg, authz_global_parse_section,
&baton, pool);
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_repos/delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_repos/delta.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_repos/delta.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_repos/delta.c Thu Nov 4 20:48:21 2010
@@ -965,7 +965,6 @@ delta_dirs(struct context *c,
entries hash? */
if (s_entries && ((s_entry = apr_hash_get(s_entries, key, klen)) != 0))
{
- int distance;
svn_node_kind_t src_kind;
s_fullpath = svn_path_join(source_path, t_entry->name, subpool);
@@ -984,7 +983,7 @@ delta_dirs(struct context *c,
old one and add the new one.
1: means the nodes are related through ancestry, so go
ahead and do the replace directly. */
- distance = svn_fs_compare_ids(s_entry->id, t_entry->id);
+ int distance = svn_fs_compare_ids(s_entry->id, t_entry->id);
if (distance == 0)
{
/* no-op */
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_repos/deprecated.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_repos/deprecated.c Thu Nov 4 20:48:21 2010
@@ -328,6 +328,26 @@ svn_repos_replay(svn_fs_root_t *root,
/*** From fs-wrap.c ***/
svn_error_t *
+svn_repos_fs_change_rev_prop3(svn_repos_t *repos,
+ svn_revnum_t rev,
+ const char *author,
+ const char *name,
+ const svn_string_t *new_value,
+ svn_boolean_t use_pre_revprop_change_hook,
+ svn_boolean_t use_post_revprop_change_hook,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *pool)
+{
+ return svn_repos_fs_change_rev_prop4(repos, rev, author, name, NULL,
+ new_value,
+ use_pre_revprop_change_hook,
+ use_post_revprop_change_hook,
+ authz_read_func,
+ authz_read_baton, pool);
+}
+
+svn_error_t *
svn_repos_fs_change_rev_prop2(svn_repos_t *repos,
svn_revnum_t rev,
const char *author,
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_repos/dump.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_repos/dump.c Thu Nov 4 20:48:21 2010
@@ -386,7 +386,7 @@ dump_node(struct edit_baton *eb,
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
compare_root, compare_path,
- TRUE, pool));
+ FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -395,7 +395,7 @@ dump_node(struct edit_baton *eb,
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
compare_root, compare_path,
- TRUE, pool));
+ FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -432,7 +432,7 @@ dump_node(struct edit_baton *eb,
/* If this is a partial dump, then issue a warning if we dump mergeinfo
properties that refer to revisions older than the first revision
dumped. */
- if (eb->notify_func && eb->oldest_dumped_rev > 1)
+ if (!eb->verify && eb->notify_func && eb->oldest_dumped_rev > 1)
{
svn_string_t *mergeinfo_str = apr_hash_get(prophash,
SVN_PROP_MERGEINFO,
@@ -513,7 +513,7 @@ dump_node(struct edit_baton *eb,
{
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
compare_root, compare_path,
- TRUE, pool));
+ FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -522,7 +522,7 @@ dump_node(struct edit_baton *eb,
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
compare_root, compare_path,
- TRUE, pool));
+ FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -542,7 +542,7 @@ dump_node(struct edit_baton *eb,
": %" SVN_FILESIZE_T_FMT "\n", textlen));
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
- eb->fs_root, path, TRUE, pool));
+ eb->fs_root, path, FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -550,7 +550,7 @@ dump_node(struct edit_baton *eb,
": %s\n", hex_digest));
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
- eb->fs_root, path, TRUE, pool));
+ eb->fs_root, path, FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
SVN_ERR(svn_stream_printf(eb->stream, pool,
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_repos/fs-wrap.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_repos/fs-wrap.c Thu Nov 4 20:48:21 2010
@@ -263,10 +263,11 @@ svn_repos_fs_change_txn_prop(svn_fs_txn_
svn_error_t *
-svn_repos_fs_change_rev_prop3(svn_repos_t *repos,
+svn_repos_fs_change_rev_prop4(svn_repos_t *repos,
svn_revnum_t rev,
const char *author,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *new_value,
svn_boolean_t use_pre_revprop_change_hook,
svn_boolean_t use_post_revprop_change_hook,
@@ -274,9 +275,7 @@ svn_repos_fs_change_rev_prop3(svn_repos_
void *authz_read_baton,
apr_pool_t *pool)
{
- svn_string_t *old_value;
svn_repos_revision_access_level_t readability;
- char action;
SVN_ERR(svn_repos_check_revision_access(&readability, repos, rev,
authz_read_func, authz_read_baton,
@@ -284,9 +283,27 @@ svn_repos_fs_change_rev_prop3(svn_repos_
if (readability == svn_repos_revision_access_full)
{
+ const svn_string_t *old_value;
+ char action;
+
SVN_ERR(validate_prop(name, new_value, pool));
- SVN_ERR(svn_fs_revision_prop(&old_value, repos->fs, rev, name, pool));
+ /* Fetch OLD_VALUE for svn_fs_change_rev_prop2(). */
+ if (old_value_p)
+ {
+ old_value = *old_value_p;
+ }
+ else
+ {
+ /* Get OLD_VALUE anyway, in order for ACTION and OLD_VALUE arguments
+ * to the hooks to be accurate. */
+ svn_string_t *old_value2;
+
+ SVN_ERR(svn_fs_revision_prop(&old_value2, repos->fs, rev, name, pool));
+ old_value = old_value2;
+ }
+
+ /* Prepare ACTION. */
if (! new_value)
action = 'D';
else if (! old_value)
@@ -294,12 +311,13 @@ svn_repos_fs_change_rev_prop3(svn_repos_
else
action = 'M';
+ /* ### currently not passing the old_value to hooks */
if (use_pre_revprop_change_hook)
SVN_ERR(svn_repos__hooks_pre_revprop_change(repos, rev, author, name,
new_value, action, pool));
- SVN_ERR(svn_fs_change_rev_prop2(repos->fs, rev, name, NULL,
- new_value, pool));
+ SVN_ERR(svn_fs_change_rev_prop2(repos->fs, rev, name,
+ &old_value, new_value, pool));
if (use_post_revprop_change_hook)
SVN_ERR(svn_repos__hooks_post_revprop_change(repos, rev, author, name,
@@ -594,7 +612,6 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
apr_array_header_t *readable_paths = (apr_array_header_t *) paths;
svn_fs_root_t *root;
apr_pool_t *iterpool = svn_pool_create(pool);
- int i;
if (!SVN_IS_VALID_REVNUM(rev))
SVN_ERR(svn_fs_youngest_rev(&rev, repos->fs, pool));
@@ -603,6 +620,8 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
/* Filter out unreadable paths before divining merge tracking info. */
if (authz_read_func)
{
+ int i;
+
for (i = 0; i < paths->nelts; i++)
{
svn_boolean_t readable;
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_repos/hooks.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_repos/hooks.c Thu Nov 4 20:48:21 2010
@@ -347,7 +347,7 @@ check_hook_cmd(const char *hook, svn_boo
for (extn = check_extns; *extn; ++extn)
{
const char *const hook_path =
- (**extn ? apr_pstrcat(pool, hook, *extn, NULL) : hook);
+ (**extn ? apr_pstrcat(pool, hook, *extn, (char *)NULL) : hook);
svn_node_kind_t kind;
if (!(err = svn_io_check_resolved_path(hook_path, &kind, pool))