On Fri, Feb 17, 2012 at 12:46 PM, Nico Kadel-Garcia <[email protected]> wrote:
> On Fri, Feb 17, 2012 at 10:54 AM, Philip Martin
> <[email protected]> wrote:
>> Paul Burba <[email protected]> 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
#