2 * resolve-cmd.c -- Subversion resolve subcommand
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
24 /* ==================================================================== */
30 #include "svn_client.h"
31 #include "svn_error.h"
32 #include "svn_pools.h"
36 #include "svn_private_config.h"
42 struct conflict_walker_baton
44 svn_client_ctx_t *ctx;
45 svn_cl__accept_t accept_which;
47 svn_boolean_t external_failed;
48 svn_boolean_t printed_summary;
49 const char *editor_cmd;
50 const char *path_prefix;
51 svn_cmdline_prompt_baton_t *pb;
52 svn_cl__conflict_stats_t *conflict_stats;
55 /* Implements svn_client_conflict_walk_func_t. */
57 conflict_walker(void *baton, svn_client_conflict_t *conflict,
58 apr_pool_t *scratch_pool)
60 struct conflict_walker_baton *cwb = baton;
62 SVN_ERR(svn_cl__resolve_conflict(&cwb->quit, &cwb->external_failed,
63 &cwb->printed_summary, conflict,
64 cwb->accept_which, cwb->editor_cmd,
65 cwb->path_prefix, cwb->pb,
67 cwb->ctx, scratch_pool));
69 return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
75 svn_cl__walk_conflicts(apr_array_header_t *targets,
76 svn_cl__conflict_stats_t *conflict_stats,
77 svn_cl__opt_state_t *opt_state,
78 svn_client_ctx_t *ctx,
79 apr_pool_t *scratch_pool)
81 svn_boolean_t had_error = FALSE;
82 svn_cmdline_prompt_baton_t *pb = apr_palloc(scratch_pool, sizeof(*pb));
83 struct conflict_walker_baton cwb = { 0 };
84 const char *path_prefix;
89 SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool));
91 pb->cancel_func = ctx->cancel_func;
92 pb->cancel_baton = ctx->cancel_baton;
95 cwb.accept_which = opt_state->accept_which;
97 cwb.external_failed = FALSE;
98 cwb.printed_summary = FALSE;
99 cwb.editor_cmd = opt_state->editor_cmd;
100 cwb.path_prefix = path_prefix;
102 cwb.conflict_stats = conflict_stats;
104 iterpool = svn_pool_create(scratch_pool);
105 for (i = 0; i < targets->nelts; i++)
107 const char *target = APR_ARRAY_IDX(targets, i, const char *);
108 const char *local_abspath;
109 svn_client_conflict_t *conflict;
111 svn_pool_clear(iterpool);
113 SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
115 SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool));
117 if (opt_state->depth == svn_depth_empty)
119 SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, ctx,
120 iterpool, iterpool));
121 err = svn_cl__resolve_conflict(&cwb.quit, &cwb.external_failed,
122 &cwb.printed_summary,
123 conflict, opt_state->accept_which,
124 opt_state->editor_cmd,
125 path_prefix, pb, conflict_stats,
129 err = svn_client_conflict_walk(local_abspath, opt_state->depth,
130 conflict_walker, &cwb, ctx, iterpool);
134 svn_error_t *root = svn_error_root_cause(err);
136 if (root->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
138 /* ### Ignore. These errors can happen due to the working copy
139 * ### being re-arranged during tree conflict resolution. */
140 svn_error_clear(err);
143 else if (root->apr_err == SVN_ERR_CANCELLED)
145 svn_error_clear(err);
149 svn_handle_warning2(stderr, svn_error_root_cause(err), "svn: ");
150 svn_error_clear(err);
154 svn_pool_destroy(iterpool);
157 return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
158 _("Failure occurred resolving one or more "
163 /* This implements the `svn_opt_subcommand_t' interface. */
165 svn_cl__resolve(apr_getopt_t *os,
167 apr_pool_t *scratch_pool)
169 svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
170 svn_cl__conflict_stats_t *conflict_stats =
171 ((svn_cl__cmd_baton_t *) baton)->conflict_stats;
172 svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
173 apr_array_header_t *targets;
175 SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
179 if (! targets->nelts)
180 svn_opt_push_implicit_dot_target(targets, scratch_pool);
182 if (opt_state->depth == svn_depth_unknown)
184 if (opt_state->accept_which == svn_cl__accept_unspecified)
185 opt_state->depth = svn_depth_infinity;
187 opt_state->depth = svn_depth_empty;
190 SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
192 SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
194 if (opt_state->accept_which == svn_cl__accept_unspecified &&
195 opt_state->non_interactive)
197 return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
198 _("missing --accept option"));
200 else if (opt_state->accept_which == svn_cl__accept_postpone ||
201 opt_state->accept_which == svn_cl__accept_edit ||
202 opt_state->accept_which == svn_cl__accept_launch)
204 return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
205 _("invalid 'accept' ARG"));
208 SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats,
209 opt_state, ctx, scratch_pool));