Hi!

[[[
Fix issue #3483 - extend svn_client_upgrade() to include externals. I've
done the externals upgrading after wc upgrade is finished. In that way
no errors in the externals will affect the wc.

* subversion/libsvn_client/cleanup.c
  (svn_client_upgrade): Get all svn:externals. We need the target_dir so
    we have to parse the description. For each target_dir we call
    svn_wc_upgrade() which will recursively upgrade the external.

Patch by: Daniel Näslund <daniel{_AT_}longitudo.com>
]]]

I have only tested this patch with the supplied shell script. 

As for performance. Bert told me today on IRC that we will gain more
speed once the property stuff is in the db. We walk the wc two
times, one for the original wc upgrade and another when searching for
externals definitions. Hopefully, caching will ease the burden.

I have one formatting issue with the svn_dirent_dirname(). If anyone has
a better suggestion I'm upen for discussion (That is, I will do whatever
you tell me to do).

Daniel
Index: subversion/libsvn_client/cleanup.c
===================================================================
--- subversion/libsvn_client/cleanup.c	(revision 894131)
+++ subversion/libsvn_client/cleanup.c	(arbetskopia)
@@ -33,6 +33,8 @@
 #include "svn_config.h"
 #include "svn_dirent_uri.h"
 #include "client.h"
+#include "svn_pools.h"
+#include "svn_props.h"
 
 #include "svn_private_config.h"
 
@@ -62,6 +64,10 @@
                    apr_pool_t *scratch_pool)
 {
   const char *local_abspath;
+  apr_hash_t *externals;
+  apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
+  svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
   SVN_ERR(svn_wc_upgrade(ctx->wc_ctx, local_abspath,
@@ -69,5 +75,56 @@
                          ctx->notify_func2, ctx->notify_baton2,
                          scratch_pool));
 
+  /* Now it's time to upgrade the externals too. We do it after the wc 
+     upgrade to avoid that errors in the externals causes the wc upgrade to
+     fail. Thanks to caching the performance penalty of walking the wc a 
+     second time shouldn't be too severe */
+  SVN_ERR(svn_client_propget3(&externals, SVN_PROP_EXTERNALS, path, &rev, 
+                              &rev, NULL, svn_depth_infinity, NULL, ctx, 
+                              scratch_pool));
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  for (hi = apr_hash_first(scratch_pool, externals); hi; 
+       hi = apr_hash_next(hi))
+    {
+      const void *key;
+      int i;
+      apr_ssize_t klen;
+      svn_string_t *external_desc;
+      apr_array_header_t *externals_p;
+      
+      svn_pool_clear(iterpool);
+      externals_p = apr_array_make(iterpool, 1,
+                                   sizeof(svn_wc_external_item2_t*));
+
+      apr_hash_this(hi, &key, &klen, NULL);
+
+      external_desc = apr_hash_get(externals, key, klen);
+
+      SVN_ERR(svn_wc_parse_externals_description3(&externals_p, 
+                                            svn_dirent_dirname(path, 
+                                                               iterpool),
+                                                  external_desc->data, TRUE,
+                                                  iterpool));
+      for (i = 0; i < externals_p->nelts; i++)
+        {
+          svn_wc_external_item2_t *item;
+          const char *external_abspath;
+
+          item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
+
+          SVN_ERR(svn_dirent_get_absolute(&external_abspath, item->target_dir,
+                                          iterpool));
+
+          SVN_ERR(svn_wc_upgrade(ctx->wc_ctx, external_abspath,
+                                 ctx->cancel_func, ctx->cancel_baton,
+                                 ctx->notify_func2, ctx->notify_baton2,
+                                 iterpool));
+        }
+    }
+
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }

Reply via email to