Author: dannas
Date: Sun Mar  7 21:21:58 2010
New Revision: 920118

URL: http://svn.apache.org/viewvc?rev=920118&view=rev
Log:
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.

* subversion/tests/cmdline/upgrade_tests.py
  (upgrade_with_externals): New. Checks the format of a 1.6 wc upgraded
    to wc-ng.
  (test_list): Add upgrade with_externals.

* subversion/tests/cmdline/upgrade_tests_data/upgrade_with_extenals.tar.bz2
  (...): New. An 1.6 wc with the same structure as those used in
    externals_tests.py.

Approved by: rhuijben

Added:
    
subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/upgrade_with_externals.tar.bz2
   (with props)
Modified:
    subversion/trunk/subversion/libsvn_client/cleanup.c
    subversion/trunk/subversion/tests/cmdline/upgrade_tests.py

Modified: subversion/trunk/subversion/libsvn_client/cleanup.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/cleanup.c?rev=920118&r1=920117&r2=920118&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/cleanup.c (original)
+++ subversion/trunk/subversion/libsvn_client/cleanup.c Sun Mar  7 21:21:58 2010
@@ -34,8 +34,11 @@
 #include "svn_dirent_uri.h"
 #include "svn_pools.h"
 #include "client.h"
+#include "svn_pools.h"
+#include "svn_props.h"
 
 #include "svn_private_config.h"
+#include "private/svn_wc_private.h"
 
 
 /*** Code. ***/
@@ -110,6 +113,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}};
   struct repos_info_baton info_baton;
   info_baton.pool = scratch_pool;
   info_baton.ctx = ctx;
@@ -123,5 +130,79 @@
                          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 char *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, (void*)&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;
+          const char *external_path;
+          svn_node_kind_t kind;
+          svn_error_t *err;
+
+          item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
+
+          /* The key is the path to the dir the svn:externals was set on */
+          external_path = svn_dirent_join(key, item->target_dir, iterpool);
+
+          SVN_ERR(svn_dirent_get_absolute(&external_abspath, external_path,
+                                          iterpool));
+
+          /* This is hack. We can only send dirs to svn_wc_upgrade(). This
+             way we will get an exception saying that the wc must be
+             upgraded if it's a dir. If it's a file then the lookup is done
+             in an adm_dir belonging to the real wc and since that was
+             updated before the externals no error is returned. */
+          err = svn_wc__node_get_kind(&kind, ctx->wc_ctx, external_abspath,
+                                        FALSE, iterpool);
+
+          if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+            {
+              SVN_ERR(svn_wc_upgrade(ctx->wc_ctx, external_abspath,
+                                     fetch_repos_info, &info_baton,
+                                     ctx->cancel_func, ctx->cancel_baton,
+                                     ctx->notify_func2, ctx->notify_baton2,
+                                     iterpool));
+              svn_error_clear(err);
+            }
+          else if (err)
+            return svn_error_return(err);
+          else
+            ;
+        }
+    }
+
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/tests/cmdline/upgrade_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/upgrade_tests.py?rev=920118&r1=920117&r2=920118&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/upgrade_tests.py Sun Mar  7 
21:21:58 2010
@@ -141,6 +141,23 @@
   expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
   run_and_verify_status_no_server(sbox.wc_dir, expected_status)
 
+def upgrade_with_externals(sbox):
+  "upgrade with externals"
+  
+  # Create wc from tarfile, uses the same structure of the wc as the tests
+  # in externals_tests.py.
+  replace_sbox_with_tarfile(sbox, 'upgrade_with_externals.tar.bz2')
+
+  # Attempt to use the working copy, this should give an error
+  expected_stderr = wc_is_too_old_regex
+  svntest.actions.run_and_verify_svn(None, None, expected_stderr,
+                                     'info', sbox.wc_dir)
+  # Now upgrade the working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'upgrade', sbox.wc_dir)
+
+  # Actually check the format number of the upgraded working copy
+  check_format(sbox, get_current_format())
 
 def upgrade_1_5_body(sbox, subcommand):
   replace_sbox_with_tarfile(sbox, 'upgrade_1_5.tar.bz2')
@@ -328,6 +345,7 @@
 # list all tests here, starting with None:
 test_list = [ None,
               basic_upgrade,
+              upgrade_with_externals,
               upgrade_1_5,
               update_1_5,
               logs_left_1_5,

Added: 
subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/upgrade_with_externals.tar.bz2
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/upgrade_with_externals.tar.bz2?rev=920118&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/upgrade_with_externals.tar.bz2
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream


Reply via email to