2 * relocate.c: do wc repos relocation
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 * ====================================================================
27 #include "svn_error.h"
28 #include "svn_pools.h"
29 #include "svn_dirent_uri.h"
35 #include "svn_private_config.h"
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
43 url_remove_final_relpath(const char *url
,
45 apr_pool_t
*result_pool
,
46 apr_pool_t
*scratch_pool
)
48 char *result
= apr_pstrdup(result_pool
, url
);
50 const char *relpath_end
;
52 SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(url
));
53 SVN_ERR_ASSERT_NO_RETURN(svn_relpath_is_canonical(relpath
));
58 relpath
= svn_path_uri_encode(relpath
, scratch_pool
);
59 result_end
= result
+ strlen(result
) - 1;
60 relpath_end
= relpath
+ strlen(relpath
) - 1;
62 while (relpath_end
>= relpath
)
64 if (*result_end
!= *relpath_end
)
71 if (*result_end
!= '/')
80 svn_wc_relocate4(svn_wc_context_t
*wc_ctx
,
81 const char *local_abspath
,
84 svn_wc_relocation_validator3_t validator
,
85 void *validator_baton
,
86 apr_pool_t
*scratch_pool
)
89 const char *repos_relpath
;
90 const char *old_repos_root
, *old_url
;
91 const char *new_repos_root
, *new_url
;
95 svn_boolean_t is_wc_root
;
97 SVN_ERR(svn_wc__is_wcroot(&is_wc_root
, wc_ctx
, local_abspath
,
101 const char *wcroot_abspath
;
104 err
= svn_wc__db_get_wcroot(&wcroot_abspath
, wc_ctx
->db
,
105 local_abspath
, scratch_pool
, scratch_pool
);
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
));
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
));
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
,
131 wc_ctx
->db
, local_abspath
, scratch_pool
,
134 if (kind
!= svn_node_dir
)
135 return svn_error_create(SVN_ERR_CLIENT_INVALID_RELOCATION
, NULL
,
136 _("Cannot relocate a single file"));
138 old_url
= svn_path_url_add_component2(old_repos_root
, repos_relpath
,
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')"),
148 if (old_url_len
== from_len
)
151 new_url
= apr_pstrcat(scratch_pool
, to
, old_url
+ from_len
, SVN_VA_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
);
157 new_repos_root
= url_remove_final_relpath(new_url
, repos_relpath
,
158 scratch_pool
, scratch_pool
);
160 return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION
, NULL
,
161 _("Invalid relocation destination: '%s' "
162 "(does not point to target)" ), new_url
);
164 SVN_ERR(validator(validator_baton
, uuid
, new_url
, new_repos_root
,
167 return svn_error_trace(svn_wc__db_global_relocate(wc_ctx
->db
, local_abspath
,