Ping! This patch has not been reviewed the last 8 days. On Tue, Dec 29, 2009 at 07:44:49PM +0100, Daniel Näslund wrote: > 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. > > * 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. > > Patch by: Daniel Näslund <daniel{_AT_}longitudo.com> > ]]] > > A big thank you to Bert for putting up with all my questions on IRC. > > My previous patch didn't handle relative externals all that well. And it > failed to upgrade file externals too. I've added a testcase to this > patch to prove that this one does things right. > > BUT, the testcase does not check the statustree of the wc after the > upgrade. I didn't understand how to set up a statustree to check > against. > > Daniel
> Index: subversion/tests/cmdline/upgrade_tests.py > =================================================================== > --- subversion/tests/cmdline/upgrade_tests.py (revision 894319) > +++ subversion/tests/cmdline/upgrade_tests.py (arbetskopia) > @@ -139,7 +139,24 @@ > 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') > > @@ -216,6 +233,7 @@ > # list all tests here, starting with None: > test_list = [ None, > basic_upgrade, > + upgrade_with_externals, > upgrade_1_5, > XFail(update_1_5), > logs_left_1_5, > Index: > subversion/tests/cmdline/upgrade_tests_data/upgrade_with_externals.tar.bz2 > =================================================================== > Kan inte visa: filen markerad som binär. > svn:mime-type = application/octet-stream > > Egenskapsändringar för: > subversion/tests/cmdline/upgrade_tests_data/upgrade_with_externals.tar.bz2 > ___________________________________________________________________ > Added: svn:mime-type > + application/octet-stream > > Index: subversion/libsvn_client/cleanup.c > =================================================================== > --- subversion/libsvn_client/cleanup.c (revision 894319) > +++ subversion/libsvn_client/cleanup.c (arbetskopia) > @@ -33,8 +33,11 @@ > #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" > +#include "private/svn_wc_private.h" > > > /*** Code. ***/ > @@ -62,6 +65,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 +76,78 @@ > 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, > + 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; > }