Author: stsp
Date: Wed Jul 4 15:09:36 2012
New Revision: 1357298
URL: http://svn.apache.org/viewvc?rev=1357298&view=rev
Log:
Make 'svn update' display conflict summary information before the interactive
conflict resolver is started, and don't invoke the conflict resolver if no
conflicts occurred during the current update operation but there are unresolved
conflicts from a previous update operation.
While trying various ways of achieving the goal of this commit, I came to
the conclusion that it is easier for client implementors to invoke the conflict
resolver themselves, rather than having the libsvn_client library invoke it.
So this commit also changes the corresponding libsvn_client code back to
its pre-r1353734 state and gives back full control over whether conflicts
are postponed during the update operation to libsvn_client API users.
Similar changes for switch and merge will follow.
* subversion/libsvn_client/checkout.c
(svn_client__checkout_internal): Track parameter list changes to
svn_client__update_internal().
* subversion/libsvn_client/client.h
(svn_client__update_internal): Remove cONFLICT_FUNC2 and CONFLICT_BATON2
paramters from function declaration.
* subversion/libsvn_client/externals.c
(switch_dir_external): Track paramter list changes to
svn_client__update_internal().
* subversion/libsvn_client/update.c
(update_internal, svn_client__update_internal): Drop the CONFLICT_FUNC2 and
CONFLICT_BATON2 parameters. Always invoke the conflict resolution callback
provided in the client context.
(svn_client_update4): Track above parameter list changes, and stop invoking
the conflict resolver before returning. This gives control over when the
conflict resolver runs back to API users.
* subversion/svn/cl.h
(svn_cl__notifier_check_conflicts, svn_cl__resolve_conflicts): Declare.
* subversion/svn/conflict-callbacks.c
(svn_cl__resolve_conflicts): New helper function that runs the resolver
on a specified list of targets.
* subversion/svn/notify.c
(svn_cl__notifier_check_conflicts): New helper to determine whether conflicts
occurred during an operation.
* subversion/svn/update-cmd.c
(svn_cl__update): Set the conflict callback in the client context to NULL
before calling svn_client_update(), postponing all conflicts. If conflicts
were reported during the update, run the conflict resolver.
* subversion/tests/cmdline/update_tests.py
(update_accept_conflicts): Adjust expected output. The conflict summary is
now printed before output from the conflict resolver is displayed, not after.
Modified:
subversion/trunk/subversion/libsvn_client/checkout.c
subversion/trunk/subversion/libsvn_client/client.h
subversion/trunk/subversion/libsvn_client/externals.c
subversion/trunk/subversion/libsvn_client/update.c
subversion/trunk/subversion/svn/cl.h
subversion/trunk/subversion/svn/conflict-callbacks.c
subversion/trunk/subversion/svn/notify.c
subversion/trunk/subversion/svn/update-cmd.c
subversion/trunk/subversion/tests/cmdline/update_tests.py
Modified: subversion/trunk/subversion/libsvn_client/checkout.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/checkout.c?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/checkout.c (original)
+++ subversion/trunk/subversion/libsvn_client/checkout.c Wed Jul 4 15:09:36
2012
@@ -168,10 +168,7 @@ svn_client__checkout_internal(svn_revnum
allow_unver_obstructions,
TRUE /* adds_as_modification */,
FALSE, FALSE,
- use_sleep, ctx,
- ctx->conflict_func2,
- ctx->conflict_baton2,
- pool);
+ use_sleep, ctx, pool);
}
if (err)
Modified: subversion/trunk/subversion/libsvn_client/client.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Wed Jul 4 15:09:36 2012
@@ -463,10 +463,6 @@ svn_client__make_local_parents(const cha
target which are missing from the working copy.
NOTE: You may not specify both INNERUPDATE and MAKE_PARENTS as true.
-
- Use CONFLICT_FUNC2 and CONFLICT_BATON2 instead of CTX->CONFLICT_FUNC2
- and CTX->CONFLICT_BATON2. If CONFLICT_FUNC2 is NULL, postpone all conflicts
- allowing the caller to perform post-update conflict resolution.
*/
svn_error_t *
svn_client__update_internal(svn_revnum_t *result_rev,
@@ -481,8 +477,6 @@ svn_client__update_internal(svn_revnum_t
svn_boolean_t innerupdate,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
- svn_wc_conflict_resolver_func2_t conflict_func2,
- void *conflict_baton2,
apr_pool_t *pool);
/* Checkout into LOCAL_ABSPATH a working copy of URL at REVISION, and (if not
Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Wed Jul 4 15:09:36
2012
@@ -169,10 +169,7 @@ switch_dir_external(const char *local_ab
FALSE, FALSE, FALSE, TRUE,
FALSE, TRUE,
timestamp_sleep,
- ctx,
- ctx->conflict_func2,
- ctx->conflict_baton2,
- subpool));
+ ctx, subpool));
svn_pool_destroy(subpool);
goto cleanup;
}
Modified: subversion/trunk/subversion/libsvn_client/update.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Wed Jul 4 15:09:36 2012
@@ -185,8 +185,6 @@ update_internal(svn_revnum_t *result_rev
svn_boolean_t *timestamp_sleep,
svn_boolean_t notify_summary,
svn_client_ctx_t *ctx,
- svn_wc_conflict_resolver_func2_t conflict_func2,
- void *conflict_baton2,
apr_pool_t *pool)
{
const svn_delta_editor_t *update_editor;
@@ -376,7 +374,7 @@ update_internal(svn_revnum_t *result_rev
clean_checkout,
diff3_cmd, preserved_exts,
svn_client__dirent_fetcher, &dfb,
- conflict_func2, conflict_baton2,
+ ctx->conflict_func2, ctx->conflict_baton2,
NULL, NULL,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func2, ctx->notify_baton2,
@@ -467,8 +465,6 @@ svn_client__update_internal(svn_revnum_t
svn_boolean_t innerupdate,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
- svn_wc_conflict_resolver_func2_t conflict_func2,
- void *conflict_baton2,
apr_pool_t *pool)
{
const char *anchor_abspath, *lockroot_abspath;
@@ -518,8 +514,7 @@ svn_client__update_internal(svn_revnum_t
&peg_revision, svn_depth_empty, FALSE,
ignore_externals, allow_unver_obstructions,
adds_as_modification, timestamp_sleep,
- FALSE, ctx, conflict_func2, conflict_baton2,
- pool);
+ FALSE, ctx, pool);
if (err)
goto cleanup;
anchor_abspath = missing_parent;
@@ -543,7 +538,7 @@ svn_client__update_internal(svn_revnum_t
&peg_revision, depth, depth_is_sticky,
ignore_externals, allow_unver_obstructions,
adds_as_modification, timestamp_sleep,
- TRUE, ctx, conflict_func2, conflict_baton2, pool);
+ TRUE, ctx, pool);
cleanup:
err = svn_error_compose_create(
err,
@@ -604,7 +599,6 @@ svn_client_update4(apr_array_header_t **
make_parents,
FALSE, &sleep,
ctx,
- NULL, NULL, /* postpone conflicts */
iterpool);
if (err)
@@ -629,44 +623,10 @@ svn_client_update4(apr_array_header_t **
if (result_revs)
APR_ARRAY_PUSH(*result_revs, svn_revnum_t) = result_rev;
}
+ svn_pool_destroy(iterpool);
if (sleep)
svn_io_sleep_for_timestamps((paths->nelts == 1) ? path : NULL, pool);
- if (ctx->conflict_func2)
- {
- for (i = 0; i < paths->nelts; ++i)
- {
- svn_error_t *err = SVN_NO_ERROR;
- const char *local_abspath;
-
- svn_pool_clear(iterpool);
- path = APR_ARRAY_IDX(paths, i, const char *);
-
- /* Resolve conflicts within the updated subtree. */
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, iterpool));
- err = svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath, depth,
- TRUE /* resolve_text */,
- "" /* resolve_prop (ALL props) */,
- TRUE /* resolve_tree */,
- svn_wc_conflict_choose_unspecified,
- ctx->conflict_func2,
- ctx->conflict_baton2,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2,
ctx->notify_baton2,
- iterpool);
- if (err)
- {
- if ((err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
- && (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND))
- return svn_error_trace(err);
-
- svn_error_clear(err);
- }
- }
- }
-
- svn_pool_destroy(iterpool);
-
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/svn/cl.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Wed Jul 4 15:09:36 2012
@@ -603,6 +603,10 @@ svn_cl__notifier_mark_export(void *baton
svn_error_t *
svn_cl__notifier_mark_wc_to_repos_copy(void *baton);
+/* Return TRUE if any conflicts were detected during notification. */
+svn_boolean_t
+svn_cl__notifier_check_conflicts(void *baton);
+
/* Baton for use with svn_cl__check_externals_failed_notify_wrapper(). */
struct svn_cl__check_externals_failed_notify_baton
{
@@ -850,6 +854,14 @@ svn_cl__check_related_source_and_target(
svn_client_ctx_t *ctx,
apr_pool_t *pool);
+/* Run the conflict resolver for all targets in the TARGETS list with
+ * the specified DEPTH. */
+svn_error_t *
+svn_cl__resolve_conflicts(apr_array_header_t *targets,
+ svn_depth_t depth,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/trunk/subversion/svn/conflict-callbacks.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/conflict-callbacks.c?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/conflict-callbacks.c (original)
+++ subversion/trunk/subversion/svn/conflict-callbacks.c Wed Jul 4 15:09:36
2012
@@ -814,3 +814,39 @@ svn_cl__conflict_handler(svn_wc_conflict
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_cl__resolve_conflicts(apr_array_header_t *targets,
+ svn_depth_t depth,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+ apr_pool_t *iterpool;
+
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+ svn_error_t *err = SVN_NO_ERROR;
+ const char *local_abspath;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool));
+ err = svn_client_resolve(local_abspath, depth,
+ svn_wc_conflict_choose_unspecified,
+ ctx, iterpool);
+ if (err)
+ {
+ if ((err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+ && (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND))
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ }
+ }
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/trunk/subversion/svn/notify.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/notify.c?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/notify.c (original)
+++ subversion/trunk/subversion/svn/notify.c Wed Jul 4 15:09:36 2012
@@ -1086,3 +1086,10 @@ svn_cl__check_externals_failed_notify_wr
nwb->wrapped_func(nwb->wrapped_baton, n, pool);
}
+svn_boolean_t
+svn_cl__notifier_check_conflicts(void *baton)
+{
+ struct notify_baton *nb = baton;
+
+ return (nb->text_conflicts || nb->prop_conflicts || nb->tree_conflicts);
+}
Modified: subversion/trunk/subversion/svn/update-cmd.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/update-cmd.c?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/update-cmd.c (original)
+++ subversion/trunk/subversion/svn/update-cmd.c Wed Jul 4 15:09:36 2012
@@ -110,6 +110,8 @@ svn_cl__update(apr_getopt_t *os,
svn_boolean_t depth_is_sticky;
struct svn_cl__check_externals_failed_notify_baton nwb;
apr_array_header_t *result_revs;
+ svn_wc_conflict_resolver_func2_t conflict_func2 = ctx->conflict_func2;
+ void *conflict_baton2 = ctx->conflict_baton2;
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -154,6 +156,11 @@ svn_cl__update(apr_getopt_t *os,
ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper;
ctx->notify_baton2 = &nwb;
+ /* Postpone conflict resolution during the update operation.
+ * If any conflicts occur we'll run the conflict resolver later. */
+ ctx->conflict_func2 = NULL;
+ ctx->conflict_baton2 = NULL;
+
SVN_ERR(svn_client_update4(&result_revs, targets,
&(opt_state->start_revision),
depth, depth_is_sticky,
@@ -172,6 +179,13 @@ svn_cl__update(apr_getopt_t *os,
SVN_ERR(svn_cl__print_conflict_stats(nwb.wrapped_baton, scratch_pool));
}
+ if (conflict_func2 && svn_cl__notifier_check_conflicts(nwb.wrapped_baton))
+ {
+ ctx->conflict_func2 = conflict_func2;
+ ctx->conflict_baton2 = conflict_baton2;
+ SVN_ERR(svn_cl__resolve_conflicts(targets, depth, ctx, scratch_pool));
+ }
+
if (nwb.had_externals_error)
return svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL,
_("Failure occurred processing one or more "
Modified: subversion/trunk/subversion/tests/cmdline/update_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/update_tests.py?rev=1357298&r1=1357297&r2=1357298&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/update_tests.py Wed Jul 4
15:09:36 2012
@@ -3916,10 +3916,10 @@ def update_accept_conflicts(sbox):
["Updating '%s':\n" % (mu_path_backup),
'C %s\n' % (mu_path_backup,),
'Updated to revision 2.\n',
- "Resolved conflicted state of '%s'\n"
- % (mu_path_backup),
'Summary of conflicts:\n',
- ' Text conflicts: 1\n'],
+ ' Text conflicts: 1\n',
+ "Resolved conflicted state of '%s'\n"
+ % (mu_path_backup)],
[],
'update', '--accept=base',
mu_path_backup)
@@ -3930,10 +3930,10 @@ def update_accept_conflicts(sbox):
["Updating '%s':\n" % (alpha_path_backup),
'C %s\n' % (alpha_path_backup,),
'Updated to revision 2.\n',
- "Resolved conflicted state of '%s'\n"
- % (alpha_path_backup),
'Summary of conflicts:\n',
- ' Text conflicts: 1\n'],
+ ' Text conflicts: 1\n',
+ "Resolved conflicted state of '%s'\n"
+ % (alpha_path_backup)],
[],
'update', '--accept=mine-full',
alpha_path_backup)
@@ -3944,10 +3944,10 @@ def update_accept_conflicts(sbox):
["Updating '%s':\n" % (beta_path_backup),
'C %s\n' % (beta_path_backup,),
'Updated to revision 2.\n',
- "Resolved conflicted state of '%s'\n"
- % (beta_path_backup),
'Summary of conflicts:\n',
- ' Text conflicts: 1\n'],
+ ' Text conflicts: 1\n',
+ "Resolved conflicted state of '%s'\n"
+ % (beta_path_backup)],
[],
'update', '--accept=theirs-full',
beta_path_backup)
@@ -3960,10 +3960,10 @@ def update_accept_conflicts(sbox):
["Updating '%s':\n" % (pi_path_backup),
'C %s\n' % (pi_path_backup,),
'Updated to revision 2.\n',
- "Resolved conflicted state of '%s'\n"
- % (pi_path_backup),
'Summary of conflicts:\n',
- ' Text conflicts: 1\n'],
+ ' Text conflicts: 1\n',
+ "Resolved conflicted state of '%s'\n"
+ % (pi_path_backup)],
"system(.*) returned.*", 0,
'update', '--accept=edit',
pi_path_backup)