summaryrefslogtreecommitdiff
path: root/subversion/libsvn_ra_serf/property.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_ra_serf/property.c')
-rw-r--r--subversion/libsvn_ra_serf/property.c760
1 files changed, 207 insertions, 553 deletions
diff --git a/subversion/libsvn_ra_serf/property.c b/subversion/libsvn_ra_serf/property.c
index 586d38ff46ca..b7e03183c4c7 100644
--- a/subversion/libsvn_ra_serf/property.c
+++ b/subversion/libsvn_ra_serf/property.c
@@ -42,7 +42,7 @@
/* Our current parsing state we're in for the PROPFIND response. */
typedef enum prop_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
MULTISTATUS,
RESPONSE,
HREF,
@@ -59,20 +59,12 @@ typedef enum prop_state_e {
* This structure represents a pending PROPFIND response.
*/
typedef struct propfind_context_t {
- /* pool to issue allocations from */
- apr_pool_t *pool;
-
svn_ra_serf__handler_t *handler;
- /* associated serf session */
- svn_ra_serf__session_t *sess;
- svn_ra_serf__connection_t *conn;
-
/* the requested path */
const char *path;
- /* the requested version (number and string form) */
- svn_revnum_t rev;
+ /* the requested version (in string form) */
const char *label;
/* the request depth */
@@ -81,12 +73,8 @@ typedef struct propfind_context_t {
/* the list of requested properties */
const svn_ra_serf__dav_props_t *find_props;
- /* hash table that will be updated with the properties
- *
- * This can be shared between multiple propfind_context_t
- * structures
- */
- apr_hash_t *ret_props;
+ svn_ra_serf__prop_func_t prop_func;
+ void *prop_func_baton;
/* hash table containing all the properties associated with the
* "current" <propstat> tag. These will get copied into RET_PROPS
@@ -94,12 +82,6 @@ typedef struct propfind_context_t {
* "good"; otherwise, they'll get discarded.
*/
apr_hash_t *ps_props;
-
- /* If not-NULL, add us to this list when we're done. */
- svn_ra_serf__list_t **done_list;
-
- svn_ra_serf__list_t done_item;
-
} propfind_context_t;
@@ -136,10 +118,14 @@ static const svn_ra_serf__xml_transition_t propfind_ttable[] = {
{ 0 }
};
+static const int propfind_expected_status[] = {
+ 207,
+ 0
+};
/* Return the HTTP status code contained in STATUS_LINE, or 0 if
there's a problem parsing it. */
-static int parse_status_code(const char *status_line)
+static apr_int64_t parse_status_code(const char *status_line)
{
/* STATUS_LINE should be of form: "HTTP/1.1 200 OK" */
if (status_line[0] == 'H' &&
@@ -159,24 +145,6 @@ static int parse_status_code(const char *status_line)
return 0;
}
-
-/* Conforms to svn_ra_serf__path_rev_walker_t */
-static svn_error_t *
-copy_into_ret_props(void *baton,
- const char *path, apr_ssize_t path_len,
- const char *ns, apr_ssize_t ns_len,
- const char *name, apr_ssize_t name_len,
- const svn_string_t *val,
- apr_pool_t *pool)
-{
- propfind_context_t *ctx = baton;
-
- svn_ra_serf__set_ver_prop(ctx->ret_props, path, ctx->rev, ns, name,
- val, ctx->pool);
- return SVN_NO_ERROR;
-}
-
-
/* Conforms to svn_ra_serf__xml_opened_t */
static svn_error_t *
propfind_opened(svn_ra_serf__xml_estate_t *xes,
@@ -189,17 +157,40 @@ propfind_opened(svn_ra_serf__xml_estate_t *xes,
if (entered_state == PROPVAL)
{
- svn_ra_serf__xml_note(xes, PROPVAL, "ns", tag->namespace);
+ svn_ra_serf__xml_note(xes, PROPVAL, "ns", tag->xmlns);
svn_ra_serf__xml_note(xes, PROPVAL, "name", tag->name);
}
else if (entered_state == PROPSTAT)
{
- ctx->ps_props = apr_hash_make(ctx->pool);
+ ctx->ps_props = apr_hash_make(svn_ra_serf__xml_state_pool(xes));
}
return SVN_NO_ERROR;
}
+/* Set PROPS for NS:NAME VAL. Helper for propfind_closed */
+static void
+set_ns_prop(apr_hash_t *ns_props,
+ const char *ns, const char *name,
+ const svn_string_t *val, apr_pool_t *result_pool)
+{
+ apr_hash_t *props = svn_hash_gets(ns_props, ns);
+
+ if (!props)
+ {
+ props = apr_hash_make(result_pool);
+ ns = apr_pstrdup(result_pool, ns);
+ svn_hash_sets(ns_props, ns, props);
+ }
+
+ if (val)
+ {
+ name = apr_pstrdup(result_pool, name);
+ val = svn_string_dup(val, result_pool);
+ }
+
+ svn_hash_sets(props, name, val);
+}
/* Conforms to svn_ra_serf__xml_closed_t */
static svn_error_t *
@@ -218,17 +209,10 @@ propfind_closed(svn_ra_serf__xml_estate_t *xes,
onto the "done list". External callers will then know this
request has been completed (tho stray response bytes may still
arrive). */
- if (ctx->done_list)
- {
- ctx->done_item.data = ctx->handler;
- ctx->done_item.next = *ctx->done_list;
- *ctx->done_list = &ctx->done_item;
- }
}
else if (leaving_state == HREF)
{
const char *path;
- const svn_string_t *val_str;
if (strcmp(ctx->depth, "1") == 0)
path = svn_urlpath__canonicalize(cdata->data, scratch_pool);
@@ -237,11 +221,10 @@ propfind_closed(svn_ra_serf__xml_estate_t *xes,
svn_ra_serf__xml_note(xes, RESPONSE, "path", path);
- /* Copy the value into the right pool, then save the HREF. */
- val_str = svn_string_dup(cdata, ctx->pool);
- svn_ra_serf__set_ver_prop(ctx->ret_props,
- path, ctx->rev, D_, "href", val_str,
- ctx->pool);
+ SVN_ERR(ctx->prop_func(ctx->prop_func_baton,
+ path,
+ D_, "href",
+ cdata, scratch_pool));
}
else if (leaving_state == COLLECTION)
{
@@ -257,21 +240,23 @@ propfind_closed(svn_ra_serf__xml_estate_t *xes,
that we wish to ignore. (Typically, if it's not a 200, the
status will be 404 to indicate that a property we
specifically requested from the server doesn't exist.) */
- int status = parse_status_code(cdata->data);
+ apr_int64_t status = parse_status_code(cdata->data);
if (status != 200)
svn_ra_serf__xml_note(xes, PROPSTAT, "ignore-prop", "*");
}
else if (leaving_state == PROPVAL)
{
- const char *encoding = svn_hash_gets(attrs, "V:encoding");
+ const char *encoding;
const svn_string_t *val_str;
- apr_hash_t *gathered;
- const char *path;
const char *ns;
const char *name;
const char *altvalue;
- if (encoding)
+ if ((altvalue = svn_hash_gets(attrs, "altvalue")) != NULL)
+ {
+ val_str = svn_string_create(altvalue, scratch_pool);
+ }
+ else if ((encoding = svn_hash_gets(attrs, "V:encoding")) != NULL)
{
if (strcmp(encoding, "base64") != 0)
return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA,
@@ -280,17 +265,15 @@ propfind_closed(svn_ra_serf__xml_estate_t *xes,
encoding);
/* Decode into the right pool. */
- val_str = svn_base64_decode_string(cdata, ctx->pool);
+ val_str = svn_base64_decode_string(cdata, scratch_pool);
}
else
{
/* Copy into the right pool. */
- val_str = svn_string_dup(cdata, ctx->pool);
+ val_str = cdata;
}
- /* The current path sits on the RESPONSE state. Gather up all the
- state from this PROPVAL to the (grandparent) RESPONSE state,
- and grab the path from there.
+ /* The current path sits on the RESPONSE state.
Now, it would be nice if we could, at this point, know that
the status code for this property indicated a problem -- then
@@ -300,24 +283,12 @@ propfind_closed(svn_ra_serf__xml_estate_t *xes,
here, setting the property and value as expected. Once we
know for sure the status code associate with the property,
we'll decide its fate. */
- gathered = svn_ra_serf__xml_gather_since(xes, RESPONSE);
-
- /* These will be dup'd into CTX->POOL, as necessary. */
- path = svn_hash_gets(gathered, "path");
- if (path == NULL)
- path = ctx->path;
ns = svn_hash_gets(attrs, "ns");
- name = apr_pstrdup(ctx->pool,
- svn_hash_gets(attrs, "name"));
-
- altvalue = svn_hash_gets(attrs, "altvalue");
- if (altvalue != NULL)
- val_str = svn_string_create(altvalue, ctx->pool);
+ name = svn_hash_gets(attrs, "name");
- svn_ra_serf__set_ver_prop(ctx->ps_props,
- path, ctx->rev, ns, name, val_str,
- ctx->pool);
+ set_ns_prop(ctx->ps_props, ns, name, val_str,
+ apr_hash_pool_get(ctx->ps_props));
}
else
{
@@ -325,146 +296,60 @@ propfind_closed(svn_ra_serf__xml_estate_t *xes,
SVN_ERR_ASSERT(leaving_state == PROPSTAT);
- gathered = svn_ra_serf__xml_gather_since(xes, PROPSTAT);
+ gathered = svn_ra_serf__xml_gather_since(xes, RESPONSE);
/* If we've squirreled away a note that says we want to ignore
these properties, we'll do so. Otherwise, we need to copy
them from the temporary hash into the ctx->ret_props hash. */
if (! svn_hash_gets(gathered, "ignore-prop"))
{
- SVN_ERR(svn_ra_serf__walk_all_paths(ctx->ps_props, ctx->rev,
- copy_into_ret_props, ctx,
- scratch_pool));
- }
+ apr_hash_index_t *hi_ns;
+ const char *path;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- ctx->ps_props = NULL;
- }
-
- return SVN_NO_ERROR;
-}
+ path = svn_hash_gets(gathered, "path");
+ if (!path)
+ path = ctx->path;
-const svn_string_t *
-svn_ra_serf__get_ver_prop_string(apr_hash_t *props,
- const char *path,
- svn_revnum_t rev,
- const char *ns,
- const char *name)
-{
- apr_hash_t *ver_props, *path_props, *ns_props;
- void *val = NULL;
-
- ver_props = apr_hash_get(props, &rev, sizeof(rev));
- if (ver_props)
- {
- path_props = svn_hash_gets(ver_props, path);
-
- if (path_props)
- {
- ns_props = svn_hash_gets(path_props, ns);
- if (ns_props)
+ for (hi_ns = apr_hash_first(scratch_pool, ctx->ps_props);
+ hi_ns;
+ hi_ns = apr_hash_next(hi_ns))
{
- val = svn_hash_gets(ns_props, name);
+ const char *ns = apr_hash_this_key(hi_ns);
+ apr_hash_t *props = apr_hash_this_val(hi_ns);
+ apr_hash_index_t *hi_prop;
+
+ svn_pool_clear(iterpool);
+
+ for (hi_prop = apr_hash_first(iterpool, props);
+ hi_prop;
+ hi_prop = apr_hash_next(hi_prop))
+ {
+ const char *name = apr_hash_this_key(hi_prop);
+ const svn_string_t *value = apr_hash_this_val(hi_prop);
+
+ SVN_ERR(ctx->prop_func(ctx->prop_func_baton, path,
+ ns, name, value, iterpool));
+ }
}
- }
- }
-
- return val;
-}
-
-const char *
-svn_ra_serf__get_ver_prop(apr_hash_t *props,
- const char *path,
- svn_revnum_t rev,
- const char *ns,
- const char *name)
-{
- const svn_string_t *val;
- val = svn_ra_serf__get_ver_prop_string(props, path, rev, ns, name);
-
- if (val)
- {
- return val->data;
- }
-
- return NULL;
-}
-
-const svn_string_t *
-svn_ra_serf__get_prop_string(apr_hash_t *props,
- const char *path,
- const char *ns,
- const char *name)
-{
- return svn_ra_serf__get_ver_prop_string(props, path, SVN_INVALID_REVNUM,
- ns, name);
-}
-
-const char *
-svn_ra_serf__get_prop(apr_hash_t *props,
- const char *path,
- const char *ns,
- const char *name)
-{
- return svn_ra_serf__get_ver_prop(props, path, SVN_INVALID_REVNUM, ns, name);
-}
-
-void
-svn_ra_serf__set_ver_prop(apr_hash_t *props,
- const char *path, svn_revnum_t rev,
- const char *ns, const char *name,
- const svn_string_t *val, apr_pool_t *pool)
-{
- apr_hash_t *ver_props, *path_props, *ns_props;
-
- ver_props = apr_hash_get(props, &rev, sizeof(rev));
- if (!ver_props)
- {
- ver_props = apr_hash_make(pool);
- apr_hash_set(props, apr_pmemdup(pool, &rev, sizeof(rev)), sizeof(rev),
- ver_props);
- }
-
- path_props = svn_hash_gets(ver_props, path);
-
- if (!path_props)
- {
- path_props = apr_hash_make(pool);
- path = apr_pstrdup(pool, path);
- svn_hash_sets(ver_props, path, path_props);
-
- /* todo: we know that we'll fail the next check, but fall through
- * for now for simplicity's sake.
- */
- }
+ svn_pool_destroy(iterpool);
+ }
- ns_props = svn_hash_gets(path_props, ns);
- if (!ns_props)
- {
- ns_props = apr_hash_make(pool);
- ns = apr_pstrdup(pool, ns);
- svn_hash_sets(path_props, ns, ns_props);
+ ctx->ps_props = NULL; /* Allocated in PROPSTAT state pool */
}
- svn_hash_sets(ns_props, name, val);
+ return SVN_NO_ERROR;
}
-void
-svn_ra_serf__set_prop(apr_hash_t *props,
- const char *path,
- const char *ns, const char *name,
- const svn_string_t *val, apr_pool_t *pool)
-{
- svn_ra_serf__set_ver_prop(props, path, SVN_INVALID_REVNUM, ns, name,
- val, pool);
-}
static svn_error_t *
setup_propfind_headers(serf_bucket_t *headers,
- void *setup_baton,
- apr_pool_t *pool)
+ void *setup_baton,
+ apr_pool_t *pool /* request pool */,
+ apr_pool_t *scratch_pool)
{
propfind_context_t *ctx = setup_baton;
@@ -480,11 +365,13 @@ setup_propfind_headers(serf_bucket_t *headers,
#define PROPFIND_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?><propfind xmlns=\"DAV:\">"
#define PROPFIND_TRAILER "</propfind>"
+/* Implements svn_ra_serf__request_body_delegate_t */
static svn_error_t *
create_propfind_body(serf_bucket_t **bkt,
void *setup_baton,
serf_bucket_alloc_t *alloc,
- apr_pool_t *pool)
+ apr_pool_t *pool /* request pool */,
+ apr_pool_t *scratch_pool)
{
propfind_context_t *ctx = setup_baton;
@@ -495,7 +382,7 @@ create_propfind_body(serf_bucket_t **bkt,
body_bkt = serf_bucket_aggregate_create(alloc);
prop = ctx->find_props;
- while (prop && prop->namespace)
+ while (prop && prop->xmlns)
{
/* special case the allprop case. */
if (strcmp(prop->name, "allprop") == 0)
@@ -515,7 +402,7 @@ create_propfind_body(serf_bucket_t **bkt,
alloc);
serf_bucket_aggregate_append(body_bkt, tmp);
- tmp = SERF_BUCKET_SIMPLE_STRING(prop->namespace, alloc);
+ tmp = SERF_BUCKET_SIMPLE_STRING(prop->xmlns, alloc);
serf_bucket_aggregate_append(body_bkt, tmp);
tmp = SERF_BUCKET_SIMPLE_STRING_LEN("\"/>", sizeof("\"/>")-1,
@@ -559,16 +446,15 @@ create_propfind_body(serf_bucket_t **bkt,
svn_error_t *
-svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
- apr_hash_t *ret_props,
- svn_ra_serf__session_t *sess,
- svn_ra_serf__connection_t *conn,
- const char *path,
- svn_revnum_t rev,
- const char *depth,
- const svn_ra_serf__dav_props_t *find_props,
- svn_ra_serf__list_t **done_list,
- apr_pool_t *pool)
+svn_ra_serf__create_propfind_handler(svn_ra_serf__handler_t **propfind_handler,
+ svn_ra_serf__session_t *sess,
+ const char *path,
+ svn_revnum_t rev,
+ const char *depth,
+ const svn_ra_serf__dav_props_t *find_props,
+ svn_ra_serf__prop_func_t prop_func,
+ void *prop_func_baton,
+ apr_pool_t *pool)
{
propfind_context_t *new_prop_ctx;
svn_ra_serf__handler_t *handler;
@@ -576,15 +462,11 @@ svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
new_prop_ctx = apr_pcalloc(pool, sizeof(*new_prop_ctx));
- new_prop_ctx->pool = apr_hash_pool_get(ret_props);
new_prop_ctx->path = path;
new_prop_ctx->find_props = find_props;
- new_prop_ctx->ret_props = ret_props;
+ new_prop_ctx->prop_func = prop_func;
+ new_prop_ctx->prop_func_baton = prop_func_baton;
new_prop_ctx->depth = depth;
- new_prop_ctx->sess = sess;
- new_prop_ctx->conn = conn;
- new_prop_ctx->rev = rev;
- new_prop_ctx->done_list = done_list;
if (SVN_IS_VALID_REVNUM(rev))
{
@@ -601,7 +483,9 @@ svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
NULL,
new_prop_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(sess, xmlctx,
+ propfind_expected_status,
+ pool);
handler->method = "PROPFIND";
handler->path = path;
@@ -611,8 +495,7 @@ svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
handler->header_delegate = setup_propfind_headers;
handler->header_delegate_baton = new_prop_ctx;
- handler->session = new_prop_ctx->sess;
- handler->conn = new_prop_ctx->conn;
+ handler->no_dav_headers = TRUE;
new_prop_ctx->handler = handler;
@@ -621,208 +504,85 @@ svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
return SVN_NO_ERROR;
}
-
-/*
- * This helper function will block until the PROP_CTX indicates that is done
- * or another error is returned.
- */
svn_error_t *
-svn_ra_serf__wait_for_props(svn_ra_serf__handler_t *handler,
- apr_pool_t *scratch_pool)
+svn_ra_serf__deliver_svn_props(void *baton,
+ const char *path,
+ const char *ns,
+ const char *name,
+ const svn_string_t *value,
+ apr_pool_t *scratch_pool)
{
- svn_error_t *err;
- svn_error_t *err2;
+ apr_hash_t *props = baton;
+ apr_pool_t *result_pool = apr_hash_pool_get(props);
+ const char *prop_name;
- err = svn_ra_serf__context_run_one(handler, scratch_pool);
+ prop_name = svn_ra_serf__svnname_from_wirename(ns, name, result_pool);
+ if (prop_name == NULL)
+ return SVN_NO_ERROR;
- err2 = svn_ra_serf__error_on_status(handler->sline,
- handler->path,
- handler->location);
+ svn_hash_sets(props, prop_name, svn_string_dup(value, result_pool));
- return svn_error_compose_create(err2, err);
+ return SVN_NO_ERROR;
}
/*
- * This is a blocking version of deliver_props.
+ * Implementation of svn_ra_serf__prop_func_t that delivers all DAV properties
+ * in (const char * -> apr_hash_t *) on Namespace pointing to a second hash
+ * (const char * -> svn_string_t *) to the values.
*/
-svn_error_t *
-svn_ra_serf__retrieve_props(apr_hash_t **results,
- svn_ra_serf__session_t *sess,
- svn_ra_serf__connection_t *conn,
- const char *url,
- svn_revnum_t rev,
- const char *depth,
- const svn_ra_serf__dav_props_t *props,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+deliver_node_props(void *baton,
+ const char *path,
+ const char *ns,
+ const char *name,
+ const svn_string_t *value,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__handler_t *handler;
+ apr_hash_t *nss = baton;
+ apr_hash_t *props;
+ apr_pool_t *result_pool = apr_hash_pool_get(nss);
- *results = apr_hash_make(result_pool);
+ props = svn_hash_gets(nss, ns);
- SVN_ERR(svn_ra_serf__deliver_props(&handler, *results, sess, conn, url,
- rev, depth, props, NULL, result_pool));
- SVN_ERR(svn_ra_serf__wait_for_props(handler, scratch_pool));
+ if (!props)
+ {
+ props = apr_hash_make(result_pool);
+
+ ns = apr_pstrdup(result_pool, ns);
+ svn_hash_sets(nss, ns, props);
+ }
+
+ name = apr_pstrdup(result_pool, name);
+ svn_hash_sets(props, name, svn_string_dup(value, result_pool));
return SVN_NO_ERROR;
}
-
svn_error_t *
svn_ra_serf__fetch_node_props(apr_hash_t **results,
- svn_ra_serf__connection_t *conn,
+ svn_ra_serf__session_t *session,
const char *url,
svn_revnum_t revision,
const svn_ra_serf__dav_props_t *which_props,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- apr_hash_t *multiprops;
- apr_hash_t *ver_props;
-
- /* Note: a couple extra hash tables and whatnot get into RESULT_POOL.
- Not a big deal at this point. Theoretically, we could fetch all
- props into SCRATCH_POOL, then copy just the REVISION/URL props
- into RESULT_POOL. Too much work for too little gain... */
- SVN_ERR(svn_ra_serf__retrieve_props(&multiprops, conn->session, conn,
- url, revision, "0", which_props,
- result_pool, scratch_pool));
-
- ver_props = apr_hash_get(multiprops, &revision, sizeof(revision));
- if (ver_props != NULL)
- {
- *results = svn_hash_gets(ver_props, url);
- if (*results != NULL)
- return SVN_NO_ERROR;
- }
-
- return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
- _("The PROPFIND response did not include "
- "the requested properties"));
-}
-
-
-svn_error_t *
-svn_ra_serf__walk_node_props(apr_hash_t *props,
- svn_ra_serf__walker_visitor_t walker,
- void *baton,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *iterpool;
- apr_hash_index_t *ns_hi;
-
- iterpool = svn_pool_create(scratch_pool);
- for (ns_hi = apr_hash_first(scratch_pool, props); ns_hi;
- ns_hi = apr_hash_next(ns_hi))
- {
- void *ns_val;
- const void *ns_name;
- apr_hash_index_t *name_hi;
-
- /* NOTE: We do not clear ITERPOOL in this loop. Generally, there are
- very few namespaces, so this loop will not have many iterations.
- Instead, ITERPOOL is used for the inner loop. */
-
- apr_hash_this(ns_hi, &ns_name, NULL, &ns_val);
-
- for (name_hi = apr_hash_first(scratch_pool, ns_val); name_hi;
- name_hi = apr_hash_next(name_hi))
- {
- void *prop_val;
- const void *prop_name;
-
- /* See note above, regarding clearing of this pool. */
- svn_pool_clear(iterpool);
-
- apr_hash_this(name_hi, &prop_name, NULL, &prop_val);
-
- SVN_ERR(walker(baton, ns_name, prop_name, prop_val, iterpool));
- }
- }
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_ra_serf__walk_all_props(apr_hash_t *props,
- const char *name,
- svn_revnum_t rev,
- svn_ra_serf__walker_visitor_t walker,
- void *baton,
- apr_pool_t *scratch_pool)
-{
- apr_hash_t *ver_props;
- apr_hash_t *path_props;
-
- ver_props = apr_hash_get(props, &rev, sizeof(rev));
- if (!ver_props)
- return SVN_NO_ERROR;
-
- path_props = svn_hash_gets(ver_props, name);
- if (!path_props)
- return SVN_NO_ERROR;
-
- return svn_error_trace(svn_ra_serf__walk_node_props(path_props,
- walker, baton,
- scratch_pool));
-}
-
-
-svn_error_t *
-svn_ra_serf__walk_all_paths(apr_hash_t *props,
- svn_revnum_t rev,
- svn_ra_serf__path_rev_walker_t walker,
- void *baton,
- apr_pool_t *pool)
-{
- apr_hash_index_t *path_hi;
- apr_hash_t *ver_props;
+ apr_hash_t *props;
+ svn_ra_serf__handler_t *handler;
- ver_props = apr_hash_get(props, &rev, sizeof(rev));
+ props = apr_hash_make(result_pool);
- if (!ver_props)
- {
- return SVN_NO_ERROR;
- }
+ SVN_ERR(svn_ra_serf__create_propfind_handler(&handler, session,
+ url, revision, "0", which_props,
+ deliver_node_props,
+ props, scratch_pool));
- for (path_hi = apr_hash_first(pool, ver_props); path_hi;
- path_hi = apr_hash_next(path_hi))
- {
- void *path_props;
- const void *path_name;
- apr_ssize_t path_len;
- apr_hash_index_t *ns_hi;
-
- apr_hash_this(path_hi, &path_name, &path_len, &path_props);
- for (ns_hi = apr_hash_first(pool, path_props); ns_hi;
- ns_hi = apr_hash_next(ns_hi))
- {
- void *ns_val;
- const void *ns_name;
- apr_ssize_t ns_len;
- apr_hash_index_t *name_hi;
- apr_hash_this(ns_hi, &ns_name, &ns_len, &ns_val);
- for (name_hi = apr_hash_first(pool, ns_val); name_hi;
- name_hi = apr_hash_next(name_hi))
- {
- void *prop_val;
- const void *prop_name;
- apr_ssize_t prop_len;
-
- apr_hash_this(name_hi, &prop_name, &prop_len, &prop_val);
- /* use a subpool? */
- SVN_ERR(walker(baton, path_name, path_len, ns_name, ns_len,
- prop_name, prop_len, prop_val, pool));
- }
- }
- }
+ SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
+ *results = props;
return SVN_NO_ERROR;
}
-
const char *
svn_ra_serf__svnname_from_wirename(const char *ns,
const char *name,
@@ -832,10 +592,10 @@ svn_ra_serf__svnname_from_wirename(const char *ns,
return apr_pstrdup(result_pool, name);
if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
- return apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
+ return apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, SVN_VA_NULL);
if (strcmp(ns, SVN_PROP_PREFIX) == 0)
- return apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
+ return apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, SVN_VA_NULL);
if (strcmp(name, SVN_DAV__VERSION_NAME) == 0)
return SVN_PROP_ENTRY_COMMITTED_REV;
@@ -863,99 +623,9 @@ svn_ra_serf__svnname_from_wirename(const char *ns,
}
/* An unknown namespace, must be a custom property. */
- return apr_pstrcat(result_pool, ns, name, (char *)NULL);
+ return apr_pstrcat(result_pool, ns, name, SVN_VA_NULL);
}
-
-/* Conforms to svn_ra_serf__walker_visitor_t */
-static svn_error_t *
-set_flat_props(void *baton,
- const char *ns,
- const char *name,
- const svn_string_t *value,
- apr_pool_t *pool)
-{
- apr_hash_t *props = baton;
- apr_pool_t *result_pool = apr_hash_pool_get(props);
- const char *prop_name;
-
- /* ### is VAL in the proper pool? */
-
- prop_name = svn_ra_serf__svnname_from_wirename(ns, name, result_pool);
- if (prop_name != NULL)
- svn_hash_sets(props, prop_name, value);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_ra_serf__flatten_props(apr_hash_t **flat_props,
- apr_hash_t *props,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- *flat_props = apr_hash_make(result_pool);
-
- return svn_error_trace(svn_ra_serf__walk_node_props(
- props,
- set_flat_props,
- *flat_props /* baton */,
- scratch_pool));
-}
-
-
-static svn_error_t *
-select_revprops(void *baton,
- const char *ns,
- const char *name,
- const svn_string_t *val,
- apr_pool_t *scratch_pool)
-{
- apr_hash_t *revprops = baton;
- apr_pool_t *result_pool = apr_hash_pool_get(revprops);
- const char *prop_name;
-
- /* ### copy NAME into the RESULT_POOL? */
- /* ### copy VAL into the RESULT_POOL? */
-
- 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(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
- else if (strcmp(ns, SVN_PROP_PREFIX) == 0)
- prop_name = apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
- else if (strcmp(ns, "") == 0)
- prop_name = name;
- else
- {
- /* do nothing for now? */
- return SVN_NO_ERROR;
- }
-
- svn_hash_sets(revprops, prop_name, val);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_ra_serf__select_revprops(apr_hash_t **revprops,
- const char *name,
- svn_revnum_t rev,
- apr_hash_t *all_revprops,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- *revprops = apr_hash_make(result_pool);
-
- return svn_error_trace(svn_ra_serf__walk_all_props(
- all_revprops, name, rev,
- select_revprops, *revprops,
- scratch_pool));
-}
-
-
/*
* Contact the server (using CONN) to calculate baseline
* information for BASELINE_URL at REVISION (which may be
@@ -969,7 +639,7 @@ svn_ra_serf__select_revprops(apr_hash_t **revprops,
static svn_error_t *
retrieve_baseline_info(svn_revnum_t *actual_revision,
const char **basecoll_url_p,
- svn_ra_serf__connection_t *conn,
+ svn_ra_serf__session_t *session,
const char *baseline_url,
svn_revnum_t revision,
apr_pool_t *result_pool,
@@ -979,7 +649,7 @@ retrieve_baseline_info(svn_revnum_t *actual_revision,
apr_hash_t *dav_props;
const char *basecoll_url;
- SVN_ERR(svn_ra_serf__fetch_node_props(&props, conn,
+ SVN_ERR(svn_ra_serf__fetch_node_props(&props, session,
baseline_url, revision,
baseline_props,
scratch_pool, scratch_pool));
@@ -1000,12 +670,18 @@ retrieve_baseline_info(svn_revnum_t *actual_revision,
const char *version_name;
version_name = svn_prop_get_value(dav_props, SVN_DAV__VERSION_NAME);
- if (!version_name)
+ if (version_name)
+ {
+ apr_int64_t rev;
+
+ SVN_ERR(svn_cstring_atoi64(&rev, version_name));
+ *actual_revision = (svn_revnum_t)rev;
+ }
+
+ if (!version_name || !SVN_IS_VALID_REVNUM(*actual_revision))
return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
_("The PROPFIND response did not include "
"the requested version-name value"));
-
- *actual_revision = SVN_STR_TO_REV(version_name);
}
return SVN_NO_ERROR;
@@ -1023,7 +699,7 @@ retrieve_baseline_info(svn_revnum_t *actual_revision,
static svn_error_t *
v1_get_youngest_revnum(svn_revnum_t *youngest,
const char **basecoll_url,
- svn_ra_serf__connection_t *conn,
+ svn_ra_serf__session_t *session,
const char *vcc_url,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -1033,7 +709,7 @@ v1_get_youngest_revnum(svn_revnum_t *youngest,
/* Fetching DAV:checked-in from the VCC (with no Label: to specify a
revision) will return the latest Baseline resource's URL. */
- SVN_ERR(svn_ra_serf__fetch_dav_prop(&baseline_url, conn, vcc_url,
+ SVN_ERR(svn_ra_serf__fetch_dav_prop(&baseline_url, session, vcc_url,
SVN_INVALID_REVNUM,
"checked-in",
scratch_pool, scratch_pool));
@@ -1052,15 +728,15 @@ v1_get_youngest_revnum(svn_revnum_t *youngest,
/* First check baseline information cache. */
SVN_ERR(svn_ra_serf__blncache_get_baseline_info(&bc_url,
youngest,
- conn->session->blncache,
+ session->blncache,
baseline_url,
scratch_pool));
if (!bc_url)
{
- SVN_ERR(retrieve_baseline_info(youngest, &bc_url, conn,
+ SVN_ERR(retrieve_baseline_info(youngest, &bc_url, session,
baseline_url, SVN_INVALID_REVNUM,
scratch_pool, scratch_pool));
- SVN_ERR(svn_ra_serf__blncache_set(conn->session->blncache,
+ SVN_ERR(svn_ra_serf__blncache_set(session->blncache,
baseline_url, *youngest,
bc_url, scratch_pool));
}
@@ -1081,12 +757,12 @@ svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest,
if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
return svn_error_trace(svn_ra_serf__v2_get_youngest_revnum(
- youngest, session->conns[0], scratch_pool));
+ youngest, session, scratch_pool));
- SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, NULL, scratch_pool));
+ SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, scratch_pool));
return svn_error_trace(v1_get_youngest_revnum(youngest, NULL,
- session->conns[0], vcc_url,
+ session, vcc_url,
scratch_pool, scratch_pool));
}
@@ -1103,9 +779,9 @@ static svn_error_t *
get_baseline_info(const char **bc_url,
svn_revnum_t *revnum_used,
svn_ra_serf__session_t *session,
- svn_ra_serf__connection_t *conn,
svn_revnum_t revision,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
/* If we detected HTTP v2 support on the server, we can construct
the baseline collection URL ourselves, and fetch the latest
@@ -1119,14 +795,10 @@ get_baseline_info(const char **bc_url,
else
{
SVN_ERR(svn_ra_serf__v2_get_youngest_revnum(
- revnum_used, conn, pool));
- if (! SVN_IS_VALID_REVNUM(*revnum_used))
- return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
- _("The OPTIONS response did not include "
- "the youngest revision"));
+ revnum_used, session, scratch_pool));
}
- *bc_url = apr_psprintf(pool, "%s/%ld",
+ *bc_url = apr_psprintf(result_pool, "%s/%ld",
session->rev_root_stub, *revnum_used);
}
@@ -1135,20 +807,22 @@ get_baseline_info(const char **bc_url,
{
const char *vcc_url;
- SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, conn, pool));
+ SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, scratch_pool));
if (SVN_IS_VALID_REVNUM(revision))
{
/* First check baseline information cache. */
SVN_ERR(svn_ra_serf__blncache_get_bc_url(bc_url,
session->blncache,
- revision, pool));
+ revision, result_pool));
if (!*bc_url)
{
- SVN_ERR(retrieve_baseline_info(NULL, bc_url, conn,
- vcc_url, revision, pool, pool));
+ SVN_ERR(retrieve_baseline_info(NULL, bc_url, session,
+ vcc_url, revision,
+ result_pool, scratch_pool));
SVN_ERR(svn_ra_serf__blncache_set(session->blncache, NULL,
- revision, *bc_url, pool));
+ revision, *bc_url,
+ scratch_pool));
}
*revnum_used = revision;
@@ -1156,8 +830,8 @@ get_baseline_info(const char **bc_url,
else
{
SVN_ERR(v1_get_youngest_revnum(revnum_used, bc_url,
- conn, vcc_url,
- pool, pool));
+ session, vcc_url,
+ result_pool, scratch_pool));
}
}
@@ -1169,7 +843,6 @@ svn_error_t *
svn_ra_serf__get_stable_url(const char **stable_url,
svn_revnum_t *latest_revnum,
svn_ra_serf__session_t *session,
- svn_ra_serf__connection_t *conn,
const char *url,
svn_revnum_t revision,
apr_pool_t *result_pool,
@@ -1183,15 +856,10 @@ svn_ra_serf__get_stable_url(const char **stable_url,
if (! url)
url = session->session_url.path;
- /* If the caller didn't provide a specific connection for us to use,
- we'll use the default connection. */
- if (! conn)
- conn = session->conns[0];
-
SVN_ERR(get_baseline_info(&basecoll_url, &revnum_used,
- session, conn, revision, scratch_pool));
+ session, revision, scratch_pool, scratch_pool));
SVN_ERR(svn_ra_serf__get_relative_path(&repos_relpath, url,
- session, conn, scratch_pool));
+ session, scratch_pool));
*stable_url = svn_path_url_add_component2(basecoll_url, repos_relpath,
result_pool);
@@ -1203,38 +871,8 @@ svn_ra_serf__get_stable_url(const char **stable_url,
svn_error_t *
-svn_ra_serf__get_resource_type(svn_node_kind_t *kind,
- apr_hash_t *props)
-{
- apr_hash_t *dav_props;
- const char *res_type;
-
- dav_props = apr_hash_get(props, "DAV:", 4);
- res_type = svn_prop_get_value(dav_props, "resourcetype");
- if (!res_type)
- {
- /* How did this happen? */
- return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
- _("The PROPFIND response did not include the "
- "requested resourcetype value"));
- }
-
- if (strcmp(res_type, "collection") == 0)
- {
- *kind = svn_node_dir;
- }
- else
- {
- *kind = svn_node_file;
- }
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
svn_ra_serf__fetch_dav_prop(const char **value,
- svn_ra_serf__connection_t *conn,
+ svn_ra_serf__session_t *session,
const char *url,
svn_revnum_t revision,
const char *propname,
@@ -1244,7 +882,7 @@ svn_ra_serf__fetch_dav_prop(const char **value,
apr_hash_t *props;
apr_hash_t *dav_props;
- SVN_ERR(svn_ra_serf__fetch_node_props(&props, conn, url, revision,
+ SVN_ERR(svn_ra_serf__fetch_node_props(&props, session, url, revision,
checked_in_props,
scratch_pool, scratch_pool));
dav_props = apr_hash_get(props, "DAV:", 4);
@@ -1261,3 +899,19 @@ svn_ra_serf__fetch_dav_prop(const char **value,
return SVN_NO_ERROR;
}
+
+/* Removes all non regular properties from PROPS */
+void
+svn_ra_serf__keep_only_regular_props(apr_hash_t *props,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, props); hi; hi = apr_hash_next(hi))
+ {
+ const char *propname = apr_hash_this_key(hi);
+
+ if (svn_property_kind2(propname) != svn_prop_regular_kind)
+ svn_hash_sets(props, propname, NULL);
+ }
+}