Author: rhuijben
Date: Tue Jul 5 14:17:22 2011
New Revision: 1143071
URL: http://svn.apache.org/viewvc?rev=1143071&view=rev
Log:
Make svn update handle some access denied scenarios with a proper skip. This
makes it less likely that the database will be closed after updating with
working queue items left.
*
subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
(Action): Add new value
* subversion/include/svn_error_codes.h
(SVN_ERR_WC_PATH_ACCESS_DENIED): New error code.
* subversion/include/svn_wc.h
(svn_wc_notify_action_t): Add new value.
* subversion/libsvn_wc/questions.c
(svn_wc__internal_file_modified_p): Wrap EACCESS errors with
SVN_ERR_WC_PATH_ACCESS_DENIED to allow callers to check for this condition
versus any access denied.
* subversion/libsvn_wc/status.c
(assemble_status): Handle the new error code instead of all access denied
errors.
* subversion/libsvn_wc/update_editor.c
(close_file): Handle the access denied error with a proper skip. Call the
notification handler.
* subversion/svn/notify.c
(notify): Handle the new skip action.
* subversion/tests/cmdline/update_tests.py
(skip_access_denied): New windows-only test that tests access denied in
update and status.
(test_list): Add skip_access_denied.
Modified:
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
subversion/trunk/subversion/include/svn_error_codes.h
subversion/trunk/subversion/include/svn_wc.h
subversion/trunk/subversion/libsvn_wc/questions.c
subversion/trunk/subversion/libsvn_wc/status.c
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/svn/notify.c
subversion/trunk/subversion/tests/cmdline/update_tests.py
Modified:
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
---
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
(original)
+++
subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
Tue Jul 5 14:17:22 2011
@@ -468,6 +468,9 @@ public class ClientNotifyInformation ext
/** Skipping a working only node */
update_skip_working_only ("update skip working only"),
+ /** Skipped a file or directory to which access couldn't be obtained */
+ update_skip_access_denied ("update skip access denied"),
+
/** An update operation removed an external working copy. */
update_external_removed ("update external removed"),
Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Tue Jul 5 14:17:22
2011
@@ -530,6 +530,11 @@ SVN_ERROR_START
SVN_ERR_WC_CATEGORY_START + 38,
"This operation can not be performed with just this depth.")
+ /** @since New in 1.7. */
+ SVN_ERRDEF(SVN_ERR_WC_PATH_ACCESS_DENIED,
+ SVN_ERR_WC_CATEGORY_START + 39,
+ "Couldn't open a working copy file because access was denied")
+
/* fs errors */
SVN_ERRDEF(SVN_ERR_FS_GENERAL,
Modified: subversion/trunk/subversion/include/svn_wc.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Tue Jul 5 14:17:22 2011
@@ -1107,6 +1107,10 @@ typedef enum svn_wc_notify_action_t
* @since New in 1.7. */
svn_wc_notify_update_skip_working_only,
+ /** An update tried to update a file or directory to which access could
+ * not be obtained. @since New in 1.7. */
+ svn_wc_notify_update_skip_access_denied,
+
/** An update operation removed an external working copy.
* @since New in 1.7. */
svn_wc_notify_update_external_removed,
Modified: subversion/trunk/subversion/libsvn_wc/questions.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/questions.c?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/questions.c (original)
+++ subversion/trunk/subversion/libsvn_wc/questions.c Tue Jul 5 14:17:22 2011
@@ -335,12 +335,22 @@ svn_wc__internal_file_modified_p(svn_boo
scratch_pool, scratch_pool));
/* Check all bytes, and verify checksum if requested. */
- SVN_ERR(compare_and_verify(modified_p, db,
+ {
+ svn_error_t *err;
+ err = compare_and_verify(modified_p, db,
local_abspath, dirent->filesize,
pristine_stream, pristine_size,
has_props, props_mod,
exact_comparison,
- scratch_pool));
+ scratch_pool);
+
+ /* At this point we already opened the pristine file, so we know that
+ the access denied applies to the working copy path */
+ if (err && APR_STATUS_IS_EACCES(err->apr_err))
+ return svn_error_create(SVN_ERR_WC_PATH_ACCESS_DENIED, err, NULL);
+ else
+ SVN_ERR(err);
+ }
if (!*modified_p)
{
Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Tue Jul 5 14:17:22 2011
@@ -537,7 +537,7 @@ assemble_status(svn_wc_status3_t **statu
if (err)
{
- if (!APR_STATUS_IS_EACCES(err->apr_err))
+ if (err->apr_err != SVN_ERR_WC_PATH_ACCESS_DENIED)
return svn_error_trace(err);
/* An access denied is very common on Windows when another
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Tue Jul 5 14:17:22
2011
@@ -4114,9 +4114,37 @@ close_file(void *file_baton,
/* Merge the text. This will queue some additional work. */
if (!fb->obstruction_found)
{
- SVN_ERR(merge_file(&work_item, &install_pristine, &install_from,
- &content_state, fb, current_actual_props,
- fb->changed_date, scratch_pool, scratch_pool));
+ svn_error_t *err;
+ err = merge_file(&work_item, &install_pristine, &install_from,
+ &content_state, fb, current_actual_props,
+ fb->changed_date, scratch_pool, scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_ACCESS_DENIED)
+ {
+ if (eb->notify_func)
+ {
+ svn_wc_notify_t *notify =svn_wc_create_notify(
+ fb->local_abspath,
+ svn_wc_notify_update_skip_access_denied,
+ scratch_pool);
+
+ notify->kind = svn_node_file;
+ notify->err = err;
+
+ eb->notify_func(eb->notify_baton, notify, scratch_pool);
+ }
+ svn_error_clear(err);
+
+ SVN_ERR(remember_skipped_tree(eb, fb->local_abspath,
+ scratch_pool));
+ fb->skip_this = TRUE;
+
+ SVN_ERR(maybe_release_dir_info(fb->bump_info));
+ svn_pool_destroy(fb->pool);
+ return SVN_NO_ERROR;
+ }
+ else
+ SVN_ERR(err);
all_work_items = svn_wc__wq_merge(all_work_items, work_item,
scratch_pool);
Modified: subversion/trunk/subversion/svn/notify.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/notify.c?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/notify.c (original)
+++ subversion/trunk/subversion/svn/notify.c Tue Jul 5 14:17:22 2011
@@ -162,6 +162,13 @@ notify(void *baton, const svn_wc_notify_
path_local)))
goto print_error;
break;
+ case svn_wc_notify_update_skip_access_denied:
+ nb->skipped_paths++;
+ if ((err = svn_cmdline_printf(
+ pool, _("Skipped '%s' -- Access denied\n"),
+ path_local)))
+ goto print_error;
+ break;
case svn_wc_notify_update_delete:
case svn_wc_notify_exclude:
nb->received_some_change = TRUE;
Modified: subversion/trunk/subversion/tests/cmdline/update_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/update_tests.py?rev=1143071&r1=1143070&r2=1143071&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/update_tests.py Tue Jul 5
14:17:22 2011
@@ -5342,6 +5342,57 @@ def revive_children_of_copy(sbox):
if not os.path.exists(psi2_path):
raise svntest.Failure('psi unexpectedly non-existent')
+@SkipUnless(svntest.main.is_os_windows)
+def skip_access_denied(sbox):
+ """access denied paths should be skipped"""
+
+ # We need something to lock the file. 'msvcrt' looks common on Windows
+ try:
+ import msvcrt
+ except ImportError:
+ raise svntest.Skip
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ iota = sbox.ospath('iota')
+
+ svntest.main.file_write(iota, 'Q')
+ sbox.simple_commit()
+ sbox.simple_update() # Update to r2
+
+ # Open iota for writing to keep an handle open
+ f = open(iota, 'w')
+
+ # Write new text of exactly the same size to avoid the early out
+ # on a different size without properties.
+ f.write('R')
+ f.flush()
+
+ # And lock the first byte of the file
+ msvcrt.locking(f.fileno(), 1, 1)
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(verb='Skipped'),
+ })
+
+ # Create expected status tree: iota isn't updated
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('iota', status='M ', wc_rev=2)
+
+ # And now check that update skips the path
+ # *and* status shows the path as modified.
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output,
+ None,
+ expected_status,
+ None,
+ None, None,
+ None, None, None, wc_dir, '-r', '1')
+
+ f.close()
+
+
#######################################################################
# Run the tests
@@ -5407,6 +5458,7 @@ test_list = [ None,
update_with_file_lock_and_keywords_property_set,
update_nonexistent_child_of_copy,
revive_children_of_copy,
+ skip_access_denied,
]
if __name__ == '__main__':