summaryrefslogtreecommitdiff
path: root/subversion/svn/resolve-cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svn/resolve-cmd.c')
-rw-r--r--subversion/svn/resolve-cmd.c193
1 files changed, 137 insertions, 56 deletions
diff --git a/subversion/svn/resolve-cmd.c b/subversion/svn/resolve-cmd.c
index 035bf29aff5ab..bbf9ff548ef5a 100644
--- a/subversion/svn/resolve-cmd.c
+++ b/subversion/svn/resolve-cmd.c
@@ -30,6 +30,7 @@
#include "svn_client.h"
#include "svn_error.h"
#include "svn_pools.h"
+#include "svn_hash.h"
#include "cl.h"
#include "svn_private_config.h"
@@ -38,6 +39,127 @@
/*** Code. ***/
+struct conflict_walker_baton
+{
+ svn_client_ctx_t *ctx;
+ svn_cl__accept_t accept_which;
+ svn_boolean_t quit;
+ svn_boolean_t external_failed;
+ svn_boolean_t printed_summary;
+ const char *editor_cmd;
+ const char *path_prefix;
+ svn_cmdline_prompt_baton_t *pb;
+ svn_cl__conflict_stats_t *conflict_stats;
+};
+
+/* Implements svn_client_conflict_walk_func_t. */
+static svn_error_t *
+conflict_walker(void *baton, svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ struct conflict_walker_baton *cwb = baton;
+
+ SVN_ERR(svn_cl__resolve_conflict(&cwb->quit, &cwb->external_failed,
+ &cwb->printed_summary, conflict,
+ cwb->accept_which, cwb->editor_cmd,
+ cwb->path_prefix, cwb->pb,
+ cwb->conflict_stats,
+ cwb->ctx, scratch_pool));
+ if (cwb->quit)
+ return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cl__walk_conflicts(apr_array_header_t *targets,
+ svn_cl__conflict_stats_t *conflict_stats,
+ svn_cl__opt_state_t *opt_state,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t had_error = FALSE;
+ svn_cmdline_prompt_baton_t *pb = apr_palloc(scratch_pool, sizeof(*pb));
+ struct conflict_walker_baton cwb = { 0 };
+ const char *path_prefix;
+ svn_error_t *err;
+ int i;
+ apr_pool_t *iterpool;
+
+ SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool));
+
+ pb->cancel_func = ctx->cancel_func;
+ pb->cancel_baton = ctx->cancel_baton;
+
+ cwb.ctx = ctx;
+ cwb.accept_which = opt_state->accept_which;
+ cwb.quit = FALSE;
+ cwb.external_failed = FALSE;
+ cwb.printed_summary = FALSE;
+ cwb.editor_cmd = opt_state->editor_cmd;
+ cwb.path_prefix = path_prefix;
+ cwb.pb = pb;
+ cwb.conflict_stats = conflict_stats;
+
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+ const char *local_abspath;
+ svn_client_conflict_t *conflict;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool));
+
+ if (opt_state->depth == svn_depth_empty)
+ {
+ SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, ctx,
+ iterpool, iterpool));
+ err = svn_cl__resolve_conflict(&cwb.quit, &cwb.external_failed,
+ &cwb.printed_summary,
+ conflict, opt_state->accept_which,
+ opt_state->editor_cmd,
+ path_prefix, pb, conflict_stats,
+ ctx, iterpool);
+ }
+ else
+ err = svn_client_conflict_walk(local_abspath, opt_state->depth,
+ conflict_walker, &cwb, ctx, iterpool);
+
+ if (err)
+ {
+ svn_error_t *root = svn_error_root_cause(err);
+
+ if (root->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ /* ### Ignore. These errors can happen due to the working copy
+ * ### being re-arranged during tree conflict resolution. */
+ svn_error_clear(err);
+ continue;
+ }
+ else if (root->apr_err == SVN_ERR_CANCELLED)
+ {
+ svn_error_clear(err);
+ break;
+ }
+
+ svn_handle_warning2(stderr, svn_error_root_cause(err), "svn: ");
+ svn_error_clear(err);
+ had_error = TRUE;
+ }
+ }
+ svn_pool_destroy(iterpool);
+
+ if (had_error)
+ return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Failure occurred resolving one or more "
+ "conflicts"));
+ return SVN_NO_ERROR;
+}
+
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__resolve(apr_getopt_t *os,
@@ -45,44 +167,10 @@ svn_cl__resolve(apr_getopt_t *os,
apr_pool_t *scratch_pool)
{
svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+ svn_cl__conflict_stats_t *conflict_stats =
+ ((svn_cl__cmd_baton_t *) baton)->conflict_stats;
svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
- svn_wc_conflict_choice_t conflict_choice;
- svn_error_t *err;
apr_array_header_t *targets;
- int i;
- apr_pool_t *iterpool;
- svn_boolean_t had_error = FALSE;
-
- switch (opt_state->accept_which)
- {
- case svn_cl__accept_working:
- conflict_choice = svn_wc_conflict_choose_merged;
- break;
- case svn_cl__accept_base:
- conflict_choice = svn_wc_conflict_choose_base;
- break;
- case svn_cl__accept_theirs_conflict:
- conflict_choice = svn_wc_conflict_choose_theirs_conflict;
- break;
- case svn_cl__accept_mine_conflict:
- conflict_choice = svn_wc_conflict_choose_mine_conflict;
- break;
- case svn_cl__accept_theirs_full:
- conflict_choice = svn_wc_conflict_choose_theirs_full;
- break;
- case svn_cl__accept_mine_full:
- conflict_choice = svn_wc_conflict_choose_mine_full;
- break;
- case svn_cl__accept_unspecified:
- if (opt_state->non_interactive)
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("missing --accept option"));
- conflict_choice = svn_wc_conflict_choose_unspecified;
- break;
- default:
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("invalid 'accept' ARG"));
- }
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -103,29 +191,22 @@ svn_cl__resolve(apr_getopt_t *os,
SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
- iterpool = svn_pool_create(scratch_pool);
- for (i = 0; i < targets->nelts; i++)
+ if (opt_state->accept_which == svn_cl__accept_unspecified &&
+ opt_state->non_interactive)
{
- const char *target = APR_ARRAY_IDX(targets, i, const char *);
- svn_pool_clear(iterpool);
- SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
- err = svn_client_resolve(target,
- opt_state->depth, conflict_choice,
- ctx,
- iterpool);
- if (err)
- {
- svn_handle_warning2(stderr, err, "svn: ");
- svn_error_clear(err);
- had_error = TRUE;
- }
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("missing --accept option"));
+ }
+ else if (opt_state->accept_which == svn_cl__accept_postpone ||
+ opt_state->accept_which == svn_cl__accept_edit ||
+ opt_state->accept_which == svn_cl__accept_launch)
+ {
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("invalid 'accept' ARG"));
}
- svn_pool_destroy(iterpool);
- if (had_error)
- return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
- _("Failure occurred resolving one or more "
- "conflicts"));
+ SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats,
+ opt_state, ctx, scratch_pool));
return SVN_NO_ERROR;
}