]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/libsvn_wc/relocate.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / subversion / subversion / libsvn_wc / relocate.c
1 /*
2  * relocate.c: do wc repos relocation
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 \f
26 #include "svn_wc.h"
27 #include "svn_error.h"
28 #include "svn_pools.h"
29 #include "svn_dirent_uri.h"
30 #include "svn_path.h"
31
32 #include "wc.h"
33 #include "props.h"
34
35 #include "svn_private_config.h"
36
37 \f
38 /* If the components of RELPATH exactly match (after being
39    URI-encoded) the final components of URL, return a copy of URL
40    minus those components allocated in RESULT_POOL; otherwise, return
41    NULL. */
42 static const char *
43 url_remove_final_relpath(const char *url,
44                          const char *relpath,
45                          apr_pool_t *result_pool,
46                          apr_pool_t *scratch_pool)
47 {
48   char *result = apr_pstrdup(result_pool, url);
49   char *result_end;
50   const char *relpath_end;
51
52   SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(url));
53   SVN_ERR_ASSERT_NO_RETURN(svn_relpath_is_canonical(relpath));
54
55   if (relpath[0] == 0)
56     return result;
57
58   relpath = svn_path_uri_encode(relpath, scratch_pool);
59   result_end = result + strlen(result) - 1;
60   relpath_end = relpath + strlen(relpath) - 1;
61
62   while (relpath_end >= relpath)
63     {
64       if (*result_end != *relpath_end)
65         return NULL;
66
67       relpath_end--;
68       result_end--;
69     }
70
71   if (*result_end != '/')
72     return NULL;
73
74   *result_end = 0;
75
76   return result;
77 }
78
79 svn_error_t *
80 svn_wc_relocate4(svn_wc_context_t *wc_ctx,
81                  const char *local_abspath,
82                  const char *from,
83                  const char *to,
84                  svn_wc_relocation_validator3_t validator,
85                  void *validator_baton,
86                  apr_pool_t *scratch_pool)
87 {
88   svn_node_kind_t kind;
89   const char *repos_relpath;
90   const char *old_repos_root, *old_url;
91   const char *new_repos_root, *new_url;
92   size_t from_len;
93   size_t old_url_len;
94   const char *uuid;
95   svn_boolean_t is_wc_root;
96
97   SVN_ERR(svn_wc__is_wcroot(&is_wc_root, wc_ctx, local_abspath,
98                             scratch_pool));
99   if (! is_wc_root)
100     {
101       const char *wcroot_abspath;
102       svn_error_t *err;
103
104       err = svn_wc__db_get_wcroot(&wcroot_abspath, wc_ctx->db,
105                                   local_abspath, scratch_pool, scratch_pool);
106       if (err)
107         {
108           svn_error_clear(err);
109           return svn_error_createf(
110             SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
111             _("Cannot relocate '%s' as it is not the root of a working copy"),
112             svn_dirent_local_style(local_abspath, scratch_pool));
113         }
114       else
115         {
116           return svn_error_createf(
117             SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
118             _("Cannot relocate '%s' as it is not the root of a working copy; "
119               "try relocating '%s' instead"),
120             svn_dirent_local_style(local_abspath, scratch_pool),
121             svn_dirent_local_style(wcroot_abspath, scratch_pool));
122         }
123     }
124
125   SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, &repos_relpath,
126                                &old_repos_root, &uuid,
127                                NULL, NULL, NULL, NULL, NULL, NULL,
128                                NULL, NULL, NULL, NULL, NULL, NULL,
129                                NULL, NULL, NULL, NULL, NULL, NULL,
130                                NULL, NULL, NULL,
131                                wc_ctx->db, local_abspath, scratch_pool,
132                                scratch_pool));
133
134   if (kind != svn_node_dir)
135     return svn_error_create(SVN_ERR_CLIENT_INVALID_RELOCATION, NULL,
136                             _("Cannot relocate a single file"));
137
138   old_url = svn_path_url_add_component2(old_repos_root, repos_relpath,
139                                         scratch_pool);
140   old_url_len = strlen(old_url);
141   from_len = strlen(from);
142   if ((from_len > old_url_len) || (strncmp(old_url, from, strlen(from)) != 0))
143     return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL,
144                              _("Invalid source URL prefix: '%s' (does not "
145                                "overlap target's URL '%s')"),
146                              from, old_url);
147
148   if (old_url_len == from_len)
149     new_url = to;
150   else
151     new_url = apr_pstrcat(scratch_pool, to, old_url + from_len, (char *)NULL);
152   if (! svn_path_is_url(new_url))
153     return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL,
154                              _("Invalid relocation destination: '%s' "
155                                "(not a URL)"), new_url);
156
157   new_repos_root = url_remove_final_relpath(new_url, repos_relpath,
158                                             scratch_pool, scratch_pool);
159   if (!new_repos_root)
160     return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL,
161                              _("Invalid relocation destination: '%s' "
162                                "(does not point to target)" ), new_url);
163
164   SVN_ERR(validator(validator_baton, uuid, new_url, new_repos_root,
165                     scratch_pool));
166
167   return svn_error_trace(svn_wc__db_global_relocate(wc_ctx->db, local_abspath,
168                                                     new_repos_root,
169                                                     scratch_pool));
170 }