On Fri, Feb 17, 2012 at 12:46 PM, Nico Kadel-Garcia <nka...@gmail.com> wrote: > On Fri, Feb 17, 2012 at 10:54 AM, Philip Martin > <philip.mar...@wandisco.com> wrote: >> Paul Burba <ptbu...@gmail.com> writes: >> >>> I'm able to replicate this failure on my Windows box with my own >>> builds of trunk@1245285, 1.7.0 and 1.7.3. Alexey's script works as >>> expected with 1.6.17, so this appears to be a regression. Moving back >>> to the dev list. >>> >>> Investigating... >> >>>> svn: E720005: Can't move 'C:\t\wc\.svn\tmp\svn-8ED6923C' to >>>> 'C:\t\wc\externals-container-copy': Access is denied. >> >> I suspect this is a directory move. Perhaps the wc.db file of the >> external is still open? Can a directory be renamed on Windows when one >> of the files inside it is still open? > > Not in my experience.
I added an issue for this: http://subversion.tigris.org/issues/show_bug.cgi?id=4123 and a test also: http://svn.apache.org/viewvc?view=revision&revision=1292090 The attached patch fixes this problem on Windows. Could any wc-ng gurus take a look and see if this seems reasonable? [[[ Fix issue #4123 'URL-to-WC copy of externals fails on Windows'. * subversion/include/private/svn_wc_private.h (svn_wc__externals_close): New declaration. * subversion/libsvn_wc/externals.c (svn_wc__externals_close): New definition. * subversion/libsvn_client/copy.c (repos_to_wc_copy_single): Use new function to close handles to externals' DB files before trying to rename the whole temp WC. * subversion/tests/cmdline/externals_tests.py (url_to_wc_copy_of_externals): Remove XFail decorator and update comments re failure status. ]]] Even with this fix I'm still seeing odd behavior post-copy (the following example uses a WC-to-WC copy, but the same problem occurs with a URL-to-WC copy): ### We have a working copy at a uniform revision with an external: >svn up -q >svn st X A\C\external Performing status on external item at 'A\C\external': >svn pl -vR Properties on 'A\C': svn:externals ^/A/D/G external ### We copy the directory with the external definition: >svn copy A/C WC-to-WC-Copy-of-C A WC-to-WC-Copy-of-C ### But the external shows up as unversioned: >svn st X A\C\external A + WC-to-WC-Copy-of-C ? WC-to-WC-Copy-of-C\external Performing status on external item at 'WC-to-WC-Copy-of-C\external': Performing status on external item at 'A\C\external': ### Even if we commit an update the WC we see the same problem: >svn ci -m "" Adding WC-to-WC-Copy-of-C Committed revision 3. >svn up Updating '.': Fetching external item into 'WC-to-WC-Copy-of-C\external': External at revision 3. Fetching external item into 'A\C\external': External at revision 3. At revision 3. >svn st X A\C\external ? WC-to-WC-Copy-of-C\external Performing status on external item at 'WC-to-WC-Copy-of-C\external': Performing status on external item at 'A\C\external': > To fix this we need to remove the external via the OS then update to restore it (note that this problem occurs without my patch applied, so this is a separate issue). Paul
Index: subversion/include/private/svn_wc_private.h =================================================================== --- subversion/include/private/svn_wc_private.h (revision 1292379) +++ subversion/include/private/svn_wc_private.h (working copy) @@ -263,6 +263,15 @@ apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/* Close the DBs for any externals under LOCAL_ABSPATH. Detection of + externals is as per svn_wc__externals_gather_definitions. + + Perform temporary allocations in SCRATCH_POOL. */ +svn_error_t * +svn_wc__externals_close(const char *local_abspath, + svn_wc_context_t *wc_ctx, + apr_pool_t *scratch_pool); + /** Set @a *tree_conflict to a newly allocated @c * svn_wc_conflict_description_t structure describing the tree * conflict state of @a victim_abspath, or to @c NULL if @a victim_abspath Index: subversion/libsvn_client/copy.c =================================================================== --- subversion/libsvn_client/copy.c (revision 1292379) +++ subversion/libsvn_client/copy.c (working copy) @@ -1519,6 +1519,17 @@ ctx->notify_baton2 = old_notify_baton2; SVN_ERR(err); + +#ifdef WIN32 + if (!ignore_externals) + { + /* Issue #4123: We may still hold file handles to the databases + for externals under TMP_ABSPATH. We need to release these + handles before we move TMP_ABSPATH below or Windows will + raise an ERROR_ACCESS_DENIED error. */ + SVN_ERR(svn_wc__externals_close(tmp_abspath, ctx->wc_ctx, pool)); + } +#endif } /* Schedule dst_path for addition in parent, with copy history. Index: subversion/libsvn_wc/externals.c =================================================================== --- subversion/libsvn_wc/externals.c (revision 1292379) +++ subversion/libsvn_wc/externals.c (working copy) @@ -1363,6 +1363,56 @@ } } +svn_error_t * +svn_wc__externals_close(const char *local_abspath, + svn_wc_context_t *wc_ctx, + apr_pool_t *scratch_pool) +{ + apr_hash_t *externals; + apr_hash_index_t *hi; + apr_pool_t *iterpool; + + SVN_ERR(svn_wc__externals_gather_definitions(&externals, NULL, wc_ctx, + local_abspath, + svn_depth_infinity, + scratch_pool, scratch_pool)); + + if (!apr_hash_count(externals)) + return SVN_NO_ERROR; + + iterpool = svn_pool_create(scratch_pool); + + for (hi = apr_hash_first(scratch_pool, externals); + hi; + hi = apr_hash_next(hi)) + { + const char *this_abspath = svn__apr_hash_index_key(hi); + const char *external_value = svn__apr_hash_index_val(hi); + apr_array_header_t *ext_desc; + int i; + + SVN_ERR(svn_wc_parse_externals_description3(&ext_desc, this_abspath, + external_value, FALSE, + iterpool)); + for (i = 0; i < ext_desc->nelts; i++) + { + svn_wc_external_item2_t *ext_item = + APR_ARRAY_IDX(ext_desc, i, svn_wc_external_item2_t *); + const char *external_abspath; + + SVN_ERR(svn_dirent_get_absolute(&external_abspath, + svn_dirent_join(this_abspath, + ext_item->target_dir, + iterpool), + iterpool)); + SVN_ERR(svn_wc__db_drop_root(wc_ctx->db, external_abspath, + iterpool)); + } + } + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; +} + /* Return the scheme of @a uri in @a scheme allocated from @a pool. If @a uri does not appear to be a valid URI, then @a scheme will not be updated. */ Index: subversion/tests/cmdline/externals_tests.py =================================================================== --- subversion/tests/cmdline/externals_tests.py (revision 1292379) +++ subversion/tests/cmdline/externals_tests.py (working copy) @@ -2787,7 +2787,6 @@ # Test for issue #4123 'URL-to-WC copy of externals fails on Windows' @Issue(4123) -@XFail(svntest.main.is_os_windows) def url_to_wc_copy_of_externals(sbox): "url-to-wc copy of externals" @@ -2805,7 +2804,8 @@ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir) # Copy ^/A/C to External-WC-to-URL-Copy. - # Currently this fails with: + # + # Previously this failed with: # >svn copy ^^/A/C External-WC-to-URL-Copy # U External-WC-to-URL-Copy #