The attached patch attempts to improve our 'sleep for timestamps' coverage,
especially in error conditions where the WC has already been changed and so we
should sleep as well as returning an error. I just happened to notice that we
currently miss several such cases.
The are several TODO notes in the log message. Before I go any further with
this, can anybody check I'm on the right track?
For easier reference, I'll repeat the log message here:
[[[
Fix some sleep-for-timestamps code: avoid missing some cases where we need
to sleep. Simplify by localizing the handling.
TODO: Similarly fix and simplify the rest of the sleep_for_timestamps calls
in libsvn_client, which are in commit, copy, and merge.
TODO: Decide whether 'sleep' should be called before or after releasing
the WC write lock, and fix where necessary to be consistent.
TODO: In revert, only sleep if we actually revert something.
TODO: In checkout (with --force), only sleep if we actually update something.
TODO: Audit all other uses of 'goto' in Subversion for cases where we use
'if (err) goto ...' on some lines but accidentally use 'SVN_ERR' on others.
* subversion/libsvn_client/client.h
(svn_client__update_internal,
svn_client__checkout_internal,
svn_client__switch_internal,
svn_client__handle_externals): Document that the 'sleep' output is set
even if the function returns an error, and don't let it be NULL.
(svn_client__export_externals): Remove the unused and unneeded 'sleep'
output parameter.
* subversion/libsvn_client/export.c
(export_directory): Remove the unneeded 'sleep' variable.
* subversion/libsvn_client/externals.c
(svn_client__export_externals): Remove the unused and unneeded 'sleep'
output parameter.
* subversion/libsvn_client/checkout.c
(svn_client__checkout_internal): Rely on the caller to sleep even if we
throw an error.
(svn_client_checkout3): Handle the sleep here.
* subversion/libsvn_client/switch.c
(switch_internal): Rely on the caller to sleep even if we throw an error.
It missed the case where externals handling fails.
(svn_client_switch3): Handle the sleep here.
* subversion/libsvn_client/update.c
(update_internal): Rely on the caller to sleep even if we throw an error.
It missed the case where externals handling fails.
(svn_client_update4): Handle the sleep here in all cases. It missed the
case where, after updating at least one target, a subsequent target
fails.
* subversion/libsvn_client/revert.c
(svn_client_revert2): Sleep even when returning an error. It missed the
case where, after reverting at least one target, a subsequent target
fails.
]]]
- Julian
--
Join WANdisco's free daily demo sessions on Scaling Subversion for the
Enterprise
<http://www.wandisco.com/training/webinars>
Fix some sleep-for-timestamps code: avoid missing some cases where we need
to sleep. Simplify by localizing the handling.
TODO: Similarly fix and simplify the rest of the sleep_for_timestamps calls
in libsvn_client, which are in commit, copy, and merge.
TODO: Decide whether 'sleep' should be called before or after releasing
the WC write lock, and fix where necessary to be consistent.
TODO: In revert, only sleep if we actually revert something.
TODO: In checkout (with --force), only sleep if we actually update something.
TODO: Audit all other uses of 'goto' in Subversion for cases where we use
'if (err) goto ...' on some lines but accidentally use 'SVN_ERR' on others.
* subversion/libsvn_client/client.h
(svn_client__update_internal,
svn_client__checkout_internal,
svn_client__switch_internal,
svn_client__handle_externals): Document that the 'sleep' output is set
even if the function returns an error, and don't let it be NULL.
(svn_client__export_externals): Remove the unused and unneeded 'sleep'
output parameter.
* subversion/libsvn_client/export.c
(export_directory): Remove the unneeded 'sleep' variable.
* subversion/libsvn_client/externals.c
(svn_client__export_externals): Remove the unused and unneeded 'sleep'
output parameter.
* subversion/libsvn_client/checkout.c
(svn_client__checkout_internal): Rely on the caller to sleep even if we
throw an error.
(svn_client_checkout3): Handle the sleep here.
* subversion/libsvn_client/switch.c
(switch_internal): Rely on the caller to sleep even if we throw an error.
It missed the case where externals handling fails.
(svn_client_switch3): Handle the sleep here.
* subversion/libsvn_client/update.c
(update_internal): Rely on the caller to sleep even if we throw an error.
It missed the case where externals handling fails.
(svn_client_update4): Handle the sleep here in all cases. It missed the
case where, after updating at least one target, a subsequent target
fails.
* subversion/libsvn_client/revert.c
(svn_client_revert2): Sleep even when returning an error. It missed the
case where, after reverting at least one target, a subsequent target
fails.
--This line, and those below, will be ignored--
Index: subversion/libsvn_client/client.h
===================================================================
--- subversion/libsvn_client/client.h (revision 1462112)
+++ subversion/libsvn_client/client.h (working copy)
@@ -464,17 +464,15 @@ svn_client__make_local_parents(const cha
If DEPTH_IS_STICKY is set and DEPTH is not svn_depth_unknown, then
in addition to updating LOCAL_ABSPATH, also set its sticky ambient depth
value to DEPTH.
If IGNORE_EXTERNALS is true, do no externals processing.
- If TIMESTAMP_SLEEP is NULL this function will sleep before
- returning to ensure timestamp integrity. If TIMESTAMP_SLEEP is not
- NULL then the function will not sleep but will set *TIMESTAMP_SLEEP
- to TRUE if a sleep is required, and will not change
- *TIMESTAMP_SLEEP if no sleep is required.
+ Set *TIMESTAMP_SLEEP to TRUE if a sleep is required; otherwise do not
+ change *TIMESTAMP_SLEEP. The output will be valid even if the function
+ returns an error.
If ALLOW_UNVER_OBSTRUCTIONS is TRUE, unversioned children of LOCAL_ABSPATH
that obstruct items added from the repos are tolerated; if FALSE,
these obstructions cause the update to fail.
If ADDS_AS_MODIFICATION is TRUE, local additions are handled as
@@ -519,17 +517,17 @@ svn_client__update_internal(svn_revnum_t
REVISION based on the PEG_REVISION. Any information not in
*RA_CACHE is retrieved by a round-trip to the repository. RA_CACHE
may be NULL which indicates that no cache information is available.
If IGNORE_EXTERNALS is true, do no externals processing.
- If TIMESTAMP_SLEEP is NULL this function will sleep before
- returning to ensure timestamp integrity. If TIMESTAMP_SLEEP is not
- NULL then the function will not sleep but will set *TIMESTAMP_SLEEP
- to TRUE if a sleep is required, and will not change *TIMESTAMP_SLEEP
- if no sleep is required. If ALLOW_UNVER_OBSTRUCTIONS is TRUE,
+ Set *TIMESTAMP_SLEEP to TRUE if a sleep is required; otherwise do not
+ change *TIMESTAMP_SLEEP. The output will be valid even if the function
+ returns an error.
+
+ If ALLOW_UNVER_OBSTRUCTIONS is TRUE,
unversioned children of LOCAL_ABSPATH that obstruct items added from
the repos are tolerated; if FALSE, these obstructions cause the checkout
to fail.
If INNERCHECKOUT is true, no anchor check is performed on the target.
*/
@@ -548,17 +546,15 @@ svn_client__checkout_internal(svn_revnum
/* Switch a working copy PATH to URL@PEG_REVISION at REVISION, and (if not
NULL) set RESULT_REV to the switch revision. A write lock will be
acquired and released if not held. Only switch as deeply as DEPTH
indicates.
- If TIMESTAMP_SLEEP is NULL this function will sleep before
- returning to ensure timestamp integrity. If TIMESTAMP_SLEEP is not
- NULL then the function will not sleep but will set *TIMESTAMP_SLEEP
- to TRUE if a sleep is required, and will not change
- *TIMESTAMP_SLEEP if no sleep is required.
+ Set *TIMESTAMP_SLEEP to TRUE if a sleep is required; otherwise do not
+ change *TIMESTAMP_SLEEP. The output will be valid even if the function
+ returns an error.
If IGNORE_EXTERNALS is true, don't process externals.
If ALLOW_UNVER_OBSTRUCTIONS is TRUE, unversioned children of PATH
that obstruct items added from the repos are tolerated; if FALSE,
these obstructions cause the switch to fail.
@@ -972,15 +968,15 @@ svn_client__do_commit(const char *base_u
svn_depth_infinity, then it is presumed to be expanding any
shallower ambient depth, so changes to svn:externals values will be
interpreted.
Pass NOTIFY_FUNC with NOTIFY_BATON along to svn_client_checkout().
- *TIMESTAMP_SLEEP will be set TRUE if a sleep is required to ensure
- timestamp integrity, *TIMESTAMP_SLEEP will be unchanged if no sleep
- is required.
+ Set *TIMESTAMP_SLEEP to TRUE if a sleep is required; otherwise do not
+ change *TIMESTAMP_SLEEP. The output will be valid even if the function
+ returns an error.
Use POOL for temporary allocation. */
svn_error_t *
svn_client__handle_externals(apr_hash_t *externals_new,
apr_hash_t *ambient_depths,
const char *repos_root_url,
@@ -1003,26 +999,21 @@ svn_client__handle_externals(apr_hash_t
REQUESTED_DEPTH is the requested_depth of the driving operation; it
behaves as for svn_client__handle_externals(), except that ambient
depths are presumed to be svn_depth_infinity.
NATIVE_EOL is the value passed as NATIVE_EOL when exporting.
- *TIMESTAMP_SLEEP will be set TRUE if a sleep is required to ensure
- timestamp integrity, *TIMESTAMP_SLEEP will be unchanged if no sleep
- is required.
-
Use POOL for temporary allocation. */
svn_error_t *
svn_client__export_externals(apr_hash_t *externals,
const char *from_url,
const char *to_abspath,
const char *repos_root_url,
svn_depth_t requested_depth,
const char *native_eol,
svn_boolean_t ignore_keywords,
- svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
/* Baton for svn_client__dirent_fetcher */
struct svn_client__dirent_fetcher_baton_t
{
Index: subversion/libsvn_client/export.c
===================================================================
--- subversion/libsvn_client/export.c (revision 1462112)
+++ subversion/libsvn_client/export.c (working copy)
@@ -1293,13 +1293,12 @@ export_directory(const char *from_path_o
apr_pool_t *scratch_pool)
{
void *edit_baton;
const svn_delta_editor_t *export_editor;
const svn_ra_reporter3_t *reporter;
void *report_baton;
- svn_boolean_t use_sleep = FALSE;
svn_node_kind_t kind;
if (!ENABLE_EV2_IMPL)
SVN_ERR(get_editor_ev1(&export_editor, &edit_baton, eb, ctx,
scratch_pool, scratch_pool));
else
@@ -1348,13 +1347,13 @@ export_directory(const char *from_path_o
scratch_pool));
SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, scratch_pool));
SVN_ERR(svn_client__export_externals(eb->externals,
from_path_or_url,
to_abspath, repos_root_url,
depth, native_eol,
- ignore_keywords, &use_sleep,
+ ignore_keywords,
ctx, scratch_pool));
}
return SVN_NO_ERROR;
}
Index: subversion/libsvn_client/externals.c
===================================================================
--- subversion/libsvn_client/externals.c (revision 1462112)
+++ subversion/libsvn_client/externals.c (working copy)
@@ -1045,13 +1045,12 @@ svn_client__export_externals(apr_hash_t
const char *from_url,
const char *to_abspath,
const char *repos_root_url,
svn_depth_t requested_depth,
const char *native_eol,
svn_boolean_t ignore_keywords,
- svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_pool_t *sub_iterpool = svn_pool_create(scratch_pool);
apr_hash_index_t *hi;
Index: subversion/libsvn_client/checkout.c
===================================================================
--- subversion/libsvn_client/checkout.c (revision 1462112)
+++ subversion/libsvn_client/checkout.c (working copy)
@@ -75,15 +75,12 @@ svn_client__checkout_internal(svn_revnum
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
- svn_error_t *err = NULL;
- svn_boolean_t sleep_here = FALSE;
- svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
svn_node_kind_t kind;
apr_pool_t *session_pool = svn_pool_create(pool);
svn_ra_session_t *ra_session;
svn_client__pathrev_t *pathrev;
/* Sanity check. Without these, the checkout is meaningless. */
@@ -114,29 +111,33 @@ svn_client__checkout_internal(svn_revnum
return svn_error_createf
(SVN_ERR_UNSUPPORTED_FEATURE , NULL,
_("URL '%s' refers to a file, not a directory"), pathrev->url);
SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
+ /* Assume a checkout will always update a WC. (This is not always true
+ * if the 'force' option is used with an existing WC.) */
+ *timestamp_sleep = TRUE;
+
if (kind == svn_node_none)
{
/* Bootstrap: create an incomplete working-copy root dir. Its
entries file should only have an entry for THIS_DIR with a
URL, revnum, and an 'incomplete' flag. */
SVN_ERR(svn_io_make_dir_recursively(local_abspath, pool));
- err = initialize_area(local_abspath, pathrev, depth, ctx, pool);
+ SVN_ERR(initialize_area(local_abspath, pathrev, depth, ctx, pool));
}
else if (kind == svn_node_dir)
{
int wc_format;
const char *entry_url;
SVN_ERR(svn_wc_check_wc2(&wc_format, ctx->wc_ctx, local_abspath, pool));
if (! wc_format)
{
- err = initialize_area(local_abspath, pathrev, depth, ctx, pool);
+ SVN_ERR(initialize_area(local_abspath, pathrev, depth, ctx, pool));
}
else
{
/* Get PATH's URL. */
SVN_ERR(svn_wc__node_get_url(&entry_url, ctx->wc_ctx, local_abspath,
pool, pool));
@@ -157,34 +158,19 @@ svn_client__checkout_internal(svn_revnum
return svn_error_createf(SVN_ERR_WC_NODE_KIND_CHANGE, NULL,
_("'%s' already exists and is not a directory"),
svn_dirent_local_style(local_abspath, pool));
}
/* Have update fix the incompleteness. */
- if (! err)
- {
- err = svn_client__update_internal(result_rev, local_abspath,
- revision, depth, TRUE,
- ignore_externals,
- allow_unver_obstructions,
- TRUE /* adds_as_modification */,
- FALSE, FALSE,
- use_sleep, ctx, pool);
- }
-
- if (err)
- {
- /* Don't rely on the error handling to handle the sleep later, do
- it now */
- svn_io_sleep_for_timestamps(local_abspath, pool);
- return svn_error_trace(err);
- }
- *use_sleep = TRUE;
-
- if (sleep_here)
- svn_io_sleep_for_timestamps(local_abspath, pool);
+ SVN_ERR(svn_client__update_internal(result_rev, local_abspath,
+ revision, depth, TRUE,
+ ignore_externals,
+ allow_unver_obstructions,
+ TRUE /* adds_as_modification */,
+ FALSE, FALSE,
+ timestamp_sleep, ctx, pool));
return SVN_NO_ERROR;
}
svn_error_t *
svn_client_checkout3(svn_revnum_t *result_rev,
@@ -196,15 +182,21 @@ svn_client_checkout3(svn_revnum_t *resul
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
const char *local_abspath;
+ svn_error_t *err;
+ svn_boolean_t sleep_here = FALSE;
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
- return svn_client__checkout_internal(result_rev, URL, local_abspath,
- peg_revision, revision, depth,
- ignore_externals,
- allow_unver_obstructions, NULL,
- ctx, pool);
+ err = svn_client__checkout_internal(result_rev, URL, local_abspath,
+ peg_revision, revision, depth,
+ ignore_externals,
+ allow_unver_obstructions, &sleep_here,
+ ctx, pool);
+ if (sleep_here)
+ svn_io_sleep_for_timestamps(local_abspath, pool);
+
+ return svn_error_trace(err);
}
Index: subversion/libsvn_client/switch.c
===================================================================
--- subversion/libsvn_client/switch.c (revision 1462112)
+++ subversion/libsvn_client/switch.c (working copy)
@@ -102,19 +102,16 @@ switch_internal(svn_revnum_t *result_rev
const svn_ra_reporter3_t *reporter;
void *report_baton;
const char *anchor_url, *target;
svn_client__pathrev_t *switch_loc;
svn_ra_session_t *ra_session;
svn_revnum_t revnum;
- svn_error_t *err = SVN_NO_ERROR;
const char *diff3_cmd;
apr_hash_t *wcroot_iprops;
apr_array_header_t *inherited_props;
svn_boolean_t use_commit_times;
- svn_boolean_t sleep_here = FALSE;
- svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
const svn_delta_editor_t *switch_editor;
void *switch_edit_baton;
const char *preserved_exts_str;
apr_array_header_t *preserved_exts;
svn_boolean_t server_supports_depth;
struct svn_client__dirent_fetcher_baton_t dfb;
@@ -338,27 +335,21 @@ switch_internal(svn_revnum_t *result_rev
switch_editor, switch_edit_baton,
pool, pool));
/* Drive the reporter structure, describing the revisions within
PATH. When we call reporter->finish_report, the update_editor
will be driven by svn_repos_dir_delta2. */
- err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
- report_baton, TRUE, depth, (! depth_is_sticky),
- (! server_supports_depth),
- use_commit_times,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2, pool);
-
- if (err)
- {
- /* Don't rely on the error handling to handle the sleep later, do
- it now */
- svn_io_sleep_for_timestamps(local_abspath, pool);
- return svn_error_trace(err);
- }
- *use_sleep = TRUE;
+ *timestamp_sleep = TRUE;
+ SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
+ report_baton, TRUE,
+ depth, (! depth_is_sticky),
+ (! server_supports_depth),
+ use_commit_times,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
+ pool));
/* We handle externals after the switch is complete, so that
handling external items (and any errors therefrom) doesn't delay
the primary operation. */
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
{
@@ -370,25 +361,16 @@ switch_internal(svn_revnum_t *result_rev
depth, pool, pool));
SVN_ERR(svn_client__handle_externals(new_externals,
new_depths,
switch_loc->repos_root_url,
local_abspath,
- depth, use_sleep,
+ depth, timestamp_sleep,
ctx, pool));
}
- /* Sleep to ensure timestamp integrity (we do this regardless of
- errors in the actual switch operation(s)). */
- if (sleep_here)
- svn_io_sleep_for_timestamps(local_abspath, pool);
-
- /* Return errors we might have sustained. */
- if (err)
- return svn_error_trace(err);
-
/* Let everyone know we're finished here. */
if (ctx->notify_func2)
{
svn_wc_notify_t *notify
= svn_wc_create_notify(anchor_abspath, svn_wc_notify_update_completed,
pool);
@@ -477,16 +459,26 @@ svn_client_switch3(svn_revnum_t *result_
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
svn_boolean_t ignore_ancestry,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
+ svn_error_t *err;
+ svn_boolean_t sleep_here = FALSE;
+
if (svn_path_is_url(path))
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
_("'%s' is not a local path"), path);
- return svn_client__switch_internal(result_rev, path, switch_url,
- peg_revision, revision, depth,
- depth_is_sticky, ignore_externals,
- allow_unver_obstructions,
- ignore_ancestry, NULL, ctx, pool);
+ err = svn_client__switch_internal(result_rev, path, switch_url,
+ peg_revision, revision, depth,
+ depth_is_sticky, ignore_externals,
+ allow_unver_obstructions,
+ ignore_ancestry, NULL, ctx, pool);
+
+ /* Sleep to ensure timestamp integrity (we do this regardless of
+ errors in the actual switch operation(s)). */
+ if (sleep_here)
+ svn_io_sleep_for_timestamps(path, pool);
+
+ return svn_error_trace(err);
}
Index: subversion/libsvn_client/update.c
===================================================================
--- subversion/libsvn_client/update.c (revision 1462112)
+++ subversion/libsvn_client/update.c (working copy)
@@ -220,17 +220,14 @@ update_internal(svn_revnum_t *result_rev
const char *corrected_url;
const char *target;
const char *repos_root_url;
const char *repos_relpath;
const char *repos_uuid;
const char *anchor_url;
- svn_error_t *err;
svn_revnum_t revnum;
svn_boolean_t use_commit_times;
- svn_boolean_t sleep_here = FALSE;
- svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
svn_boolean_t clean_checkout = FALSE;
const char *diff3_cmd;
apr_hash_t *wcroot_iprops;
svn_opt_revision_t opt_rev;
svn_ra_session_t *ra_session;
const char *preserved_exts_str;
@@ -262,12 +259,13 @@ update_internal(svn_revnum_t *result_rev
TRUE, FALSE,
pool, pool));
/* It does not make sense to update conflict victims. */
if (repos_relpath)
{
+ svn_error_t *err;
svn_boolean_t text_conflicted, prop_conflicted;
anchor_url = svn_path_url_add_component2(repos_root_url, repos_relpath,
pool);
err = svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
@@ -449,28 +447,21 @@ update_internal(svn_revnum_t *result_rev
: svn_depth_unknown),
FALSE, update_editor, update_edit_baton, pool));
/* Drive the reporter structure, describing the revisions within
PATH. When we call reporter->finish_report, the
update_editor will be driven by svn_repos_dir_delta2. */
- err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
- report_baton, TRUE, depth, (! depth_is_sticky),
- (! server_supports_depth),
- use_commit_times,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- pool);
-
- if (err)
- {
- /* Don't rely on the error handling to handle the sleep later, do
- it now */
- svn_io_sleep_for_timestamps(local_abspath, pool);
- return svn_error_trace(err);
- }
- *use_sleep = TRUE;
+ *timestamp_sleep = TRUE;
+ SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
+ report_baton, TRUE,
+ depth, (! depth_is_sticky),
+ (! server_supports_depth),
+ use_commit_times,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
+ pool));
/* We handle externals after the update is complete, so that
handling external items (and any errors therefrom) doesn't delay
the primary operation. */
if ((SVN_DEPTH_IS_RECURSIVE(depth) || cropping_target)
&& (! ignore_externals))
@@ -482,19 +473,16 @@ update_internal(svn_revnum_t *result_rev
ctx->wc_ctx, local_abspath,
depth, pool, pool));
SVN_ERR(svn_client__handle_externals(new_externals,
new_depths,
repos_root_url, local_abspath,
- depth, use_sleep,
+ depth, timestamp_sleep,
ctx, pool));
}
- if (sleep_here)
- svn_io_sleep_for_timestamps(local_abspath, pool);
-
/* Let everyone know we're finished here (unless we're asked not to). */
if (ctx->notify_func2 && notify_summary)
{
svn_wc_notify_t *notify
= svn_wc_create_notify(local_abspath, svn_wc_notify_update_completed,
pool);
@@ -636,12 +624,13 @@ svn_client_update4(apr_array_header_t **
apr_pool_t *pool)
{
int i;
apr_pool_t *iterpool = svn_pool_create(pool);
const char *path = NULL;
svn_boolean_t sleep = FALSE;
+ svn_error_t *err = SVN_NO_ERROR;
if (result_revs)
*result_revs = apr_array_make(pool, paths->nelts, sizeof(svn_revnum_t));
for (i = 0; i < paths->nelts; ++i)
{
@@ -651,37 +640,42 @@ svn_client_update4(apr_array_header_t **
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
_("'%s' is not a local path"), path);
}
for (i = 0; i < paths->nelts; ++i)
{
- svn_error_t *err = SVN_NO_ERROR;
svn_revnum_t result_rev;
const char *local_abspath;
path = APR_ARRAY_IDX(paths, i, const char *);
svn_pool_clear(iterpool);
if (ctx->cancel_func)
- SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+ {
+ err = ctx->cancel_func(ctx->cancel_baton);
+ if (err)
+ goto cleanup;
+ }
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, iterpool));
+ err = svn_dirent_get_absolute(&local_abspath, path, iterpool);
+ if (err)
+ goto cleanup;
err = svn_client__update_internal(&result_rev, local_abspath,
revision, depth, depth_is_sticky,
ignore_externals,
allow_unver_obstructions,
adds_as_modification,
make_parents,
FALSE, &sleep,
ctx,
iterpool);
if (err)
{
- if(err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
- return svn_error_trace(err);
+ if (err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+ goto cleanup;
svn_error_clear(err);
/* SVN_ERR_WC_NOT_WORKING_COPY: it's not versioned */
result_rev = SVN_INVALID_REVNUM;
@@ -696,11 +690,12 @@ svn_client_update4(apr_array_header_t **
}
if (result_revs)
APR_ARRAY_PUSH(*result_revs, svn_revnum_t) = result_rev;
}
svn_pool_destroy(iterpool);
+ cleanup:
if (sleep)
svn_io_sleep_for_timestamps((paths->nelts == 1) ? path : NULL, pool);
- return SVN_NO_ERROR;
+ return svn_error_trace(err);
}
Index: subversion/libsvn_client/revert.c
===================================================================
--- subversion/libsvn_client/revert.c (revision 1462112)
+++ subversion/libsvn_client/revert.c (working copy)
@@ -157,22 +157,25 @@ svn_client_revert2(const apr_array_heade
/* See if we've been asked to cancel this operation. */
if ((ctx->cancel_func)
&& ((err = ctx->cancel_func(ctx->cancel_baton))))
goto errorful;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+ err = svn_dirent_get_absolute(&local_abspath, path, pool);
+ if (err)
+ goto errorful;
baton.local_abspath = local_abspath;
baton.depth = depth;
baton.use_commit_times = use_commit_times;
baton.changelists = changelists;
baton.ctx = ctx;
- SVN_ERR(svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath,
- pool));
+ err = svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath, pool);
+ if (err)
+ goto errorful;
lock_target = wc_root ? local_abspath
: svn_dirent_dirname(local_abspath, pool);
err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx,
lock_target, FALSE, pool, pool);
if (err)
goto errorful;