Author: stsp
Date: Thu Feb 17 17:27:53 2011
New Revision: 1071711

URL: http://svn.apache.org/viewvc?rev=1071711&view=rev
Log:
Make svn_client__crawl_for_externals() use the new recursive proplist
libsvn_wc API instead of a status crawl.

Apart from being faster, this will also make externals on locally added
directories show up. A future commit will make use of this capability to
address issue #2267, "support svn:externals on locally added directories".

The only existing caller of svn_client__crawl_for_externals() is
svn_client_relocate2(), which will now relocate existing relative
externals within locally added directories.

* subversion/libsvn_client/relocate.c
  (relocate_externals): Tolerate externals that are missing from disk
   even though they are listed in the externals definition.
   The external may have been removed accidentally, or the definition is
   set on a locally added directory. In the latter case there is currently
   no way to make the external appear, so erroring out is unfriendly.

* subversion/libsvn_client/externals.c
  (): Include svn_props.h.
  (externals_update_func, status_noop_func): Remove.
  (externals_crawl_proplist_receiver): New. Replaces the above two functions,
   and is used with svn_wc__prop_list_recursive().
  (svn_client__crawl_for_externals): Use svn_wc__prop_list_recursive()
   instead of svn_wc_walk_status() to gather externals.

Modified:
    subversion/trunk/subversion/libsvn_client/externals.c
    subversion/trunk/subversion/libsvn_client/relocate.c

Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1071711&r1=1071710&r2=1071711&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Thu Feb 17 17:27:53 
2011
@@ -36,6 +36,7 @@
 #include "svn_error.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
+#include "svn_props.h"
 #include "svn_config.h"
 #include "client.h"
 
@@ -1424,33 +1425,36 @@ svn_client__external_info_gatherer(void 
 }
 
 
-/* Callback of type svn_wc_external_update_t.  Just squirrels away an
+/* An implementation of svn_wc__proplist_receiver_t. Just squirrels away an
    svn:externals property value into BATON (which is an apr_hash_t *
    keyed on local absolute path).  */
 static svn_error_t *
-externals_update_func(void *baton,
-                      const char *local_abspath,
-                      const svn_string_t *old_val,
-                      const svn_string_t *new_val,
-                      svn_depth_t depth,
-                      apr_pool_t *scratch_pool)
+externals_crawl_proplist_receiver(void *baton,
+                                  const char *local_abspath,
+                                  apr_hash_t *props,
+                                  apr_pool_t *scratch_pool)
 {
-  apr_hash_t *externals_hash = baton;
-  apr_pool_t *hash_pool = apr_hash_pool_get(externals_hash);
+  apr_hash_index_t *hi;
+  apr_hash_t *externals_hash = (apr_hash_t*)baton;
 
-  apr_hash_set(externals_hash, apr_pstrdup(hash_pool, local_abspath),
-               APR_HASH_KEY_STRING, svn_string_dup(new_val, hash_pool));
-  return SVN_NO_ERROR;
-}
+  for (hi = apr_hash_first(scratch_pool, props);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *propname;
 
+      propname = svn__apr_hash_index_key(hi);
+      if (strcmp(propname, SVN_PROP_EXTERNALS) == 0)
+        {
+          apr_pool_t *hash_pool = apr_hash_pool_get(externals_hash);
+          svn_string_t *propval = svn__apr_hash_index_val(hi);
+
+          apr_hash_set(externals_hash, apr_pstrdup(hash_pool, local_abspath),
+                       APR_HASH_KEY_STRING, svn_string_dup(propval, 
hash_pool));
+          break;
+        }
+    }
 
-/* Callback of type svn_wc_status_func4_t.  Does nothing. */
-static svn_error_t *
-status_noop_func(void *baton,
-                 const char *local_abspath,
-                 const svn_wc_status3_t *status,
-                 apr_pool_t *scratch_pool)
-{
   return SVN_NO_ERROR;
 }
 
@@ -1465,12 +1469,12 @@ svn_client__crawl_for_externals(apr_hash
 {
   apr_hash_t *externals_hash = apr_hash_make(result_pool);
 
-  /* Do a status run just to harvest externals definitions. */
-  SVN_ERR(svn_wc_walk_status(ctx->wc_ctx, local_abspath, depth,
-                             FALSE, FALSE, NULL, status_noop_func, NULL,
-                             externals_update_func, externals_hash,
-                             ctx->cancel_func, ctx->cancel_baton,
-                             scratch_pool));
+  SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, depth,
+                                      externals_crawl_proplist_receiver,
+                                      externals_hash,
+                                      ctx->cancel_func,
+                                      ctx->cancel_baton,
+                                      scratch_pool));
 
   *externals_p = externals_hash;
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_client/relocate.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/relocate.c?rev=1071711&r1=1071710&r2=1071711&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/relocate.c (original)
+++ subversion/trunk/subversion/libsvn_client/relocate.c Thu Feb 17 17:27:53 
2011
@@ -157,6 +157,7 @@ relocate_externals(const char *local_abs
         APR_ARRAY_IDX(ext_desc, i, svn_wc_external_item2_t *);
       const char *target_repos_root_url;
       const char *target_abspath;
+      svn_error_t *err;
 
       svn_pool_clear(iterpool);
 
@@ -181,8 +182,19 @@ relocate_externals(const char *local_abs
                                                       ext_item->target_dir,
                                                       iterpool),
                                       iterpool));
-      SVN_ERR(svn_client_root_url_from_path(&target_repos_root_url,
-                                            target_abspath, ctx, iterpool));
+      err = svn_client_root_url_from_path(&target_repos_root_url,
+                                          target_abspath, ctx, iterpool);
+
+      /* Ignore externals that aren't present in the working copy.
+       * This can happen if an external is deleted from disk accidentally,
+       * or if an external is configured on a locally added directory. */
+      if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+        {
+          svn_error_clear(err);
+          continue;
+        }
+      else
+        SVN_ERR(err);
 
       if (strcmp(target_repos_root_url, old_parent_repos_root_url) == 0)
         SVN_ERR(svn_client_relocate2(target_abspath,


Reply via email to