]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/subversion/subversion/svn/switch-cmd.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / subversion / subversion / svn / switch-cmd.c
1 /*
2  * switch-cmd.c -- Bring work tree in sync with a different URL
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
30 #include "svn_wc.h"
31 #include "svn_client.h"
32 #include "svn_dirent_uri.h"
33 #include "svn_path.h"
34 #include "svn_error.h"
35 #include "svn_pools.h"
36 #include "cl.h"
37
38 #include "svn_private_config.h"
39 \f
40 /*** Code. ***/
41
42 static svn_error_t *
43 rewrite_urls(const apr_array_header_t *targets,
44              svn_boolean_t ignore_externals,
45              svn_client_ctx_t *ctx,
46              apr_pool_t *pool)
47 {
48   apr_pool_t *subpool;
49   const char *from;
50   const char *to;
51
52   if (targets->nelts < 2)
53     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
54
55   from = APR_ARRAY_IDX(targets, 0, const char *);
56   to = APR_ARRAY_IDX(targets, 1, const char *);
57
58   /* "--relocate http https" and "--relocate http://foo svn://bar" are OK,
59      but things like "--relocate http://foo svn" are not */
60   if (svn_path_is_url(from) != svn_path_is_url(to))
61     return svn_error_createf
62       (SVN_ERR_INCORRECT_PARAMS, NULL,
63        _("'%s' to '%s' is not a valid relocation"), from, to);
64
65   subpool = svn_pool_create(pool);
66
67   if (targets->nelts == 2)
68     {
69       SVN_ERR(svn_client_relocate2("", from, to, ignore_externals,
70                                    ctx, pool));
71     }
72   else
73     {
74       int i;
75
76       for (i = 2; i < targets->nelts; i++)
77         {
78           const char *target = APR_ARRAY_IDX(targets, i, const char *);
79           svn_pool_clear(subpool);
80           SVN_ERR(svn_client_relocate2(target, from, to,
81                                        ignore_externals, ctx, subpool));
82         }
83     }
84
85   svn_pool_destroy(subpool);
86   return SVN_NO_ERROR;
87 }
88
89
90 /* This implements the `svn_opt_subcommand_t' interface. */
91 svn_error_t *
92 svn_cl__switch(apr_getopt_t *os,
93                void *baton,
94                apr_pool_t *scratch_pool)
95 {
96   svn_error_t *err = SVN_NO_ERROR;
97   svn_error_t *externals_err = SVN_NO_ERROR;
98   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
99   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
100   apr_array_header_t *targets;
101   const char *target, *switch_url;
102   svn_opt_revision_t peg_revision;
103   svn_depth_t depth;
104   svn_boolean_t depth_is_sticky;
105   struct svn_cl__check_externals_failed_notify_baton nwb;
106
107   /* This command should discover (or derive) exactly two cmdline
108      arguments: a local path to update ("target"), and a new url to
109      switch to ("switch_url"). */
110   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
111                                                       opt_state->targets,
112                                                       ctx, FALSE,
113                                                       scratch_pool));
114
115   /* handle only-rewrite case specially */
116   if (opt_state->relocate)
117     return rewrite_urls(targets, opt_state->ignore_externals,
118                         ctx, scratch_pool);
119
120   if (targets->nelts < 1)
121     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
122   if (targets->nelts > 2)
123     return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
124
125   /* Get the required SWITCH_URL and its optional PEG_REVISION, and the
126    * optional TARGET argument. */
127   SVN_ERR(svn_opt_parse_path(&peg_revision, &switch_url,
128                              APR_ARRAY_IDX(targets, 0, const char *),
129                              scratch_pool));
130   if (targets->nelts == 1)
131     target = "";
132   else
133     target = APR_ARRAY_IDX(targets, 1, const char *);
134
135   /* Validate the switch_url */
136   if (! svn_path_is_url(switch_url))
137     return svn_error_createf(SVN_ERR_BAD_URL, NULL,
138                              _("'%s' does not appear to be a URL"), switch_url);
139
140   SVN_ERR(svn_cl__check_target_is_local_path(target));
141
142   /* Deal with depthstuffs. */
143   if (opt_state->set_depth != svn_depth_unknown)
144     {
145       depth = opt_state->set_depth;
146       depth_is_sticky = TRUE;
147     }
148   else
149     {
150       depth = opt_state->depth;
151       depth_is_sticky = FALSE;
152     }
153
154   nwb.wrapped_func = ctx->notify_func2;
155   nwb.wrapped_baton = ctx->notify_baton2;
156   nwb.had_externals_error = FALSE;
157   ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper;
158   ctx->notify_baton2 = &nwb;
159
160   /* Do the 'switch' update. */
161   err = svn_client_switch3(NULL, target, switch_url, &peg_revision,
162                            &(opt_state->start_revision), depth,
163                            depth_is_sticky, opt_state->ignore_externals,
164                            opt_state->force, opt_state->ignore_ancestry,
165                            ctx, scratch_pool);
166   if (err)
167     {
168       if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES)
169         return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, err,
170                                  _("Path '%s' does not share common version "
171                                    "control ancestry with the requested switch "
172                                    "location.  Use --ignore-ancestry to "
173                                    "disable this check."),
174                                    svn_dirent_local_style(target,
175                                                           scratch_pool));
176       if (err->apr_err == SVN_ERR_RA_UUID_MISMATCH
177           || err->apr_err == SVN_ERR_WC_INVALID_SWITCH)
178         return svn_error_quick_wrap(
179                  err,
180                  _("'svn switch' does not support switching a working copy to "
181                    "a different repository"));
182       return err;
183     }
184
185   if (nwb.had_externals_error)
186     externals_err = svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS,
187                                      NULL,
188                                      _("Failure occurred processing one or "
189                                        "more externals definitions"));
190
191   if (! opt_state->quiet)
192     {
193       err = svn_cl__notifier_print_conflict_stats(nwb.wrapped_baton, scratch_pool);
194       if (err)
195         return svn_error_compose_create(externals_err, err);
196     }
197
198   return svn_error_compose_create(externals_err, err);
199 }