[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Teach ra_dav editor parser to filter unwanted data (for sparse directories)

From: C. Michael Pilato <cmpilato_at_collab.net>
Date: 2007-04-20 21:42:31 CEST

-- 
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

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.