--
C. Michael Pilato <cmpilato@collab.net>
CollabNet <> www.collab.net <> Distributed Development On Demand
Teach the ra_DAV editor parser to filter out unwanted stuff based on
the requested depth of the operation. This is useful for
compatibility with older depth-ignorant servers.
* subversion/libsvn_ra_dav/fetch.c
(report_baton_t): Add 'is_file' and 'depth' members.
(okay_to_edit): New helper function.
(start_element, end_element): Use okay_to_edit() to avoid making
editor and RA callback calls for items outside the scope of the
requested edit operation. Use the report baton's 'is_file' member
to determine if we're handling a file instead of the 'file_baton'
member, which now may be NULL simply because we're "in too deep"
in the edit.
(add_node_props): Rework this function to reduce redundancy, and use
the report baton's 'is_file' member to make the file/dir
determination.
(make_reporter): Populate report baton's 'depth' member.
Index: subversion/libsvn_ra_dav/fetch.c
===================================================================
--- subversion/libsvn_ra_dav/fetch.c (revision 24685)
+++ subversion/libsvn_ra_dav/fetch.c (working copy)
@@ -149,7 +149,12 @@
#define DIR_DEPTH(rb) ((rb)->dirs->nelts)
#define PUSH_BATON(rb,b) (APR_ARRAY_PUSH((rb)->dirs, void *) = (b))
- /* These items are only valid inside add- and open-file tags! */
+ /* Are we currently handling a file? */
+ svn_boolean_t is_file;
+
+ /* These items are only valid inside add- and open-file tags, and
+ even then, only when handling files that aren't out-of-scope by
+ way of the requested 'depth' for the edit drive. */
void *file_baton;
apr_pool_t *file_pool;
const char *result_checksum; /* hex md5 digest of result; may be null */
@@ -201,6 +206,9 @@
otherwise, it stays false (i.e., it's not a modern server). */
svn_boolean_t receiving_all;
+ /* The requested depth of the operation. */
+ svn_depth_t depth;
+
} report_baton_t;
static const svn_ra_dav__xml_elm_t report_elements[] =
@@ -1991,6 +1999,39 @@
di->pool = pool;
}
+/* Return TRUE iff we are allowed to open/add/modify a node of kind
+ KIND based on our current position in an editor drive as determined
+ by examining the report baton RB. */
+static svn_boolean_t
+okay_to_edit(report_baton_t *rb,
+ svn_node_kind_t kind)
+{
+ /* The effective depth is based not just on the number of dir batons
+ on the stack, but also whether there was a target for the
+ operation. If there was a target, then the root of the edit has
+ a depth of -1 and the target has a depth of 0. If there was no
+ target, or then the root of the edit has a depth of 0. */
+
+ int effective_depth = rb->dirs->nelts - (*(rb->target) ? 1 : 0);
+ switch (rb->depth)
+ {
+ case svn_depth_empty:
+ return (kind == svn_node_dir && effective_depth <= 0);
+ case svn_depth_files:
+ return ((effective_depth <= 0)
+ || (kind == svn_node_file && effective_depth == 1));
+ case svn_depth_immediates:
+ return (effective_depth <= 1);
+ case svn_depth_infinity:
+ return TRUE;
+ default:
+ abort();
+ }
+ /* we should never get here */
+ return FALSE;
+}
+
+
/* This implements the `ne_xml_startelm_cb' prototype. */
static svn_error_t *
start_element(int *elem, void *userdata, int parent, const char *nspace,
@@ -2004,7 +2045,7 @@
svn_stringbuf_t *cpath = NULL;
svn_revnum_t crev = SVN_INVALID_REVNUM;
dir_item_t *parent_dir;
- void *new_dir_baton;
+ void *new_dir_baton = NULL;
svn_stringbuf_t *pathbuf;
apr_pool_t *subpool;
const char *base_checksum = NULL;
@@ -2038,6 +2079,10 @@
name = svn_xml_get_attr_value("name", atts);
/* ### verify we got it. punt on error. */
+ /* Ignore editor drive portions outside our requested depth. */
+ if (! okay_to_edit(rb, svn_node_dir))
+ break;
+
parent_dir = &TOP_DIR(rb);
pathbuf = svn_stringbuf_dup(parent_dir->pathbuf, parent_dir->pool);
svn_path_add_component(pathbuf, name);
@@ -2051,6 +2096,10 @@
name = svn_xml_get_attr_value("name", atts);
/* ### verify we got it. punt on error. */
+ /* Ignore editor drive portions outside our requested depth. */
+ if (okay_to_edit(rb, svn_node_file))
+ break;
+
parent_dir = &TOP_DIR(rb);
pathbuf = svn_stringbuf_dup(parent_dir->pathbuf, parent_dir->pool);
svn_path_add_component(pathbuf, name);
@@ -2063,6 +2112,7 @@
case ELEM_resource:
att = svn_xml_get_attr_value("path", atts);
/* ### verify we got it. punt on error. */
+
svn_stringbuf_set(rb->current_wcprop_path, att);
rb->in_resource = TRUE;
break;
@@ -2090,9 +2140,6 @@
subpool = svn_pool_create(rb->pool);
SVN_ERR((*rb->editor->open_root)(rb->edit_baton, base,
subpool, &new_dir_baton));
-
- /* push the new baton onto the directory baton stack */
- push_dir(rb, new_dir_baton, pathbuf, subpool);
}
else
{
@@ -2104,17 +2151,23 @@
subpool = svn_pool_create(parent_dir->pool);
pathbuf = svn_stringbuf_dup(parent_dir->pathbuf, subpool);
- svn_path_add_component(pathbuf, rb->namestr->data);
+ svn_path_add_component(pathbuf, name);
- SVN_ERR((*rb->editor->open_directory)(pathbuf->data,
- parent_dir->baton, base,
- subpool,
- &new_dir_baton));
+ /* Only really call the editor if we're within our requested
+ depth. */
+ if (okay_to_edit(rb, svn_node_dir))
+ SVN_ERR((*rb->editor->open_directory)(pathbuf->data,
+ parent_dir->baton, base,
+ subpool,
+ &new_dir_baton));
- /* push the new baton onto the directory baton stack */
- push_dir(rb, new_dir_baton, pathbuf, subpool);
}
+ /* Push the new baton onto the directory baton stack. If this
+ directory was outside our requested depth, NEW_DIR_BATON will
+ be NULL. */
+ push_dir(rb, new_dir_baton, pathbuf, subpool);
+
/* Property fetching is NOT implied in replacement. */
TOP_DIR(rb).fetch_props = FALSE;
break;
@@ -2140,13 +2193,17 @@
pathbuf = svn_stringbuf_dup(parent_dir->pathbuf, subpool);
svn_path_add_component(pathbuf, rb->namestr->data);
+
+ /* Only really call the editor if we're within our requested depth. */
+ if (okay_to_edit(rb, svn_node_dir))
+ SVN_ERR((*rb->editor->add_directory)(pathbuf->data, parent_dir->baton,
+ cpath ? cpath->data : NULL,
+ crev, subpool,
+ &new_dir_baton));
- SVN_ERR((*rb->editor->add_directory)(pathbuf->data, parent_dir->baton,
- cpath ? cpath->data : NULL,
- crev, subpool,
- &new_dir_baton));
-
- /* push the new baton onto the directory baton stack */
+ /* Push the new baton onto the directory baton stack. If this
+ directory was outside our requested depth, NEW_DIR_BATON will
+ be NULL. */
push_dir(rb, new_dir_baton, pathbuf, subpool);
/* Property fetching is implied in addition. This flag is only
@@ -2154,15 +2211,16 @@
a modern server. */
TOP_DIR(rb).fetch_props = TRUE;
- bc_url = svn_xml_get_attr_value("bc-url", atts);
-
/* In non-modern report responses, we're just told to fetch the
props later. In that case, we can at least do a pre-emptive
depth-1 propfind on the directory right now; this prevents
individual propfinds on added-files later on, thus reducing
the number of network turnarounds (though not by as much as
- simply getting a modern report response!). */
- if ((! rb->receiving_all) && bc_url)
+ simply getting a modern report response!).
+
+ Only bother to do this if we really added the directory. */
+ bc_url = svn_xml_get_attr_value("bc-url", atts);
+ if (TOP_DIR(rb).baton && ((! rb->receiving_all) && bc_url))
{
apr_hash_t *bc_children;
SVN_ERR(svn_ra_dav__get_props(&bc_children,
@@ -2204,67 +2262,64 @@
break;
case ELEM_open_file:
- att = svn_xml_get_attr_value("rev", atts);
- /* ### verify we got it. punt on error. */
- base = SVN_STR_TO_REV(att);
-
+ case ELEM_add_file:
name = svn_xml_get_attr_value("name", atts);
/* ### verify we got it. punt on error. */
svn_stringbuf_set(rb->namestr, name);
- parent_dir = &TOP_DIR(rb);
- rb->file_pool = svn_pool_create(parent_dir->pool);
- rb->result_checksum = NULL;
-
/* Add this file's name into the directory's path buffer. It will be
removed in end_element() */
+ parent_dir = &TOP_DIR(rb);
svn_path_add_component(parent_dir->pathbuf, rb->namestr->data);
- SVN_ERR((*rb->editor->open_file)(parent_dir->pathbuf->data,
- parent_dir->baton, base,
- rb->file_pool,
- &rb->file_baton));
+ /* If it's okay to make this edit, do so. */
+ if (okay_to_edit(rb, svn_node_file))
+ {
+ rb->file_pool = svn_pool_create(parent_dir->pool);
+ if (elm->id == ELEM_open_file)
+ {
+ att = svn_xml_get_attr_value("rev", atts);
+ /* ### verify we got it. punt on error. */
+ base = SVN_STR_TO_REV(att);
- /* Property fetching is NOT implied in replacement. */
- rb->fetch_props = FALSE;
+ SVN_ERR((*rb->editor->open_file)(parent_dir->pathbuf->data,
+ parent_dir->baton, base,
+ rb->file_pool,
+ &rb->file_baton));
- break;
+ /* Property fetching is NOT implied in replacement. */
+ rb->fetch_props = FALSE;
+ }
+ else
+ {
+ att = svn_xml_get_attr_value("copyfrom-path", atts);
+ if (att != NULL)
+ {
+ cpath = rb->cpathstr;
+ svn_stringbuf_set(cpath, att);
+
+ att = svn_xml_get_attr_value("copyfrom-rev", atts);
+ /* ### verify we got it. punt on error. */
+ crev = SVN_STR_TO_REV(att);
+ }
- case ELEM_add_file:
- name = svn_xml_get_attr_value("name", atts);
- /* ### verify we got it. punt on error. */
- svn_stringbuf_set(rb->namestr, name);
-
- att = svn_xml_get_attr_value("copyfrom-path", atts);
- if (att != NULL)
- {
- cpath = rb->cpathstr;
- svn_stringbuf_set(cpath, att);
-
- att = svn_xml_get_attr_value("copyfrom-rev", atts);
- /* ### verify we got it. punt on error. */
- crev = SVN_STR_TO_REV(att);
+ SVN_ERR((*rb->editor->add_file)(parent_dir->pathbuf->data,
+ parent_dir->baton,
+ cpath ? cpath->data : NULL,
+ crev, rb->file_pool,
+ &rb->file_baton));
+
+ /* Property fetching is implied in addition. This flag is only
+ for parsing old-style reports; it is ignored when talking to
+ a modern server. */
+ rb->fetch_props = TRUE;
+ }
}
- parent_dir = &TOP_DIR(rb);
- rb->file_pool = svn_pool_create(parent_dir->pool);
+ /* Record file-specific state. */
rb->result_checksum = NULL;
+ rb->is_file = TRUE;
- /* Add this file's name into the directory's path buffer. It will be
- removed in end_element() */
- svn_path_add_component(parent_dir->pathbuf, rb->namestr->data);
-
- SVN_ERR((*rb->editor->add_file)(parent_dir->pathbuf->data,
- parent_dir->baton,
- cpath ? cpath->data : NULL,
- crev, rb->file_pool,
- &rb->file_baton));
-
- /* Property fetching is implied in addition. This flag is only
- for parsing old-style reports; it is ignored when talking to
- a modern server. */
- rb->fetch_props = TRUE;
-
break;
case ELEM_txdelta:
@@ -2276,6 +2331,11 @@
if (! rb->receiving_all)
break;
+ /* No file baton? No file contents. (We leave rb->base64_decoder
+ NULL as a flag to other handlers of this tag.) */
+ if (! rb->file_baton)
+ break;
+
SVN_ERR((*rb->editor->apply_textdelta)(rb->file_baton,
NULL, /* ### base_checksum */
rb->file_pool,
@@ -2301,7 +2361,8 @@
else
svn_stringbuf_setempty(rb->encoding);
}
-
+ /* (In case you're wordering, the actual work of setting the
+ property is done at tag closure time.) */
break;
case ELEM_remove_prop:
@@ -2309,8 +2370,12 @@
/* ### verify we got it. punt on error. */
svn_stringbuf_set(rb->namestr, name);
- /* Removing a prop. */
- if (rb->file_baton == NULL)
+ /* No baton? No propchanges. */
+ if (! (rb->is_file ? rb->file_baton : TOP_DIR(rb).baton))
+ break;
+
+ /* Remove the property. */
+ if (! rb->is_file)
SVN_ERR(rb->editor->change_dir_prop(TOP_DIR(rb).baton,
rb->namestr->data,
NULL, TOP_DIR(rb).pool));
@@ -2320,6 +2385,10 @@
break;
case ELEM_fetch_props:
+ /* No baton? No propfetching. */
+ if (! (rb->is_file ? rb->file_baton : TOP_DIR(rb).baton))
+ break;
+
if (!rb->fetch_content)
{
/* If this is just a status check, the specifics of the
@@ -2328,7 +2397,7 @@
property mod. */
svn_stringbuf_set(rb->namestr, SVN_PROP_PREFIX "BOGOSITY");
- if (rb->file_baton == NULL)
+ if (! rb->is_file)
SVN_ERR(rb->editor->change_dir_prop(TOP_DIR(rb).baton,
rb->namestr->data,
NULL, TOP_DIR(rb).pool));
@@ -2340,7 +2409,7 @@
else
{
/* Note that we need to fetch props for this... */
- if (rb->file_baton == NULL)
+ if (! rb->is_file)
TOP_DIR(rb).fetch_props = TRUE; /* ...directory. */
else
rb->fetch_props = TRUE; /* ...file. */
@@ -2348,6 +2417,10 @@
break;
case ELEM_fetch_file:
+ /* No baton? No propfetching. */
+ if (! rb->file_baton)
+ break;
+
base_checksum = svn_xml_get_attr_value("base-checksum", atts);
rb->result_checksum = NULL;
@@ -2383,6 +2456,13 @@
parent_dir = &TOP_DIR(rb);
+ /* Ignore editor drive portions outside our requested depth. */
+ /* ### TODO(sd): We lie here and say this is a file when we
+ actually have no idea what the kind is. Better to be
+ intentionally conservative than accidentally liberal. */
+ if (! okay_to_edit(rb, svn_node_file))
+ break;
+
/* Pool use is a little non-standard here. When lots of items in the
same directory get deleted each one will trigger a call to
editor->delete_entry, but we don't have a pool that readily fits
@@ -2416,71 +2496,44 @@
{
svn_ra_dav__resource_t *rsrc = NULL;
apr_hash_t *props = NULL;
+ const char *url;
/* Do nothing if parsing a modern report, because the properties
already come inline. */
if (rb->receiving_all)
return SVN_NO_ERROR;
- /* Do nothing if we aren't fetching content. */
+ /* Do nothing if we aren't fetching content. */
if (!rb->fetch_content)
return SVN_NO_ERROR;
- if (rb->file_baton)
- {
- if (! rb->fetch_props)
- return SVN_NO_ERROR;
+ /* Do nothing if we aren't fetching props. */
+ if (! (rb->is_file ? rb->fetch_props : TOP_DIR(rb).fetch_props))
+ return SVN_NO_ERROR;
- /* Check to see if your parent directory already has your props
- stored, possibly from a depth-1 propfind. Otherwise just do
- a propfind directly on the file url. */
- if ( ! ((TOP_DIR(rb).children)
- && (props = apr_hash_get(TOP_DIR(rb).children, rb->href->data,
- APR_HASH_KEY_STRING))) )
- {
- SVN_ERR(svn_ra_dav__get_props_resource(&rsrc,
- rb->ras,
- rb->href->data,
- NULL,
- NULL,
- pool));
- props = rsrc->propset;
- }
+ /* Do nothing if we have no baton. */
+ if (! (rb->is_file ? rb->file_baton : TOP_DIR(rb).baton))
+ return SVN_NO_ERROR;
- SVN_ERR(add_props(props,
- rb->editor->change_file_prop,
- rb->file_baton,
- pool));
+ /* Check to see if your parent directory already has your props
+ stored, possibly from a depth-1 propfind. Otherwise just do a
+ propfind directly on the URL. */
+ url = rb->is_file ? rb->href->data : TOP_DIR(rb).vsn_url;
+ if (! ((TOP_DIR(rb).children)
+ && (props = apr_hash_get(TOP_DIR(rb).children, url,
+ APR_HASH_KEY_STRING))))
+ {
+ SVN_ERR(svn_ra_dav__get_props_resource(&rsrc, rb->ras, url, NULL,
+ NULL, pool));
+ props = rsrc->propset;
}
+
+ if (rb->is_file)
+ return add_props(props, rb->editor->change_file_prop,
+ rb->file_baton, pool);
else
- {
- if (! TOP_DIR(rb).fetch_props)
- return SVN_NO_ERROR;
-
- /* Check to see if your props are already stored, possibly from
- a depth-1 propfind. Otherwise just do a propfind directly on
- the directory url. */
- if ( ! ((TOP_DIR(rb).children)
- && (props = apr_hash_get(TOP_DIR(rb).children,
- TOP_DIR(rb).vsn_url,
- APR_HASH_KEY_STRING))) )
- {
- SVN_ERR(svn_ra_dav__get_props_resource(&rsrc,
- rb->ras,
- TOP_DIR(rb).vsn_url,
- NULL,
- NULL,
- pool));
- props = rsrc->propset;
- }
-
- SVN_ERR(add_props(props,
- rb->editor->change_dir_prop,
- TOP_DIR(rb).baton,
- pool));
- }
-
- return SVN_NO_ERROR;
+ return add_props(props, rb->editor->change_dir_prop,
+ TOP_DIR(rb).baton, pool);
}
/* This implements the `svn_ra_dav__cdata_cb_t' prototype. */
@@ -2512,6 +2565,10 @@
if (! rb->receiving_all)
break;
+ /* No decoder? No problem. (But no file contents, either.) */
+ if (! rb->base64_decoder)
+ break;
+
SVN_ERR(svn_stream_write(rb->base64_decoder, cdata, &nlen));
if (nlen != len)
{
@@ -2565,8 +2622,10 @@
/* Close the directory on top of the stack, and pop it. Also,
destroy the subpool used exclusive by this directory and its
children. */
- SVN_ERR((*rb->editor->close_directory)(TOP_DIR(rb).baton,
- TOP_DIR(rb).pool));
+ if (TOP_DIR(rb).baton)
+ SVN_ERR((*rb->editor->close_directory)(TOP_DIR(rb).baton,
+ TOP_DIR(rb).pool));
+
svn_pool_destroy(TOP_DIR(rb).pool);
apr_array_pop(rb->dirs);
break;
@@ -2576,37 +2635,43 @@
retrieve the href before fetching. */
/* fetch file */
- if (! rb->receiving_all)
+ if (rb->file_baton)
{
- SVN_ERR(simple_fetch_file(rb->ras,
- rb->href->data,
- TOP_DIR(rb).pathbuf->data,
- rb->fetch_content,
- rb->file_baton,
- NULL, /* no base checksum in an add */
- rb->editor,
- rb->ras->callbacks->get_wc_prop,
- rb->ras->callback_baton,
- rb->file_pool));
-
- /* fetch node props as necessary. */
- SVN_ERR(add_node_props(rb, rb->file_pool));
+ if (! rb->receiving_all)
+ {
+ SVN_ERR(simple_fetch_file(rb->ras,
+ rb->href->data,
+ TOP_DIR(rb).pathbuf->data,
+ rb->fetch_content,
+ rb->file_baton,
+ NULL, /* no base checksum in an add */
+ rb->editor,
+ rb->ras->callbacks->get_wc_prop,
+ rb->ras->callback_baton,
+ rb->file_pool));
+
+ /* fetch node props as necessary. */
+ SVN_ERR(add_node_props(rb, rb->file_pool));
+ }
+
+ /* Close the file and cleanup its pool. */
+ SVN_ERR((*rb->editor->close_file)(rb->file_baton,
+ rb->result_checksum,
+ rb->file_pool));
+ svn_pool_destroy(rb->file_pool);
+ rb->file_pool = NULL;
}
- /* close the file and mark that we are no longer operating on a file */
- SVN_ERR((*rb->editor->close_file)(rb->file_baton,
- rb->result_checksum,
- rb->file_pool));
- rb->file_baton = NULL;
-
/* Yank this file out of the directory's path buffer. */
svn_path_remove_component(TOP_DIR(rb).pathbuf);
- svn_pool_destroy(rb->file_pool);
- rb->file_pool = NULL;
+
+ /* We are no longer operating on a file. */
+ rb->is_file = FALSE;
+ rb->file_baton = NULL;
break;
- case ELEM_txdelta:
- /* Pre 1.2, mod_dav_svn was using <txdelta> tags (in addition to
+ case ELEM_txdelta:
+ /* Pre 1.2, mod_dav_svn was using <txdelta> tags (in addition to
<fetch-file>s and such) when *not* in "send-all" mode. As a
client, we're smart enough to know that's wrong, so when not
in "receiving-all" mode, we'll ignore <txdelta> tags
@@ -2614,6 +2679,9 @@
if (! rb->receiving_all)
break;
+ if (! rb->base64_decoder)
+ break;
+
SVN_ERR(svn_stream_close(rb->base64_decoder));
rb->whandler = NULL;
rb->whandler_baton = NULL;
@@ -2622,81 +2690,90 @@
break;
case ELEM_open_file:
- /* fetch node props as necessary. */
- SVN_ERR(add_node_props(rb, rb->file_pool));
+ if (rb->file_baton)
+ {
+ /* fetch node props as necessary. */
+ SVN_ERR(add_node_props(rb, rb->file_pool));
- /* close the file and mark that we are no longer operating on a file */
- SVN_ERR((*rb->editor->close_file)(rb->file_baton,
+ /* Close the file and cleanup its pool. */
+ SVN_ERR((*rb->editor->close_file)(rb->file_baton,
rb->result_checksum,
rb->file_pool));
- rb->file_baton = NULL;
+ svn_pool_destroy(rb->file_pool);
+ rb->file_pool = NULL;
+ }
/* Yank this file out of the directory's path buffer. */
svn_path_remove_component(TOP_DIR(rb).pathbuf);
- svn_pool_destroy(rb->file_pool);
- rb->file_pool = NULL;
+
+ /* We are no longer operating on a file. */
+ rb->is_file = FALSE;
+ rb->file_baton = NULL;
break;
case ELEM_set_prop:
- {
- svn_string_t decoded_value;
- const svn_string_t *decoded_value_p;
- apr_pool_t *pool;
-
- if (rb->file_baton)
- pool = rb->file_pool;
- else
- pool = TOP_DIR(rb).pool;
+ if (rb->is_file ? rb->file_baton : TOP_DIR(rb).baton)
+ {
+ svn_string_t decoded_value;
+ const svn_string_t *decoded_value_p;
+ apr_pool_t *pool = rb->is_file ? rb->file_pool : TOP_DIR(rb).pool;
- decoded_value.data = rb->cdata_accum->data;
- decoded_value.len = rb->cdata_accum->len;
+ decoded_value.data = rb->cdata_accum->data;
+ decoded_value.len = rb->cdata_accum->len;
- /* Determine the cdata encoding, if any. */
- if (svn_stringbuf_isempty(rb->encoding))
- {
- decoded_value_p = &decoded_value;
- }
- else if (strcmp(rb->encoding->data, "base64") == 0)
- {
- decoded_value_p = svn_base64_decode_string(&decoded_value, pool);
- svn_stringbuf_setempty(rb->encoding);
- }
- else
- {
- SVN_ERR(svn_error_createf(SVN_ERR_XML_UNKNOWN_ENCODING, NULL,
- _("Unknown XML encoding: '%s'"),
- rb->encoding->data));
- abort(); /* Not reached. */
- }
-
- /* Set the prop. */
- if (rb->file_baton)
- {
- SVN_ERR(rb->editor->change_file_prop(rb->file_baton,
- rb->namestr->data,
- decoded_value_p, pool));
- }
- else
- {
- SVN_ERR(rb->editor->change_dir_prop(TOP_DIR(rb).baton,
- rb->namestr->data,
- decoded_value_p, pool));
- }
- }
-
+ /* Determine the cdata encoding, if any. */
+ if (svn_stringbuf_isempty(rb->encoding))
+ {
+ decoded_value_p = &decoded_value;
+ }
+ else if (strcmp(rb->encoding->data, "base64") == 0)
+ {
+ decoded_value_p = svn_base64_decode_string(&decoded_value, pool);
+ svn_stringbuf_setempty(rb->encoding);
+ }
+ else
+ {
+ SVN_ERR(svn_error_createf(SVN_ERR_XML_UNKNOWN_ENCODING, NULL,
+ _("Unknown XML encoding: '%s'"),
+ rb->encoding->data));
+ abort(); /* Not reached. */
+ }
+
+ /* Set the prop. */
+ if (rb->is_file)
+ {
+ SVN_ERR(rb->editor->change_file_prop(rb->file_baton,
+ rb->namestr->data,
+ decoded_value_p, pool));
+ }
+ else
+ {
+ SVN_ERR(rb->editor->change_dir_prop(TOP_DIR(rb).baton,
+ rb->namestr->data,
+ decoded_value_p, pool));
+ }
+ }
+
svn_stringbuf_setempty(rb->cdata_accum);
break;
case ELEM_href:
+ /* If we're fetching content, record the href we just found.
+ Otherwise, we've nothing to do here at all. */
if (rb->fetch_content)
- /* record the href that we just found */
- svn_ra_dav__copy_href(rb->href, rb->cdata_accum->data);
- svn_stringbuf_setempty(rb->cdata_accum);
+ {
+ svn_ra_dav__copy_href(rb->href, rb->cdata_accum->data);
+ svn_stringbuf_setempty(rb->cdata_accum);
+ }
+ else
+ {
+ break;
+ }
- /* do nothing if we aren't fetching content. */
- if (!rb->fetch_content)
+ /* If we've no baton, we're done. */
+ if (! (rb->is_file ? rb->file_baton : TOP_DIR(rb).baton))
break;
-
+
/* if we're within a <resource> tag, then just call the generic
RA set_wcprop_callback directly; no need to use the
update-editor. */
@@ -2716,7 +2793,7 @@
svn_pool_clear(rb->scratch_pool);
}
/* else we're setting a wcprop in the context of an editor drive. */
- else if (rb->file_baton == NULL)
+ else if (! rb->is_file)
{
/* Update the wcprop here, unless this is the top directory
and the real target of this operation is something other
@@ -2756,21 +2833,21 @@
case ELEM_version_name:
case ELEM_creationdate:
case ELEM_creator_displayname:
- {
- /* The name of the xml tag is the property that we want to set. */
- apr_pool_t *pool =
- rb->file_baton ? rb->file_pool : TOP_DIR(rb).pool;
- prop_setter_t setter =
- rb->file_baton ? editor->change_file_prop : editor->change_dir_prop;
- const char *name = apr_pstrcat(pool, elm->nspace, elm->name, NULL);
- void *baton = rb->file_baton ? rb->file_baton : TOP_DIR(rb).baton;
- svn_string_t valstr;
-
- valstr.data = rb->cdata_accum->data;
- valstr.len = rb->cdata_accum->len;
- SVN_ERR(set_special_wc_prop(name, &valstr, setter, baton, pool));
- svn_stringbuf_setempty(rb->cdata_accum);
- }
+ if (! (rb->is_file ? rb->file_baton : TOP_DIR(rb).baton))
+ {
+ /* The name of the xml tag is the property that we want to set. */
+ apr_pool_t *pool = rb->is_file ? rb->file_pool : TOP_DIR(rb).pool;
+ prop_setter_t setter =
+ rb->is_file ? editor->change_file_prop : editor->change_dir_prop;
+ const char *name = apr_pstrcat(pool, elm->nspace, elm->name, NULL);
+ void *baton = rb->is_file ? rb->file_baton : TOP_DIR(rb).baton;
+ svn_string_t valstr;
+
+ valstr.data = rb->cdata_accum->data;
+ valstr.len = rb->cdata_accum->len;
+ SVN_ERR(set_special_wc_prop(name, &valstr, setter, baton, pool));
+ svn_stringbuf_setempty(rb->cdata_accum);
+ }
break;
default:
@@ -3040,6 +3117,7 @@
rb->svndiff_decoder = NULL;
rb->base64_decoder = NULL;
rb->cdata_accum = svn_stringbuf_create("", pool);
+ rb->depth = depth;
/* Neon "pulls" request body content from the caller. The reporter is
organized where data is "pushed" into self. To match these up, we use
Received on Fri Apr 20 21:42:45 2007