1251881Speter/* 2251881Speter * util.c: general routines defying categorization; eventually I 3251881Speter * suspect they'll end up in libsvn_subr, but don't want to 4251881Speter * pollute that right now. Note that nothing in here is 5251881Speter * specific to working copies. 6251881Speter * 7251881Speter * ==================================================================== 8251881Speter * Licensed to the Apache Software Foundation (ASF) under one 9251881Speter * or more contributor license agreements. See the NOTICE file 10251881Speter * distributed with this work for additional information 11251881Speter * regarding copyright ownership. The ASF licenses this file 12251881Speter * to you under the Apache License, Version 2.0 (the 13251881Speter * "License"); you may not use this file except in compliance 14251881Speter * with the License. You may obtain a copy of the License at 15251881Speter * 16251881Speter * http://www.apache.org/licenses/LICENSE-2.0 17251881Speter * 18251881Speter * Unless required by applicable law or agreed to in writing, 19251881Speter * software distributed under the License is distributed on an 20251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21251881Speter * KIND, either express or implied. See the License for the 22251881Speter * specific language governing permissions and limitations 23251881Speter * under the License. 24251881Speter * ==================================================================== 25251881Speter */ 26251881Speter 27251881Speter#include <apr_pools.h> 28251881Speter#include <apr_file_io.h> 29251881Speter 30251881Speter#include "svn_io.h" 31251881Speter#include "svn_types.h" 32251881Speter#include "svn_error.h" 33251881Speter#include "svn_dirent_uri.h" 34251881Speter#include "svn_path.h" 35251881Speter#include "svn_props.h" 36251881Speter#include "svn_version.h" 37251881Speter 38251881Speter#include "wc.h" /* just for prototypes of things in this .c file */ 39251881Speter#include "entries.h" 40251881Speter#include "private/svn_wc_private.h" 41251881Speter 42251881Speter#include "svn_private_config.h" 43251881Speter 44251881Speter 45251881Spetersvn_error_t * 46251881Spetersvn_wc__ensure_directory(const char *path, 47251881Speter apr_pool_t *pool) 48251881Speter{ 49251881Speter svn_node_kind_t kind; 50251881Speter 51251881Speter SVN_ERR(svn_io_check_path(path, &kind, pool)); 52251881Speter 53251881Speter if (kind != svn_node_none && kind != svn_node_dir) 54251881Speter { 55251881Speter /* If got an error other than dir non-existence, then we can't 56251881Speter ensure this directory's existence, so just return the error. 57251881Speter Might happen if there's a file in the way, for example. */ 58251881Speter return svn_error_createf(APR_ENOTDIR, NULL, 59251881Speter _("'%s' is not a directory"), 60251881Speter svn_dirent_local_style(path, pool)); 61251881Speter } 62251881Speter else if (kind == svn_node_none) 63251881Speter { 64251881Speter /* The dir doesn't exist, and it's our job to change that. */ 65251881Speter SVN_ERR(svn_io_make_dir_recursively(path, pool)); 66251881Speter } 67251881Speter else /* No problem, the dir already existed, so just leave. */ 68251881Speter SVN_ERR_ASSERT(kind == svn_node_dir); 69251881Speter 70251881Speter return SVN_NO_ERROR; 71251881Speter} 72251881Speter 73251881Speter/* Return the library version number. */ 74251881Speterconst svn_version_t * 75251881Spetersvn_wc_version(void) 76251881Speter{ 77251881Speter SVN_VERSION_BODY; 78251881Speter} 79251881Speter 80251881Spetersvn_wc_notify_t * 81251881Spetersvn_wc_create_notify(const char *path, 82251881Speter svn_wc_notify_action_t action, 83251881Speter apr_pool_t *pool) 84251881Speter{ 85251881Speter svn_wc_notify_t *ret = apr_pcalloc(pool, sizeof(*ret)); 86251881Speter ret->path = path; 87251881Speter ret->action = action; 88251881Speter ret->kind = svn_node_unknown; 89251881Speter ret->content_state = ret->prop_state = svn_wc_notify_state_unknown; 90251881Speter ret->lock_state = svn_wc_notify_lock_state_unknown; 91251881Speter ret->revision = SVN_INVALID_REVNUM; 92251881Speter ret->old_revision = SVN_INVALID_REVNUM; 93251881Speter 94251881Speter return ret; 95251881Speter} 96251881Speter 97251881Spetersvn_wc_notify_t * 98251881Spetersvn_wc_create_notify_url(const char *url, 99251881Speter svn_wc_notify_action_t action, 100251881Speter apr_pool_t *pool) 101251881Speter{ 102251881Speter svn_wc_notify_t *ret = svn_wc_create_notify(".", action, pool); 103251881Speter ret->url = url; 104251881Speter 105251881Speter return ret; 106251881Speter} 107251881Speter 108251881Speter/* Pool cleanup function to clear an svn_error_t *. */ 109251881Speterstatic apr_status_t err_cleanup(void *data) 110251881Speter{ 111251881Speter svn_error_clear(data); 112251881Speter 113251881Speter return APR_SUCCESS; 114251881Speter} 115251881Speter 116251881Spetersvn_wc_notify_t * 117251881Spetersvn_wc_dup_notify(const svn_wc_notify_t *notify, 118251881Speter apr_pool_t *pool) 119251881Speter{ 120251881Speter svn_wc_notify_t *ret = apr_palloc(pool, sizeof(*ret)); 121251881Speter 122251881Speter *ret = *notify; 123251881Speter 124251881Speter if (ret->path) 125251881Speter ret->path = apr_pstrdup(pool, ret->path); 126251881Speter if (ret->mime_type) 127251881Speter ret->mime_type = apr_pstrdup(pool, ret->mime_type); 128251881Speter if (ret->lock) 129251881Speter ret->lock = svn_lock_dup(ret->lock, pool); 130251881Speter if (ret->err) 131251881Speter { 132251881Speter ret->err = svn_error_dup(ret->err); 133251881Speter apr_pool_cleanup_register(pool, ret->err, err_cleanup, 134251881Speter apr_pool_cleanup_null); 135251881Speter } 136251881Speter if (ret->changelist_name) 137251881Speter ret->changelist_name = apr_pstrdup(pool, ret->changelist_name); 138251881Speter if (ret->merge_range) 139251881Speter ret->merge_range = svn_merge_range_dup(ret->merge_range, pool); 140251881Speter if (ret->url) 141251881Speter ret->url = apr_pstrdup(pool, ret->url); 142251881Speter if (ret->path_prefix) 143251881Speter ret->path_prefix = apr_pstrdup(pool, ret->path_prefix); 144251881Speter if (ret->prop_name) 145251881Speter ret->prop_name = apr_pstrdup(pool, ret->prop_name); 146251881Speter if (ret->rev_props) 147251881Speter ret->rev_props = svn_prop_hash_dup(ret->rev_props, pool); 148251881Speter 149251881Speter return ret; 150251881Speter} 151251881Speter 152251881Spetersvn_error_t * 153251881Spetersvn_wc_external_item2_create(svn_wc_external_item2_t **item, 154251881Speter apr_pool_t *pool) 155251881Speter{ 156251881Speter *item = apr_pcalloc(pool, sizeof(svn_wc_external_item2_t)); 157251881Speter return SVN_NO_ERROR; 158251881Speter} 159251881Speter 160251881Speter 161251881Spetersvn_wc_external_item2_t * 162251881Spetersvn_wc_external_item2_dup(const svn_wc_external_item2_t *item, 163251881Speter apr_pool_t *pool) 164251881Speter{ 165251881Speter svn_wc_external_item2_t *new_item = apr_palloc(pool, sizeof(*new_item)); 166251881Speter 167251881Speter *new_item = *item; 168251881Speter 169251881Speter if (new_item->target_dir) 170251881Speter new_item->target_dir = apr_pstrdup(pool, new_item->target_dir); 171251881Speter 172251881Speter if (new_item->url) 173251881Speter new_item->url = apr_pstrdup(pool, new_item->url); 174251881Speter 175251881Speter return new_item; 176251881Speter} 177251881Speter 178251881Speter 179251881Spetersvn_boolean_t 180251881Spetersvn_wc_match_ignore_list(const char *str, const apr_array_header_t *list, 181251881Speter apr_pool_t *pool) 182251881Speter{ 183251881Speter /* For now, we simply forward to svn_cstring_match_glob_list. In the 184251881Speter future, if we support more complex ignore patterns, we would iterate 185251881Speter over 'list' ourselves, and decide for each pattern how to handle 186251881Speter it. */ 187251881Speter 188251881Speter return svn_cstring_match_glob_list(str, list); 189251881Speter} 190251881Speter 191251881Spetersvn_wc_conflict_description2_t * 192251881Spetersvn_wc_conflict_description_create_text2(const char *local_abspath, 193251881Speter apr_pool_t *result_pool) 194251881Speter{ 195251881Speter svn_wc_conflict_description2_t *conflict; 196251881Speter 197251881Speter SVN_ERR_ASSERT_NO_RETURN(svn_dirent_is_absolute(local_abspath)); 198251881Speter 199251881Speter conflict = apr_pcalloc(result_pool, sizeof(*conflict)); 200251881Speter conflict->local_abspath = apr_pstrdup(result_pool, local_abspath); 201251881Speter conflict->node_kind = svn_node_file; 202251881Speter conflict->kind = svn_wc_conflict_kind_text; 203251881Speter conflict->action = svn_wc_conflict_action_edit; 204251881Speter conflict->reason = svn_wc_conflict_reason_edited; 205251881Speter return conflict; 206251881Speter} 207251881Speter 208251881Spetersvn_wc_conflict_description2_t * 209251881Spetersvn_wc_conflict_description_create_prop2(const char *local_abspath, 210251881Speter svn_node_kind_t node_kind, 211251881Speter const char *property_name, 212251881Speter apr_pool_t *result_pool) 213251881Speter{ 214251881Speter svn_wc_conflict_description2_t *conflict; 215251881Speter 216251881Speter SVN_ERR_ASSERT_NO_RETURN(svn_dirent_is_absolute(local_abspath)); 217251881Speter 218251881Speter conflict = apr_pcalloc(result_pool, sizeof(*conflict)); 219251881Speter conflict->local_abspath = apr_pstrdup(result_pool, local_abspath); 220251881Speter conflict->node_kind = node_kind; 221251881Speter conflict->kind = svn_wc_conflict_kind_property; 222251881Speter conflict->property_name = apr_pstrdup(result_pool, property_name); 223251881Speter return conflict; 224251881Speter} 225251881Speter 226251881Spetersvn_wc_conflict_description2_t * 227251881Spetersvn_wc_conflict_description_create_tree2( 228251881Speter const char *local_abspath, 229251881Speter svn_node_kind_t node_kind, 230251881Speter svn_wc_operation_t operation, 231251881Speter const svn_wc_conflict_version_t *src_left_version, 232251881Speter const svn_wc_conflict_version_t *src_right_version, 233251881Speter apr_pool_t *result_pool) 234251881Speter{ 235251881Speter svn_wc_conflict_description2_t *conflict; 236251881Speter 237251881Speter SVN_ERR_ASSERT_NO_RETURN(svn_dirent_is_absolute(local_abspath)); 238251881Speter 239251881Speter conflict = apr_pcalloc(result_pool, sizeof(*conflict)); 240251881Speter conflict->local_abspath = apr_pstrdup(result_pool, local_abspath); 241251881Speter conflict->node_kind = node_kind; 242251881Speter conflict->kind = svn_wc_conflict_kind_tree; 243251881Speter conflict->operation = operation; 244251881Speter conflict->src_left_version = svn_wc_conflict_version_dup(src_left_version, 245251881Speter result_pool); 246251881Speter conflict->src_right_version = svn_wc_conflict_version_dup(src_right_version, 247251881Speter result_pool); 248251881Speter return conflict; 249251881Speter} 250251881Speter 251289180Spetersvn_wc_conflict_version_t * 252289180Spetersvn_wc_conflict_version_create2(const char *repos_url, 253289180Speter const char *repos_uuid, 254289180Speter const char *repos_relpath, 255289180Speter svn_revnum_t revision, 256289180Speter svn_node_kind_t kind, 257289180Speter apr_pool_t *result_pool) 258289180Speter{ 259289180Speter svn_wc_conflict_version_t *version; 260251881Speter 261289180Speter version = apr_pcalloc(result_pool, sizeof(*version)); 262289180Speter 263289180Speter SVN_ERR_ASSERT_NO_RETURN(svn_uri_is_canonical(repos_url, result_pool) 264289180Speter && svn_relpath_is_canonical(repos_relpath) 265289180Speter && SVN_IS_VALID_REVNUM(revision) 266289180Speter /* ### repos_uuid can be NULL :( */); 267289180Speter 268289180Speter version->repos_url = repos_url; 269289180Speter version->peg_rev = revision; 270289180Speter version->path_in_repos = repos_relpath; 271289180Speter version->node_kind = kind; 272289180Speter version->repos_uuid = repos_uuid; 273289180Speter 274289180Speter return version; 275289180Speter} 276289180Speter 277251881Spetersvn_wc_conflict_description2_t * 278289180Spetersvn_wc_conflict_description2_dup(const svn_wc_conflict_description2_t *conflict, 279251881Speter apr_pool_t *pool) 280251881Speter{ 281251881Speter svn_wc_conflict_description2_t *new_conflict; 282251881Speter 283251881Speter new_conflict = apr_pcalloc(pool, sizeof(*new_conflict)); 284251881Speter 285251881Speter /* Shallow copy all members. */ 286251881Speter *new_conflict = *conflict; 287251881Speter 288251881Speter if (conflict->local_abspath) 289251881Speter new_conflict->local_abspath = apr_pstrdup(pool, conflict->local_abspath); 290251881Speter if (conflict->property_name) 291251881Speter new_conflict->property_name = apr_pstrdup(pool, conflict->property_name); 292251881Speter if (conflict->mime_type) 293251881Speter new_conflict->mime_type = apr_pstrdup(pool, conflict->mime_type); 294251881Speter if (conflict->base_abspath) 295251881Speter new_conflict->base_abspath = apr_pstrdup(pool, conflict->base_abspath); 296251881Speter if (conflict->their_abspath) 297251881Speter new_conflict->their_abspath = apr_pstrdup(pool, conflict->their_abspath); 298251881Speter if (conflict->my_abspath) 299251881Speter new_conflict->my_abspath = apr_pstrdup(pool, conflict->my_abspath); 300251881Speter if (conflict->merged_file) 301251881Speter new_conflict->merged_file = apr_pstrdup(pool, conflict->merged_file); 302251881Speter if (conflict->src_left_version) 303251881Speter new_conflict->src_left_version = 304251881Speter svn_wc_conflict_version_dup(conflict->src_left_version, pool); 305251881Speter if (conflict->src_right_version) 306251881Speter new_conflict->src_right_version = 307251881Speter svn_wc_conflict_version_dup(conflict->src_right_version, pool); 308251881Speter 309289180Speter /* ### For property conflicts, cd2 stores prop_reject_abspath in 310289180Speter * ### their_abspath, and stores theirs_abspath in merged_file. */ 311289180Speter if (conflict->prop_reject_abspath) 312289180Speter new_conflict->prop_reject_abspath = new_conflict->their_abspath; 313251881Speter 314289180Speter if (conflict->prop_value_base) 315289180Speter new_conflict->prop_value_base = 316289180Speter svn_string_dup(conflict->prop_value_base, pool); 317289180Speter if (conflict->prop_value_working) 318289180Speter new_conflict->prop_value_working = 319289180Speter svn_string_dup(conflict->prop_value_working, pool); 320289180Speter if (conflict->prop_value_incoming_old) 321289180Speter new_conflict->prop_value_incoming_old = 322289180Speter svn_string_dup(conflict->prop_value_incoming_old, pool); 323289180Speter if (conflict->prop_value_incoming_new) 324289180Speter new_conflict->prop_value_incoming_new = 325289180Speter svn_string_dup(conflict->prop_value_incoming_new, pool); 326251881Speter 327289180Speter return new_conflict; 328251881Speter} 329251881Speter 330251881Spetersvn_wc_conflict_version_t * 331251881Spetersvn_wc_conflict_version_dup(const svn_wc_conflict_version_t *version, 332251881Speter apr_pool_t *result_pool) 333251881Speter{ 334251881Speter 335251881Speter svn_wc_conflict_version_t *new_version; 336251881Speter 337251881Speter if (version == NULL) 338251881Speter return NULL; 339251881Speter 340251881Speter new_version = apr_pcalloc(result_pool, sizeof(*new_version)); 341251881Speter 342251881Speter /* Shallow copy all members. */ 343251881Speter *new_version = *version; 344251881Speter 345251881Speter if (version->repos_url) 346251881Speter new_version->repos_url = apr_pstrdup(result_pool, version->repos_url); 347251881Speter 348251881Speter if (version->path_in_repos) 349251881Speter new_version->path_in_repos = apr_pstrdup(result_pool, 350251881Speter version->path_in_repos); 351251881Speter 352251881Speter if (version->repos_uuid) 353251881Speter new_version->repos_uuid = apr_pstrdup(result_pool, version->repos_uuid); 354251881Speter 355251881Speter return new_version; 356251881Speter} 357251881Speter 358251881Spetersvn_wc_conflict_description_t * 359251881Spetersvn_wc__cd2_to_cd(const svn_wc_conflict_description2_t *conflict, 360251881Speter apr_pool_t *result_pool) 361251881Speter{ 362251881Speter svn_wc_conflict_description_t *new_conflict; 363251881Speter 364251881Speter if (conflict == NULL) 365251881Speter return NULL; 366251881Speter 367251881Speter new_conflict = apr_pcalloc(result_pool, sizeof(*new_conflict)); 368251881Speter 369251881Speter new_conflict->path = apr_pstrdup(result_pool, conflict->local_abspath); 370251881Speter new_conflict->node_kind = conflict->node_kind; 371251881Speter new_conflict->kind = conflict->kind; 372251881Speter new_conflict->action = conflict->action; 373251881Speter new_conflict->reason = conflict->reason; 374251881Speter if (conflict->src_left_version) 375251881Speter new_conflict->src_left_version = 376251881Speter svn_wc_conflict_version_dup(conflict->src_left_version, result_pool); 377251881Speter if (conflict->src_right_version) 378251881Speter new_conflict->src_right_version = 379251881Speter svn_wc_conflict_version_dup(conflict->src_right_version, result_pool); 380251881Speter 381251881Speter switch (conflict->kind) 382251881Speter { 383251881Speter 384251881Speter case svn_wc_conflict_kind_property: 385251881Speter new_conflict->property_name = apr_pstrdup(result_pool, 386251881Speter conflict->property_name); 387251881Speter /* Falling through. */ 388251881Speter 389251881Speter case svn_wc_conflict_kind_text: 390251881Speter new_conflict->is_binary = conflict->is_binary; 391251881Speter if (conflict->mime_type) 392251881Speter new_conflict->mime_type = apr_pstrdup(result_pool, 393251881Speter conflict->mime_type); 394251881Speter if (conflict->base_abspath) 395251881Speter new_conflict->base_file = apr_pstrdup(result_pool, 396251881Speter conflict->base_abspath); 397251881Speter if (conflict->their_abspath) 398251881Speter new_conflict->their_file = apr_pstrdup(result_pool, 399251881Speter conflict->their_abspath); 400251881Speter if (conflict->my_abspath) 401251881Speter new_conflict->my_file = apr_pstrdup(result_pool, 402251881Speter conflict->my_abspath); 403251881Speter if (conflict->merged_file) 404251881Speter new_conflict->merged_file = apr_pstrdup(result_pool, 405251881Speter conflict->merged_file); 406251881Speter break; 407251881Speter 408251881Speter case svn_wc_conflict_kind_tree: 409251881Speter new_conflict->operation = conflict->operation; 410251881Speter break; 411251881Speter } 412251881Speter 413251881Speter /* A NULL access baton is allowable by the API. */ 414251881Speter new_conflict->access = NULL; 415251881Speter 416251881Speter return new_conflict; 417251881Speter} 418251881Speter 419251881Speter 420251881Spetersvn_error_t * 421251881Spetersvn_wc__fetch_kind_func(svn_node_kind_t *kind, 422251881Speter void *baton, 423251881Speter const char *path, 424251881Speter svn_revnum_t base_revision, 425251881Speter apr_pool_t *scratch_pool) 426251881Speter{ 427251881Speter struct svn_wc__shim_fetch_baton_t *sfb = baton; 428251881Speter const char *local_abspath = svn_dirent_join(sfb->base_abspath, path, 429251881Speter scratch_pool); 430251881Speter 431251881Speter SVN_ERR(svn_wc__db_read_kind(kind, sfb->db, local_abspath, 432251881Speter FALSE /* allow_missing */, 433251881Speter TRUE /* show_deleted */, 434251881Speter FALSE /* show_hidden */, 435251881Speter scratch_pool)); 436251881Speter 437251881Speter return SVN_NO_ERROR; 438251881Speter} 439251881Speter 440251881Speter 441251881Spetersvn_error_t * 442251881Spetersvn_wc__fetch_props_func(apr_hash_t **props, 443251881Speter void *baton, 444251881Speter const char *path, 445251881Speter svn_revnum_t base_revision, 446251881Speter apr_pool_t *result_pool, 447251881Speter apr_pool_t *scratch_pool) 448251881Speter{ 449251881Speter struct svn_wc__shim_fetch_baton_t *sfb = baton; 450251881Speter const char *local_abspath = svn_dirent_join(sfb->base_abspath, path, 451251881Speter scratch_pool); 452251881Speter svn_error_t *err; 453251881Speter 454251881Speter if (sfb->fetch_base) 455251881Speter err = svn_wc__db_base_get_props(props, sfb->db, local_abspath, result_pool, 456251881Speter scratch_pool); 457251881Speter else 458251881Speter err = svn_wc__db_read_props(props, sfb->db, local_abspath, 459251881Speter result_pool, scratch_pool); 460251881Speter 461251881Speter /* If the path doesn't exist, just return an empty set of props. */ 462251881Speter if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 463251881Speter { 464251881Speter svn_error_clear(err); 465251881Speter *props = apr_hash_make(result_pool); 466251881Speter } 467251881Speter else if (err) 468251881Speter return svn_error_trace(err); 469251881Speter 470251881Speter return SVN_NO_ERROR; 471251881Speter} 472251881Speter 473251881Speter 474251881Spetersvn_error_t * 475251881Spetersvn_wc__fetch_base_func(const char **filename, 476251881Speter void *baton, 477251881Speter const char *path, 478251881Speter svn_revnum_t base_revision, 479251881Speter apr_pool_t *result_pool, 480251881Speter apr_pool_t *scratch_pool) 481251881Speter{ 482251881Speter struct svn_wc__shim_fetch_baton_t *sfb = baton; 483251881Speter const svn_checksum_t *checksum; 484251881Speter svn_error_t *err; 485251881Speter const char *local_abspath = svn_dirent_join(sfb->base_abspath, path, 486251881Speter scratch_pool); 487251881Speter 488251881Speter err = svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL, 489251881Speter NULL, NULL, NULL, NULL, &checksum, 490251881Speter NULL, NULL, NULL, NULL, NULL, 491251881Speter sfb->db, local_abspath, 492251881Speter scratch_pool, scratch_pool); 493251881Speter if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 494251881Speter { 495251881Speter svn_error_clear(err); 496251881Speter *filename = NULL; 497251881Speter return SVN_NO_ERROR; 498251881Speter } 499251881Speter else if (err) 500251881Speter return svn_error_trace(err); 501251881Speter 502251881Speter if (checksum == NULL) 503251881Speter { 504251881Speter *filename = NULL; 505251881Speter return SVN_NO_ERROR; 506251881Speter } 507251881Speter 508251881Speter SVN_ERR(svn_wc__db_pristine_get_path(filename, sfb->db, local_abspath, 509251881Speter checksum, scratch_pool, scratch_pool)); 510251881Speter 511251881Speter return SVN_NO_ERROR; 512251881Speter} 513