Author: pburba Date: Fri Mar 18 01:46:39 2011 New Revision: 1082786 URL: http://svn.apache.org/viewvc?rev=1082786&view=rev Log: Leverage the recent improvements to svn proplist -R[1] so that svn propget -R can do away with svn_wc__node_walk_children().
[1] See r1066541 and r1071283. This is a redo of r1082658, see http://svn.haxx.se/dev/archive-2011-03/0558.shtml * subversion/include/private/svn_skel.h * subversion/libsvn_subr/skel.c (svn_skel__parse_prop): New. * subversion/include/private/svn_wc_private.h (svn_wc__prop_list_recursive): Optionally list only a particular property. * subversion/libsvn_client/externals.c (svn_client__crawl_for_externals): Update call to svn_wc__prop_list_recursive(), forgoing the optional filtering. * subversion/libsvn_client/prop_commands.c (propget_walk_baton, propget_walk_cb): Delete this svn_wc__node_found_func_t callback and its baton and replace them with... (recursive_propget_receiver_baton, recursive_propget_receiver): ...this svn_wc__proplist_receiver_t callback and its baton. (get_prop_from_wc): Reimplement using svn_wc__prop_list_recursive() instead of svn_wc__node_walk_children(). (svn_client_proplist3): Update call to svn_wc__prop_list_recursive(), forgoing the optional filtering. * subversion/libsvn_wc/props.c (svn_wc__prop_list_recursive): Optionally list only a particular property. Update call to svn_wc__db_read_props_streamily(). * subversion/libsvn_wc/wc_db.c (svn_wc__db_read_props_streamily): Optionally list only a particular property. * subversion/libsvn_wc/wc_db.h (svn_wc__db_read_props_streamily): Optionally list only a particular property. Modified: subversion/trunk/subversion/include/private/svn_skel.h subversion/trunk/subversion/include/private/svn_wc_private.h subversion/trunk/subversion/libsvn_client/externals.c subversion/trunk/subversion/libsvn_client/prop_commands.c subversion/trunk/subversion/libsvn_subr/skel.c subversion/trunk/subversion/libsvn_wc/props.c subversion/trunk/subversion/libsvn_wc/wc_db.c subversion/trunk/subversion/libsvn_wc/wc_db.h Modified: subversion/trunk/subversion/include/private/svn_skel.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_skel.h?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/include/private/svn_skel.h (original) +++ subversion/trunk/subversion/include/private/svn_skel.h Fri Mar 18 01:46:39 2011 @@ -191,6 +191,14 @@ svn_skel__parse_proplist(apr_hash_t **pr const svn_skel_t *skel, apr_pool_t *result_pool); +/* Parse a `PROPLIST' SKEL looking for PROPNAME. If PROPNAME is found + then return its value in *PROVAL, allocated in RESULT_POOL. */ +svn_error_t * +svn_skel__parse_prop(svn_string_t **propval, + const svn_skel_t *skel, + const char *propname, + apr_pool_t *result_pool); + /* Unparse a PROPLIST hash (which has const char * property names and svn_stringbuf_t * values) into a `PROPLIST' skel *SKEL_P. Use POOL for all allocations. */ Modified: subversion/trunk/subversion/include/private/svn_wc_private.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/include/private/svn_wc_private.h (original) +++ subversion/trunk/subversion/include/private/svn_wc_private.h Fri Mar 18 01:46:39 2011 @@ -750,6 +750,8 @@ typedef svn_error_t *(*svn_wc__proplist_ * a hash table mapping <tt>char *</tt> names onto <tt>svn_string_t *</tt> * values for all the regular properties of the node at @a local_abspath * and any node beneath @a local_abspath within the specified @a depth. + * If @a propname is not NULL, the passed hash table will only contain + * the property @a propname. * * If @a pristine is @c TRUE, get the pristine (or "BASE") properties * from the working copy, instead of getting the current (or "WORKING") @@ -768,6 +770,7 @@ typedef svn_error_t *(*svn_wc__proplist_ svn_error_t * svn_wc__prop_list_recursive(svn_wc_context_t *wc_ctx, const char *local_abspath, + const char *propname, svn_depth_t depth, svn_boolean_t pristine, svn_wc__proplist_receiver_t receiver_func, Modified: subversion/trunk/subversion/libsvn_client/externals.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/externals.c (original) +++ subversion/trunk/subversion/libsvn_client/externals.c Fri Mar 18 01:46:39 2011 @@ -1428,7 +1428,7 @@ svn_client__crawl_for_externals(apr_hash { apr_hash_t *externals_hash = apr_hash_make(result_pool); - SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, depth, + SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL, depth, FALSE, /* pristine */ externals_crawl_proplist_receiver, externals_hash, Modified: subversion/trunk/subversion/libsvn_client/prop_commands.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/prop_commands.c?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/prop_commands.c (original) +++ subversion/trunk/subversion/libsvn_client/prop_commands.c Fri Mar 18 01:46:39 2011 @@ -653,70 +653,6 @@ pristine_or_working_propval(const svn_st return SVN_NO_ERROR; } - -/* A baton for propget_walk_cb. */ -struct propget_walk_baton -{ - const char *propname; /* The name of the property to get. */ - svn_boolean_t pristine; /* Select base rather than working props. */ - svn_wc_context_t *wc_ctx; /* Context for the tree being walked. */ - apr_hash_t *changelist_hash; /* Keys are changelists to filter on. */ - apr_hash_t *props; /* Out: mapping of (path:propval). */ - - /* Anchor, anchor_abspath pair for converting to relative paths */ - const char *anchor; - const char *anchor_abspath; -}; - -/* An entries-walk callback for svn_client_propget. - * - * For the path given by PATH and ENTRY, - * populate wb->PROPS with the values of property wb->PROPNAME, - * where "wb" is the WALK_BATON of type "struct propget_walk_baton *". - * If wb->PRISTINE is true, use the base value, else use the working value. - * - * The keys of wb->PROPS will be 'const char *' paths, rooted at the - * path wb->anchor, and the values are 'const svn_string_t *' property values. - */ -static svn_error_t * -propget_walk_cb(const char *local_abspath, - svn_node_kind_t kind, - void *walk_baton, - apr_pool_t *pool) -{ - struct propget_walk_baton *wb = walk_baton; - const svn_string_t *propval; - - /* If our entry doesn't pass changelist filtering, get outta here. */ - if (! svn_wc__changelist_match(wb->wc_ctx, local_abspath, - wb->changelist_hash, pool)) - return SVN_NO_ERROR; - - SVN_ERR(pristine_or_working_propval(&propval, wb->wc_ctx, local_abspath, - wb->propname, wb->pristine, - apr_hash_pool_get(wb->props), pool)); - - if (propval) - { - const char *path; - - if (wb->anchor && wb->anchor_abspath) - { - path = svn_dirent_join(wb->anchor, - svn_dirent_skip_ancestor(wb->anchor_abspath, - local_abspath), - apr_hash_pool_get(wb->props)); - } - else - path = apr_pstrdup(apr_hash_pool_get(wb->props), local_abspath); - - apr_hash_set(wb->props, path, APR_HASH_KEY_STRING, propval); - } - - return SVN_NO_ERROR; -} - - /* Helper for the remote case of svn_client_propget. * * Get the value of property PROPNAME in REVNUM, using RA_LIB and @@ -825,9 +761,61 @@ remote_propget(apr_hash_t *props, return SVN_NO_ERROR; } +/* Baton for recursive_propget_receiver(). */ +struct recursive_propget_receiver_baton +{ + apr_hash_t *props; /* Hash to collect props. */ + apr_pool_t *pool; /* Pool to allocate additions to PROPS. */ + apr_hash_t *changelist_hash; /* Keys are changelists to filter on. */ + svn_wc_context_t *wc_ctx; /* Working copy context. */ + + /* Anchor, anchor_abspath pair for converting to relative paths */ + const char *anchor; + const char *anchor_abspath; +}; + +/* An implementation of svn_wc__proplist_receiver_t. */ +static svn_error_t * +recursive_propget_receiver(void *baton, + const char *local_abspath, + apr_hash_t *props, + apr_pool_t *scratch_pool) +{ + struct recursive_propget_receiver_baton *b = baton; + const char *path; + + /* If the node doesn't pass changelist filtering, get outta here. */ + if (! svn_wc__changelist_match(b->wc_ctx, local_abspath, + b->changelist_hash, scratch_pool)) + return SVN_NO_ERROR; + + /* Attempt to convert absolute paths to relative paths for + * presentation purposes, if needed. */ + if (b->anchor && b->anchor_abspath) + { + path = svn_dirent_join(b->anchor, + svn_dirent_skip_ancestor(b->anchor_abspath, + local_abspath), + scratch_pool); + } + else + path = local_abspath; + + if (apr_hash_count(props)) + { + apr_hash_index_t *hi = apr_hash_first(scratch_pool, props); + apr_hash_set(b->props, apr_pstrdup(b->pool, path), + APR_HASH_KEY_STRING, + svn_string_dup(svn__apr_hash_index_val(hi), b->pool)); + } + + return SVN_NO_ERROR; +} + /* Return the property value for any PROPNAME set on TARGET in *PROPS, with WC paths of char * for keys and property values of - svn_string_t * for values. Assumes that PROPS is non-NULL. + svn_string_t * for values. Assumes that PROPS is non-NULL. Additions + to *PROPS are allocated in POOL. CHANGELISTS is an array of const char * changelist names, used as a restrictive filter on items whose properties are set; that is, @@ -849,9 +837,10 @@ get_prop_from_wc(apr_hash_t *props, apr_pool_t *pool) { apr_hash_t *changelist_hash = NULL; - struct propget_walk_baton wb; + struct recursive_propget_receiver_baton rb; const char *target_abspath; + SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, pool)); if (changelists && changelists->nelts) @@ -865,35 +854,47 @@ get_prop_from_wc(apr_hash_t *props, if (depth == svn_depth_unknown) depth = svn_depth_infinity; - if (strcmp(target_abspath, target) != 0) + rb.props = props; + rb.pool = pool; + rb.wc_ctx = ctx->wc_ctx; + rb.changelist_hash = changelist_hash; + + if (strcmp(target, target_abspath) != 0) { - wb.anchor = target; - wb.anchor_abspath = target_abspath; + rb.anchor = target; + rb.anchor_abspath = target_abspath; } else { - wb.anchor = NULL; - wb.anchor_abspath = NULL; + rb.anchor = NULL; + rb.anchor_abspath = NULL; } - wb.propname = propname; - wb.pristine = pristine; - wb.changelist_hash = changelist_hash; - wb.props = props; - wb.wc_ctx = ctx->wc_ctx; - /* Fetch the property, recursively or for a single resource. */ if (depth >= svn_depth_files && kind == svn_node_dir) { - SVN_ERR(svn_wc__node_walk_children(ctx->wc_ctx, target_abspath, FALSE, - propget_walk_cb, &wb, depth, - ctx->cancel_func, ctx->cancel_baton, - pool)); + SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, target_abspath, + propname, depth, pristine, + recursive_propget_receiver, &rb, + ctx->cancel_func, ctx->cancel_baton, + pool)); } else if (svn_wc__changelist_match(ctx->wc_ctx, target_abspath, changelist_hash, pool)) { - SVN_ERR(propget_walk_cb(target_abspath, kind, &wb, pool)); + const svn_string_t *propval; + + SVN_ERR(pristine_or_working_propval(&propval, ctx->wc_ctx, target_abspath, + propname, pristine, pool, pool)); + if (propval) + { + apr_hash_t *target_props = apr_hash_make(pool); + + apr_hash_set(target_props, target_abspath, APR_HASH_KEY_STRING, + propval); + SVN_ERR(recursive_propget_receiver(&rb, target_abspath, target_props, + pool)); + } } return SVN_NO_ERROR; @@ -1279,7 +1280,7 @@ svn_client_proplist3(const char *path_or rb.anchor_abspath = NULL; } - SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, + SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL, depth, pristine, recursive_proplist_receiver, &rb, ctx->cancel_func, Modified: subversion/trunk/subversion/libsvn_subr/skel.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/skel.c?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_subr/skel.c (original) +++ subversion/trunk/subversion/libsvn_subr/skel.c Fri Mar 18 01:46:39 2011 @@ -710,6 +710,39 @@ svn_skel__parse_proplist(apr_hash_t **pr svn_error_t * +svn_skel__parse_prop(svn_string_t **propval, + const svn_skel_t *skel, + const char *propname, + apr_pool_t *pool /* result_pool */) +{ + svn_skel_t *elt; + + *propval = NULL; + + /* Validate the skel. */ + if (! is_valid_proplist_skel(skel)) + return skel_err("proplist"); + + /* Look for PROPNAME in SKEL. */ + for (elt = skel->children; elt; elt = elt->next->next) + { + if (elt->len == strlen(propname) + && strncmp(propname, elt->data, elt->len) == 0) + { + *propval = svn_string_ncreate(elt->next->data, elt->next->len, + pool); + break; + } + else + { + continue; + } + } + return SVN_NO_ERROR; +} + + +svn_error_t * svn_skel__unparse_proplist(svn_skel_t **skel_p, apr_hash_t *proplist, apr_pool_t *pool) Modified: subversion/trunk/subversion/libsvn_wc/props.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/props.c (original) +++ subversion/trunk/subversion/libsvn_wc/props.c Fri Mar 18 01:46:39 2011 @@ -1671,6 +1671,7 @@ svn_wc_prop_list2(apr_hash_t **props, svn_error_t * svn_wc__prop_list_recursive(svn_wc_context_t *wc_ctx, const char *local_abspath, + const char *propname, svn_depth_t depth, svn_boolean_t pristine, svn_wc__proplist_receiver_t receiver_func, @@ -1702,7 +1703,7 @@ svn_wc__prop_list_recursive(svn_wc_conte case svn_depth_immediates: case svn_depth_infinity: SVN_ERR(svn_wc__db_read_props_streamily(wc_ctx->db, local_abspath, - depth, pristine, + propname, depth, pristine, receiver_func, receiver_baton, cancel_func, cancel_baton, scratch_pool)); Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Mar 18 01:46:39 2011 @@ -5453,6 +5453,7 @@ cache_props_recursive(void *cb_baton, svn_error_t * svn_wc__db_read_props_streamily(svn_wc__db_t *db, const char *local_abspath, + const char *propname, svn_depth_t depth, svn_boolean_t pristine, svn_wc__proplist_receiver_t receiver_func, @@ -5532,13 +5533,32 @@ svn_wc__db_read_props_streamily(svn_wc__ { const char *child_relpath; const char *child_abspath; - apr_hash_t *props; + apr_hash_t *props = NULL; child_relpath = svn_sqlite__column_text(stmt, 0, NULL); child_abspath = svn_dirent_join(wcroot->abspath, child_relpath, iterpool); - SVN_ERR(svn_skel__parse_proplist(&props, prop_skel, iterpool)); - if (receiver_func && apr_hash_count(props) != 0) + if (propname) + { + svn_string_t *propval; + + SVN_ERR(svn_skel__parse_prop(&propval, prop_skel, propname, + iterpool)); + if (propval) + { + props = apr_hash_make(iterpool); + apr_hash_set(props, propname, APR_HASH_KEY_STRING, + propval); + } + + } + else + { + SVN_ERR(svn_skel__parse_proplist(&props, prop_skel, + iterpool)); + } + + if (receiver_func && props && apr_hash_count(props) != 0) { SVN_ERR((*receiver_func)(receiver_baton, child_abspath, props, Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1082786&r1=1082785&r2=1082786&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db.h (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db.h Fri Mar 18 01:46:39 2011 @@ -1593,6 +1593,8 @@ svn_wc__db_read_props(apr_hash_t **props * a hash table mapping <tt>char *</tt> names onto svn_string_t * * values for any properties of child nodes of LOCAL_ABSPATH (up to DEPTH). * If PRISTINE is TRUE, read the pristine props (op_depth = 0). + * If PROPNAME is not NULL, the passed hash table will only contain + * the property PROPNAME. * * NOTE: The only valid values for DEPTH are svn_depth_files, * svn_depth_immediates, and svn_depth_infinity. @@ -1600,6 +1602,7 @@ svn_wc__db_read_props(apr_hash_t **props svn_error_t * svn_wc__db_read_props_streamily(svn_wc__db_t *db, const char *local_abspath, + const char *propname, svn_depth_t depth, svn_boolean_t pristine, svn_wc__proplist_receiver_t receiver_func,
