1251881Speter/* 2251881Speter * relocate.c: do wc repos relocation 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter#include "svn_wc.h" 27251881Speter#include "svn_error.h" 28251881Speter#include "svn_pools.h" 29251881Speter#include "svn_dirent_uri.h" 30251881Speter#include "svn_path.h" 31251881Speter 32251881Speter#include "wc.h" 33251881Speter#include "props.h" 34251881Speter 35251881Speter#include "svn_private_config.h" 36251881Speter 37251881Speter 38251881Speter/* If the components of RELPATH exactly match (after being 39251881Speter URI-encoded) the final components of URL, return a copy of URL 40251881Speter minus those components allocated in RESULT_POOL; otherwise, return 41251881Speter NULL. */ 42251881Speterstatic const char * 43251881Speterurl_remove_final_relpath(const char *url, 44251881Speter const char *relpath, 45251881Speter apr_pool_t *result_pool, 46251881Speter apr_pool_t *scratch_pool) 47251881Speter{ 48251881Speter char *result = apr_pstrdup(result_pool, url); 49251881Speter char *result_end; 50251881Speter const char *relpath_end; 51251881Speter 52251881Speter SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(url)); 53251881Speter SVN_ERR_ASSERT_NO_RETURN(svn_relpath_is_canonical(relpath)); 54251881Speter 55251881Speter if (relpath[0] == 0) 56251881Speter return result; 57251881Speter 58251881Speter relpath = svn_path_uri_encode(relpath, scratch_pool); 59251881Speter result_end = result + strlen(result) - 1; 60251881Speter relpath_end = relpath + strlen(relpath) - 1; 61251881Speter 62251881Speter while (relpath_end >= relpath) 63251881Speter { 64251881Speter if (*result_end != *relpath_end) 65251881Speter return NULL; 66251881Speter 67251881Speter relpath_end--; 68251881Speter result_end--; 69251881Speter } 70251881Speter 71251881Speter if (*result_end != '/') 72251881Speter return NULL; 73251881Speter 74251881Speter *result_end = 0; 75251881Speter 76251881Speter return result; 77251881Speter} 78251881Speter 79251881Spetersvn_error_t * 80251881Spetersvn_wc_relocate4(svn_wc_context_t *wc_ctx, 81251881Speter const char *local_abspath, 82251881Speter const char *from, 83251881Speter const char *to, 84251881Speter svn_wc_relocation_validator3_t validator, 85251881Speter void *validator_baton, 86251881Speter apr_pool_t *scratch_pool) 87251881Speter{ 88251881Speter svn_node_kind_t kind; 89251881Speter const char *repos_relpath; 90251881Speter const char *old_repos_root, *old_url; 91251881Speter const char *new_repos_root, *new_url; 92251881Speter size_t from_len; 93251881Speter size_t old_url_len; 94251881Speter const char *uuid; 95251881Speter svn_boolean_t is_wc_root; 96251881Speter 97251881Speter SVN_ERR(svn_wc__is_wcroot(&is_wc_root, wc_ctx, local_abspath, 98251881Speter scratch_pool)); 99251881Speter if (! is_wc_root) 100251881Speter { 101251881Speter const char *wcroot_abspath; 102251881Speter svn_error_t *err; 103251881Speter 104251881Speter err = svn_wc__db_get_wcroot(&wcroot_abspath, wc_ctx->db, 105251881Speter local_abspath, scratch_pool, scratch_pool); 106251881Speter if (err) 107251881Speter { 108251881Speter svn_error_clear(err); 109251881Speter return svn_error_createf( 110251881Speter SVN_ERR_WC_INVALID_OP_ON_CWD, NULL, 111251881Speter _("Cannot relocate '%s' as it is not the root of a working copy"), 112251881Speter svn_dirent_local_style(local_abspath, scratch_pool)); 113251881Speter } 114251881Speter else 115251881Speter { 116251881Speter return svn_error_createf( 117251881Speter SVN_ERR_WC_INVALID_OP_ON_CWD, NULL, 118251881Speter _("Cannot relocate '%s' as it is not the root of a working copy; " 119251881Speter "try relocating '%s' instead"), 120251881Speter svn_dirent_local_style(local_abspath, scratch_pool), 121251881Speter svn_dirent_local_style(wcroot_abspath, scratch_pool)); 122251881Speter } 123251881Speter } 124251881Speter 125251881Speter SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, &repos_relpath, 126251881Speter &old_repos_root, &uuid, 127251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 128251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 129251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 130251881Speter NULL, NULL, NULL, 131251881Speter wc_ctx->db, local_abspath, scratch_pool, 132251881Speter scratch_pool)); 133251881Speter 134251881Speter if (kind != svn_node_dir) 135251881Speter return svn_error_create(SVN_ERR_CLIENT_INVALID_RELOCATION, NULL, 136251881Speter _("Cannot relocate a single file")); 137251881Speter 138251881Speter old_url = svn_path_url_add_component2(old_repos_root, repos_relpath, 139251881Speter scratch_pool); 140251881Speter old_url_len = strlen(old_url); 141251881Speter from_len = strlen(from); 142251881Speter if ((from_len > old_url_len) || (strncmp(old_url, from, strlen(from)) != 0)) 143251881Speter return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL, 144251881Speter _("Invalid source URL prefix: '%s' (does not " 145251881Speter "overlap target's URL '%s')"), 146251881Speter from, old_url); 147251881Speter 148251881Speter if (old_url_len == from_len) 149251881Speter new_url = to; 150251881Speter else 151251881Speter new_url = apr_pstrcat(scratch_pool, to, old_url + from_len, (char *)NULL); 152251881Speter if (! svn_path_is_url(new_url)) 153251881Speter return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL, 154251881Speter _("Invalid relocation destination: '%s' " 155251881Speter "(not a URL)"), new_url); 156251881Speter 157251881Speter new_repos_root = url_remove_final_relpath(new_url, repos_relpath, 158251881Speter scratch_pool, scratch_pool); 159251881Speter if (!new_repos_root) 160251881Speter return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL, 161251881Speter _("Invalid relocation destination: '%s' " 162251881Speter "(does not point to target)" ), new_url); 163251881Speter 164251881Speter SVN_ERR(validator(validator_baton, uuid, new_url, new_repos_root, 165251881Speter scratch_pool)); 166251881Speter 167251881Speter return svn_error_trace(svn_wc__db_global_relocate(wc_ctx->db, local_abspath, 168251881Speter new_repos_root, 169251881Speter scratch_pool)); 170251881Speter} 171