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,