]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/subversion/subversion/svn/resolve-cmd.c
THIS BRANCH IS OBSOLETE, PLEASE READ:
[FreeBSD/FreeBSD.git] / contrib / subversion / subversion / svn / resolve-cmd.c
1 /*
2  * resolve-cmd.c -- Subversion resolve subcommand
3  *
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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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
20  *    under the License.
21  * ====================================================================
22  */
23
24 /* ==================================================================== */
25
26
27 \f
28 /*** Includes. ***/
29 #include "svn_path.h"
30 #include "svn_client.h"
31 #include "svn_error.h"
32 #include "svn_pools.h"
33 #include "svn_hash.h"
34 #include "cl.h"
35
36 #include "svn_private_config.h"
37
38
39 \f
40 /*** Code. ***/
41
42 struct conflict_walker_baton
43 {
44   svn_client_ctx_t *ctx;
45   svn_cl__accept_t accept_which;
46   svn_boolean_t quit;
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;
53 };
54
55 /* Implements svn_client_conflict_walk_func_t. */
56 static svn_error_t *
57 conflict_walker(void *baton, svn_client_conflict_t *conflict,
58                 apr_pool_t *scratch_pool)
59 {
60   struct conflict_walker_baton *cwb = baton;
61
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,
66                                    cwb->conflict_stats,
67                                    cwb->ctx, scratch_pool));
68   if (cwb->quit)
69     return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
70
71   return SVN_NO_ERROR;
72 }
73
74 svn_error_t *
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)
80 {
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;
85   svn_error_t *err;
86   int i;
87   apr_pool_t *iterpool;
88
89   SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool));
90
91   pb->cancel_func = ctx->cancel_func;
92   pb->cancel_baton = ctx->cancel_baton;
93
94   cwb.ctx = ctx;
95   cwb.accept_which = opt_state->accept_which;
96   cwb.quit = FALSE;
97   cwb.external_failed = FALSE;
98   cwb.printed_summary = FALSE;
99   cwb.editor_cmd = opt_state->editor_cmd;
100   cwb.path_prefix = path_prefix;
101   cwb.pb = pb;
102   cwb.conflict_stats = conflict_stats;
103
104   iterpool = svn_pool_create(scratch_pool);
105   for (i = 0; i < targets->nelts; i++)
106     {
107       const char *target = APR_ARRAY_IDX(targets, i, const char *);
108       const char *local_abspath;
109       svn_client_conflict_t *conflict;
110
111       svn_pool_clear(iterpool);
112
113       SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
114
115       SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool));
116
117       if (opt_state->depth == svn_depth_empty)
118         {
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,
126                                          ctx, iterpool);
127         }
128       else
129         err = svn_client_conflict_walk(local_abspath, opt_state->depth,
130                                        conflict_walker, &cwb, ctx, iterpool);
131
132       if (err)
133         {
134           svn_error_t *root = svn_error_root_cause(err);
135
136           if (root->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
137             {
138               /* ### Ignore. These errors can happen due to the working copy
139                * ### being re-arranged during tree conflict resolution. */
140               svn_error_clear(err);
141               continue;
142             }
143           else if (root->apr_err == SVN_ERR_CANCELLED)
144             {
145               svn_error_clear(err);
146               break;
147             }
148
149           svn_handle_warning2(stderr, svn_error_root_cause(err), "svn: ");
150           svn_error_clear(err);
151           had_error = TRUE;
152         }
153     }
154   svn_pool_destroy(iterpool);
155
156   if (had_error)
157     return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
158                             _("Failure occurred resolving one or more "
159                               "conflicts"));
160   return SVN_NO_ERROR;
161 }
162
163 /* This implements the `svn_opt_subcommand_t' interface. */
164 svn_error_t *
165 svn_cl__resolve(apr_getopt_t *os,
166                 void *baton,
167                 apr_pool_t *scratch_pool)
168 {
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;
174
175   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
176                                                       opt_state->targets,
177                                                       ctx, FALSE,
178                                                       scratch_pool));
179   if (! targets->nelts)
180     svn_opt_push_implicit_dot_target(targets, scratch_pool);
181
182   if (opt_state->depth == svn_depth_unknown)
183     {
184       if (opt_state->accept_which == svn_cl__accept_unspecified)
185         opt_state->depth = svn_depth_infinity;
186       else
187         opt_state->depth = svn_depth_empty;
188     }
189
190   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
191
192   SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
193
194   if (opt_state->accept_which == svn_cl__accept_unspecified &&
195       opt_state->non_interactive)
196     {
197       return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
198                               _("missing --accept option"));
199     }
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)
203     {
204       return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
205                               _("invalid 'accept' ARG"));
206     }
207
208   SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats,
209                                  opt_state, ctx, scratch_pool));
210
211   return SVN_NO_ERROR;
212 }