Author: stsp
Date: Thu Feb 17 18:28:20 2011
New Revision: 1071739
URL: http://svn.apache.org/viewvc?rev=1071739&view=rev
Log:
As part of issue #2267, "support svn:externals on locally added directories",
allow 'svn update' to populate externals within locally added directories.
This fix avoids modifying the crawling code shared between several
commands (status, update, switch), a concern that caused a previous
attempt at fixing this issue to be backed out (r946661).
* subversion/libsvn_client/update.c
(gather_externals_in_locally_added_dirs): New helper function.
(update_internal): Use the new helper function to gather externals
which weren't already picked up during the base tree crawl.
Modified:
subversion/trunk/subversion/libsvn_client/update.c
Modified: subversion/trunk/subversion/libsvn_client/update.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1071739&r1=1071738&r2=1071739&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Thu Feb 17 18:28:20 2011
@@ -44,6 +44,58 @@
/*** Code. ***/
+/* Helper function to fix issue #2267,
+ * "support svn:externals on locally added directories".
+ *
+ * Crawl all externals beneath ANCHOR_ABSPATH (this is cheap because we're
+ * only crawling the WC DB itself). If there are externals within the
+ * REQUESTED_DEPTH that weren't already picked up while we were crawling
+ * the BASE tree, add them to the EXTERNALS_NEW hash with ambient depth
+ * infinity. Facilitates populating externals in locally added directories.
+ *
+ * ### This is a bit of a hack. We should try to find a better solution
+ * ### to this problem. */
+static svn_error_t *
+gather_externals_in_locally_added_dirs(apr_hash_t *externals_new,
+ apr_hash_t *ambient_depths,
+ const char *anchor_abspath,
+ svn_depth_t requested_depth,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_t *all_externals;
+ apr_hash_index_t *hi;
+
+ /* If there was no requested depth for this operation, use infinity.
+ * svn_client__crawl_for_externals() doesn't like depth 'unknown'. */
+ if (requested_depth == svn_depth_unknown)
+ requested_depth = svn_depth_infinity;
+
+ SVN_ERR(svn_client__crawl_for_externals(&all_externals, anchor_abspath,
+ requested_depth, ctx, scratch_pool,
+ scratch_pool));
+
+ for (hi = apr_hash_first(scratch_pool, all_externals);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *local_abspath = svn__apr_hash_index_key(hi);
+
+ if (! apr_hash_get(externals_new, local_abspath, APR_HASH_KEY_STRING))
+ {
+ apr_pool_t *hash_pool = apr_hash_pool_get(externals_new);
+ svn_string_t *propval = svn__apr_hash_index_val(hi);
+
+ apr_hash_set(externals_new, local_abspath, APR_HASH_KEY_STRING,
+ apr_pstrdup(hash_pool, propval->data));
+ apr_hash_set(ambient_depths, local_abspath, APR_HASH_KEY_STRING,
+ svn_depth_to_word(svn_depth_infinity));
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* This is a helper for svn_client__update_internal(), which see for
an explanation of most of these parameters. Some stuff that's
unique is as follows:
@@ -250,6 +302,10 @@ update_internal(svn_revnum_t *result_rev
the primary operation. */
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
{
+ SVN_ERR(gather_externals_in_locally_added_dirs(efb.externals_new,
+ efb.ambient_depths,
+ anchor_abspath,
+ depth, ctx, pool));
SVN_ERR(svn_client__handle_externals(efb.externals_old,
efb.externals_new,
efb.ambient_depths,