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,


Reply via email to