1251881Speter/* 2251881Speter * node.c: routines for getting information about nodes in the working copy. 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/* A note about these functions: 25251881Speter 26251881Speter We aren't really sure yet which bits of data libsvn_client needs about 27251881Speter nodes. In wc-1, we just grab the entry, and then use whatever we want 28251881Speter from it. Such a pattern is Bad. 29251881Speter 30251881Speter This file is intended to hold functions which retrieve specific bits of 31251881Speter information about a node, and will hopefully give us a better idea about 32251881Speter what data libsvn_client needs, and how to best provide that data in 1.7 33251881Speter final. As such, these functions should only be called from outside 34251881Speter libsvn_wc; any internal callers are encouraged to use the appropriate 35251881Speter information fetching function, such as svn_wc__db_read_info(). 36251881Speter*/ 37251881Speter 38251881Speter#include <apr_pools.h> 39251881Speter#include <apr_time.h> 40251881Speter 41251881Speter#include "svn_pools.h" 42251881Speter#include "svn_dirent_uri.h" 43251881Speter#include "svn_path.h" 44251881Speter#include "svn_hash.h" 45251881Speter#include "svn_types.h" 46251881Speter 47251881Speter#include "wc.h" 48251881Speter#include "props.h" 49251881Speter#include "entries.h" 50251881Speter#include "wc_db.h" 51251881Speter 52251881Speter#include "svn_private_config.h" 53251881Speter#include "private/svn_wc_private.h" 54251881Speter 55251881Speter 56251881Speter/* Set *CHILDREN_ABSPATHS to a new array of the full paths formed by joining 57251881Speter * each name in REL_CHILDREN onto DIR_ABSPATH. If SHOW_HIDDEN is false then 58251881Speter * omit any paths that are reported as 'hidden' by svn_wc__db_node_hidden(). 59251881Speter * 60251881Speter * Allocate the output array and its elements in RESULT_POOL. */ 61251881Speterstatic svn_error_t * 62251881Speterfilter_and_make_absolute(const apr_array_header_t **children_abspaths, 63251881Speter svn_wc_context_t *wc_ctx, 64251881Speter const char *dir_abspath, 65251881Speter const apr_array_header_t *rel_children, 66251881Speter svn_boolean_t show_hidden, 67251881Speter apr_pool_t *result_pool, 68251881Speter apr_pool_t *scratch_pool) 69251881Speter{ 70251881Speter apr_array_header_t *children; 71251881Speter int i; 72251881Speter 73251881Speter children = apr_array_make(result_pool, rel_children->nelts, 74251881Speter sizeof(const char *)); 75251881Speter for (i = 0; i < rel_children->nelts; i++) 76251881Speter { 77251881Speter const char *child_abspath = svn_dirent_join(dir_abspath, 78251881Speter APR_ARRAY_IDX(rel_children, 79251881Speter i, 80251881Speter const char *), 81251881Speter result_pool); 82251881Speter 83251881Speter /* Don't add hidden nodes to *CHILDREN if we don't want them. */ 84251881Speter if (!show_hidden) 85251881Speter { 86251881Speter svn_boolean_t child_is_hidden; 87251881Speter 88251881Speter SVN_ERR(svn_wc__db_node_hidden(&child_is_hidden, wc_ctx->db, 89251881Speter child_abspath, scratch_pool)); 90251881Speter if (child_is_hidden) 91251881Speter continue; 92251881Speter } 93251881Speter 94251881Speter APR_ARRAY_PUSH(children, const char *) = child_abspath; 95251881Speter } 96251881Speter 97251881Speter *children_abspaths = children; 98251881Speter 99251881Speter return SVN_NO_ERROR; 100251881Speter} 101251881Speter 102251881Speter 103251881Spetersvn_error_t * 104251881Spetersvn_wc__node_get_children_of_working_node(const apr_array_header_t **children, 105251881Speter svn_wc_context_t *wc_ctx, 106251881Speter const char *dir_abspath, 107251881Speter svn_boolean_t show_hidden, 108251881Speter apr_pool_t *result_pool, 109251881Speter apr_pool_t *scratch_pool) 110251881Speter{ 111251881Speter const apr_array_header_t *rel_children; 112251881Speter 113251881Speter SVN_ERR(svn_wc__db_read_children_of_working_node(&rel_children, 114251881Speter wc_ctx->db, dir_abspath, 115251881Speter scratch_pool, scratch_pool)); 116251881Speter SVN_ERR(filter_and_make_absolute(children, wc_ctx, dir_abspath, 117251881Speter rel_children, show_hidden, 118251881Speter result_pool, scratch_pool)); 119251881Speter return SVN_NO_ERROR; 120251881Speter} 121251881Speter 122251881Spetersvn_error_t * 123251881Spetersvn_wc__node_get_children(const apr_array_header_t **children, 124251881Speter svn_wc_context_t *wc_ctx, 125251881Speter const char *dir_abspath, 126251881Speter svn_boolean_t show_hidden, 127251881Speter apr_pool_t *result_pool, 128251881Speter apr_pool_t *scratch_pool) 129251881Speter{ 130251881Speter const apr_array_header_t *rel_children; 131251881Speter 132251881Speter SVN_ERR(svn_wc__db_read_children(&rel_children, wc_ctx->db, dir_abspath, 133251881Speter scratch_pool, scratch_pool)); 134251881Speter SVN_ERR(filter_and_make_absolute(children, wc_ctx, dir_abspath, 135251881Speter rel_children, show_hidden, 136251881Speter result_pool, scratch_pool)); 137251881Speter return SVN_NO_ERROR; 138251881Speter} 139251881Speter 140251881Speter 141251881Spetersvn_error_t * 142251881Spetersvn_wc__internal_get_repos_info(svn_revnum_t *revision, 143251881Speter const char **repos_relpath, 144251881Speter const char **repos_root_url, 145251881Speter const char **repos_uuid, 146251881Speter svn_wc__db_t *db, 147251881Speter const char *local_abspath, 148251881Speter apr_pool_t *result_pool, 149251881Speter apr_pool_t *scratch_pool) 150251881Speter{ 151251881Speter svn_wc__db_status_t status; 152251881Speter svn_boolean_t have_work; 153251881Speter 154251881Speter SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, repos_relpath, 155251881Speter repos_root_url, repos_uuid, 156251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 157251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 158251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 159251881Speter NULL, NULL, &have_work, 160251881Speter db, local_abspath, 161251881Speter result_pool, scratch_pool)); 162251881Speter 163251881Speter if ((repos_relpath ? *repos_relpath != NULL : TRUE) 164251881Speter && (repos_root_url ? *repos_root_url != NULL: TRUE) 165251881Speter && (repos_uuid ? *repos_uuid != NULL : TRUE)) 166251881Speter return SVN_NO_ERROR; /* We got the requested information */ 167251881Speter 168251881Speter if (!have_work) /* not-present, (server-)excluded? */ 169251881Speter { 170251881Speter return SVN_NO_ERROR; /* Can't fetch more */ 171251881Speter } 172251881Speter 173251881Speter if (status == svn_wc__db_status_deleted) 174251881Speter { 175251881Speter const char *base_del_abspath, *wrk_del_abspath; 176251881Speter 177251881Speter SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL, 178251881Speter &wrk_del_abspath, NULL, 179251881Speter db, local_abspath, 180251881Speter scratch_pool, scratch_pool)); 181251881Speter 182251881Speter if (base_del_abspath) 183251881Speter { 184251881Speter SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, repos_relpath, 185251881Speter repos_root_url, repos_uuid, NULL, 186251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 187251881Speter NULL, NULL, NULL, 188251881Speter db, base_del_abspath, 189251881Speter result_pool, scratch_pool)); 190251881Speter 191251881Speter /* If we have a repos_relpath, it is of the op-root */ 192251881Speter if (repos_relpath) 193251881Speter *repos_relpath = svn_relpath_join(*repos_relpath, 194251881Speter svn_dirent_skip_ancestor(base_del_abspath, 195251881Speter local_abspath), 196251881Speter result_pool); 197251881Speter /* We keep revision as SVN_INVALID_REVNUM */ 198251881Speter } 199251881Speter else if (wrk_del_abspath) 200251881Speter { 201251881Speter const char *op_root_abspath = NULL; 202251881Speter 203251881Speter SVN_ERR(svn_wc__db_scan_addition(NULL, repos_relpath 204251881Speter ? &op_root_abspath : NULL, 205251881Speter repos_relpath, repos_root_url, 206251881Speter repos_uuid, NULL, NULL, NULL, NULL, 207251881Speter db, svn_dirent_dirname( 208251881Speter wrk_del_abspath, 209251881Speter scratch_pool), 210251881Speter result_pool, scratch_pool)); 211251881Speter 212251881Speter /* If we have a repos_relpath, it is of the op-root */ 213251881Speter if (repos_relpath) 214251881Speter *repos_relpath = svn_relpath_join( 215251881Speter *repos_relpath, 216251881Speter svn_dirent_skip_ancestor(op_root_abspath, 217251881Speter local_abspath), 218251881Speter result_pool); 219251881Speter } 220251881Speter } 221251881Speter else /* added, or WORKING incomplete */ 222251881Speter { 223251881Speter const char *op_root_abspath = NULL; 224251881Speter 225251881Speter /* We have an addition. scan_addition() will find the intended 226251881Speter repository location by scanning up the tree. */ 227251881Speter SVN_ERR(svn_wc__db_scan_addition(NULL, repos_relpath 228251881Speter ? &op_root_abspath : NULL, 229251881Speter repos_relpath, repos_root_url, 230251881Speter repos_uuid, NULL, NULL, NULL, NULL, 231251881Speter db, local_abspath, 232251881Speter result_pool, scratch_pool)); 233251881Speter } 234251881Speter 235251881Speter SVN_ERR_ASSERT(repos_root_url == NULL || *repos_root_url != NULL); 236251881Speter SVN_ERR_ASSERT(repos_uuid == NULL || *repos_uuid != NULL); 237251881Speter return SVN_NO_ERROR; 238251881Speter} 239251881Speter 240251881Spetersvn_error_t * 241251881Spetersvn_wc__node_get_repos_info(svn_revnum_t *revision, 242251881Speter const char **repos_relpath, 243251881Speter const char **repos_root_url, 244251881Speter const char **repos_uuid, 245251881Speter svn_wc_context_t *wc_ctx, 246251881Speter const char *local_abspath, 247251881Speter apr_pool_t *result_pool, 248251881Speter apr_pool_t *scratch_pool) 249251881Speter{ 250251881Speter return svn_error_trace( 251251881Speter svn_wc__internal_get_repos_info(revision, 252251881Speter repos_relpath, 253251881Speter repos_root_url, 254251881Speter repos_uuid, 255251881Speter wc_ctx->db, local_abspath, 256251881Speter result_pool, scratch_pool)); 257251881Speter} 258251881Speter 259251881Speter/* Convert DB_KIND into the appropriate NODE_KIND value. 260251881Speter * If SHOW_HIDDEN is TRUE, report the node kind as found in the DB 261251881Speter * even if DB_STATUS indicates that the node is hidden. 262251881Speter * Else, return svn_node_none for such nodes. 263251881Speter * 264251881Speter * ### This is a bit ugly. We should consider promoting svn_kind_t 265251881Speter * ### to the de-facto node kind type instead of converting between them 266251881Speter * ### in non-backwards compat code. 267251881Speter * ### See also comments at the definition of svn_kind_t. 268251881Speter * 269251881Speter * ### In reality, the previous comment is out of date, as there is 270251881Speter * ### now only one enumeration for node kinds, and that is 271251881Speter * ### svn_node_kind_t (svn_kind_t was merged with that). But it's 272251881Speter * ### still ugly. 273251881Speter */ 274251881Speterstatic svn_error_t * 275251881Speterconvert_db_kind_to_node_kind(svn_node_kind_t *node_kind, 276251881Speter svn_node_kind_t db_kind, 277251881Speter svn_wc__db_status_t db_status, 278251881Speter svn_boolean_t show_hidden) 279251881Speter{ 280251881Speter *node_kind = db_kind; 281251881Speter 282251881Speter /* Make sure hidden nodes return svn_node_none. */ 283251881Speter if (! show_hidden) 284251881Speter switch (db_status) 285251881Speter { 286251881Speter case svn_wc__db_status_not_present: 287251881Speter case svn_wc__db_status_server_excluded: 288251881Speter case svn_wc__db_status_excluded: 289251881Speter *node_kind = svn_node_none; 290251881Speter 291251881Speter default: 292251881Speter break; 293251881Speter } 294251881Speter 295251881Speter return SVN_NO_ERROR; 296251881Speter} 297251881Speter 298251881Spetersvn_error_t * 299251881Spetersvn_wc_read_kind2(svn_node_kind_t *kind, 300251881Speter svn_wc_context_t *wc_ctx, 301251881Speter const char *local_abspath, 302251881Speter svn_boolean_t show_deleted, 303251881Speter svn_boolean_t show_hidden, 304251881Speter apr_pool_t *scratch_pool) 305251881Speter{ 306251881Speter svn_node_kind_t db_kind; 307251881Speter 308251881Speter SVN_ERR(svn_wc__db_read_kind(&db_kind, 309251881Speter wc_ctx->db, local_abspath, 310251881Speter TRUE, 311251881Speter show_deleted, 312251881Speter show_hidden, 313251881Speter scratch_pool)); 314251881Speter 315251881Speter if (db_kind == svn_node_dir) 316251881Speter *kind = svn_node_dir; 317251881Speter else if (db_kind == svn_node_file || db_kind == svn_node_symlink) 318251881Speter *kind = svn_node_file; 319251881Speter else 320251881Speter *kind = svn_node_none; 321251881Speter 322251881Speter return SVN_NO_ERROR; 323251881Speter} 324251881Speter 325251881Spetersvn_error_t * 326251881Spetersvn_wc__node_get_depth(svn_depth_t *depth, 327251881Speter svn_wc_context_t *wc_ctx, 328251881Speter const char *local_abspath, 329251881Speter apr_pool_t *scratch_pool) 330251881Speter{ 331251881Speter return svn_error_trace( 332251881Speter svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL, 333251881Speter NULL, NULL, depth, NULL, NULL, NULL, NULL, 334251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 335251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 336251881Speter wc_ctx->db, local_abspath, scratch_pool, 337251881Speter scratch_pool)); 338251881Speter} 339251881Speter 340251881Spetersvn_error_t * 341251881Spetersvn_wc__node_get_changed_info(svn_revnum_t *changed_rev, 342251881Speter apr_time_t *changed_date, 343251881Speter const char **changed_author, 344251881Speter svn_wc_context_t *wc_ctx, 345251881Speter const char *local_abspath, 346251881Speter apr_pool_t *result_pool, 347251881Speter apr_pool_t *scratch_pool) 348251881Speter{ 349251881Speter return svn_error_trace( 350251881Speter svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, changed_rev, 351251881Speter changed_date, changed_author, NULL, NULL, NULL, 352251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 353251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 354251881Speter wc_ctx->db, local_abspath, result_pool, 355251881Speter scratch_pool)); 356251881Speter} 357251881Speter 358251881Spetersvn_error_t * 359251881Spetersvn_wc__node_get_url(const char **url, 360251881Speter svn_wc_context_t *wc_ctx, 361251881Speter const char *local_abspath, 362251881Speter apr_pool_t *result_pool, 363251881Speter apr_pool_t *scratch_pool) 364251881Speter{ 365251881Speter return svn_error_trace(svn_wc__db_read_url(url, wc_ctx->db, local_abspath, 366251881Speter result_pool, scratch_pool)); 367251881Speter} 368251881Speter 369251881Speter/* A recursive node-walker, helper for svn_wc__internal_walk_children(). 370251881Speter * 371251881Speter * Call WALK_CALLBACK with WALK_BATON on all children (recursively) of 372251881Speter * DIR_ABSPATH in DB, but not on DIR_ABSPATH itself. DIR_ABSPATH must be a 373251881Speter * versioned directory. If SHOW_HIDDEN is true, visit hidden nodes, else 374251881Speter * ignore them. Restrict the depth of the walk to DEPTH. 375251881Speter * 376251881Speter * ### Is it possible for a subdirectory to be hidden and known to be a 377251881Speter * directory? If so, and if show_hidden is true, this will try to 378251881Speter * recurse into it. */ 379251881Speterstatic svn_error_t * 380251881Speterwalker_helper(svn_wc__db_t *db, 381251881Speter const char *dir_abspath, 382251881Speter svn_boolean_t show_hidden, 383251881Speter const apr_hash_t *changelist_filter, 384251881Speter svn_wc__node_found_func_t walk_callback, 385251881Speter void *walk_baton, 386251881Speter svn_depth_t depth, 387251881Speter svn_cancel_func_t cancel_func, 388251881Speter void *cancel_baton, 389251881Speter apr_pool_t *scratch_pool) 390251881Speter{ 391251881Speter apr_hash_t *rel_children_info; 392251881Speter apr_hash_index_t *hi; 393251881Speter apr_pool_t *iterpool; 394251881Speter 395251881Speter if (depth == svn_depth_empty) 396251881Speter return SVN_NO_ERROR; 397251881Speter 398251881Speter SVN_ERR(svn_wc__db_read_children_walker_info(&rel_children_info, db, 399251881Speter dir_abspath, scratch_pool, 400251881Speter scratch_pool)); 401251881Speter 402251881Speter 403251881Speter iterpool = svn_pool_create(scratch_pool); 404251881Speter for (hi = apr_hash_first(scratch_pool, rel_children_info); 405251881Speter hi; 406251881Speter hi = apr_hash_next(hi)) 407251881Speter { 408251881Speter const char *child_name = svn__apr_hash_index_key(hi); 409251881Speter struct svn_wc__db_walker_info_t *wi = svn__apr_hash_index_val(hi); 410251881Speter svn_node_kind_t child_kind = wi->kind; 411251881Speter svn_wc__db_status_t child_status = wi->status; 412251881Speter const char *child_abspath; 413251881Speter 414251881Speter svn_pool_clear(iterpool); 415251881Speter 416251881Speter /* See if someone wants to cancel this operation. */ 417251881Speter if (cancel_func) 418251881Speter SVN_ERR(cancel_func(cancel_baton)); 419251881Speter 420251881Speter child_abspath = svn_dirent_join(dir_abspath, child_name, iterpool); 421251881Speter 422251881Speter if (!show_hidden) 423251881Speter switch (child_status) 424251881Speter { 425251881Speter case svn_wc__db_status_not_present: 426251881Speter case svn_wc__db_status_server_excluded: 427251881Speter case svn_wc__db_status_excluded: 428251881Speter continue; 429251881Speter default: 430251881Speter break; 431251881Speter } 432251881Speter 433251881Speter /* Return the child, if appropriate. */ 434251881Speter if ( (child_kind == svn_node_file 435251881Speter || depth >= svn_depth_immediates) 436251881Speter && svn_wc__internal_changelist_match(db, child_abspath, 437251881Speter changelist_filter, 438251881Speter scratch_pool) ) 439251881Speter { 440251881Speter svn_node_kind_t kind; 441251881Speter 442251881Speter SVN_ERR(convert_db_kind_to_node_kind(&kind, child_kind, 443251881Speter child_status, show_hidden)); 444251881Speter /* ### We might want to pass child_status as well because at least 445251881Speter * ### one callee is asking for it. 446251881Speter * ### But is it OK to use an svn_wc__db type in this API? 447251881Speter * ### Not yet, we need to get the node walker 448251881Speter * ### libsvn_wc-internal first. -hkw */ 449251881Speter SVN_ERR(walk_callback(child_abspath, kind, walk_baton, iterpool)); 450251881Speter } 451251881Speter 452251881Speter /* Recurse into this directory, if appropriate. */ 453251881Speter if (child_kind == svn_node_dir 454251881Speter && depth >= svn_depth_immediates) 455251881Speter { 456251881Speter svn_depth_t depth_below_here = depth; 457251881Speter 458251881Speter if (depth == svn_depth_immediates) 459251881Speter depth_below_here = svn_depth_empty; 460251881Speter 461251881Speter SVN_ERR(walker_helper(db, child_abspath, show_hidden, 462251881Speter changelist_filter, 463251881Speter walk_callback, walk_baton, 464251881Speter depth_below_here, 465251881Speter cancel_func, cancel_baton, 466251881Speter iterpool)); 467251881Speter } 468251881Speter } 469251881Speter 470251881Speter svn_pool_destroy(iterpool); 471251881Speter 472251881Speter return SVN_NO_ERROR; 473251881Speter} 474251881Speter 475251881Speter 476251881Spetersvn_error_t * 477251881Spetersvn_wc__internal_walk_children(svn_wc__db_t *db, 478251881Speter const char *local_abspath, 479251881Speter svn_boolean_t show_hidden, 480251881Speter const apr_array_header_t *changelist_filter, 481251881Speter svn_wc__node_found_func_t walk_callback, 482251881Speter void *walk_baton, 483251881Speter svn_depth_t walk_depth, 484251881Speter svn_cancel_func_t cancel_func, 485251881Speter void *cancel_baton, 486251881Speter apr_pool_t *scratch_pool) 487251881Speter{ 488251881Speter svn_node_kind_t db_kind; 489251881Speter svn_node_kind_t kind; 490251881Speter svn_wc__db_status_t status; 491251881Speter apr_hash_t *changelist_hash = NULL; 492251881Speter 493251881Speter SVN_ERR_ASSERT(walk_depth >= svn_depth_empty 494251881Speter && walk_depth <= svn_depth_infinity); 495251881Speter 496251881Speter if (changelist_filter && changelist_filter->nelts) 497251881Speter SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter, 498251881Speter scratch_pool)); 499251881Speter 500251881Speter /* Check if the node exists before the first callback */ 501251881Speter SVN_ERR(svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL, 502251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 503251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 504251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 505251881Speter db, local_abspath, scratch_pool, scratch_pool)); 506251881Speter 507251881Speter SVN_ERR(convert_db_kind_to_node_kind(&kind, db_kind, status, show_hidden)); 508251881Speter 509251881Speter if (svn_wc__internal_changelist_match(db, local_abspath, 510251881Speter changelist_hash, scratch_pool)) 511251881Speter SVN_ERR(walk_callback(local_abspath, kind, walk_baton, scratch_pool)); 512251881Speter 513251881Speter if (db_kind == svn_node_file 514251881Speter || status == svn_wc__db_status_not_present 515251881Speter || status == svn_wc__db_status_excluded 516251881Speter || status == svn_wc__db_status_server_excluded) 517251881Speter return SVN_NO_ERROR; 518251881Speter 519251881Speter if (db_kind == svn_node_dir) 520251881Speter { 521251881Speter return svn_error_trace( 522251881Speter walker_helper(db, local_abspath, show_hidden, changelist_hash, 523251881Speter walk_callback, walk_baton, 524251881Speter walk_depth, cancel_func, cancel_baton, scratch_pool)); 525251881Speter } 526251881Speter 527251881Speter return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL, 528251881Speter _("'%s' has an unrecognized node kind"), 529251881Speter svn_dirent_local_style(local_abspath, 530251881Speter scratch_pool)); 531251881Speter} 532251881Speter 533251881Spetersvn_error_t * 534251881Spetersvn_wc__node_is_status_deleted(svn_boolean_t *is_deleted, 535251881Speter svn_wc_context_t *wc_ctx, 536251881Speter const char *local_abspath, 537251881Speter apr_pool_t *scratch_pool) 538251881Speter{ 539251881Speter svn_wc__db_status_t status; 540251881Speter 541251881Speter SVN_ERR(svn_wc__db_read_info(&status, 542251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 543251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 544251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 545251881Speter NULL, NULL, NULL, NULL, NULL, 546251881Speter wc_ctx->db, local_abspath, 547251881Speter scratch_pool, scratch_pool)); 548251881Speter 549251881Speter *is_deleted = (status == svn_wc__db_status_deleted); 550251881Speter 551251881Speter return SVN_NO_ERROR; 552251881Speter} 553251881Speter 554251881Spetersvn_error_t * 555251881Spetersvn_wc__node_get_deleted_ancestor(const char **deleted_ancestor_abspath, 556251881Speter svn_wc_context_t *wc_ctx, 557251881Speter const char *local_abspath, 558251881Speter apr_pool_t *result_pool, 559251881Speter apr_pool_t *scratch_pool) 560251881Speter{ 561251881Speter svn_wc__db_status_t status; 562251881Speter 563251881Speter *deleted_ancestor_abspath = NULL; 564251881Speter 565251881Speter SVN_ERR(svn_wc__db_read_info(&status, 566251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 567251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 568251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 569251881Speter NULL, NULL, NULL, NULL, NULL, 570251881Speter wc_ctx->db, local_abspath, 571251881Speter scratch_pool, scratch_pool)); 572251881Speter 573251881Speter if (status == svn_wc__db_status_deleted) 574251881Speter SVN_ERR(svn_wc__db_scan_deletion(deleted_ancestor_abspath, NULL, NULL, 575251881Speter NULL, wc_ctx->db, local_abspath, 576251881Speter result_pool, scratch_pool)); 577251881Speter 578251881Speter return SVN_NO_ERROR; 579251881Speter} 580251881Speter 581251881Spetersvn_error_t * 582251881Spetersvn_wc__node_is_not_present(svn_boolean_t *is_not_present, 583251881Speter svn_boolean_t *is_excluded, 584251881Speter svn_boolean_t *is_server_excluded, 585251881Speter svn_wc_context_t *wc_ctx, 586251881Speter const char *local_abspath, 587251881Speter svn_boolean_t base_only, 588251881Speter apr_pool_t *scratch_pool) 589251881Speter{ 590251881Speter svn_wc__db_status_t status; 591251881Speter 592251881Speter if (base_only) 593251881Speter { 594251881Speter SVN_ERR(svn_wc__db_base_get_info(&status, 595251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 596251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 597251881Speter NULL, NULL, NULL, 598251881Speter wc_ctx->db, local_abspath, 599251881Speter scratch_pool, scratch_pool)); 600251881Speter } 601251881Speter else 602251881Speter { 603251881Speter SVN_ERR(svn_wc__db_read_info(&status, 604251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 605251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 606251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 607251881Speter NULL, NULL, NULL, NULL, NULL, 608251881Speter wc_ctx->db, local_abspath, 609251881Speter scratch_pool, scratch_pool)); 610251881Speter } 611251881Speter 612251881Speter if (is_not_present) 613251881Speter *is_not_present = (status == svn_wc__db_status_not_present); 614251881Speter 615251881Speter if (is_excluded) 616251881Speter *is_excluded = (status == svn_wc__db_status_excluded); 617251881Speter 618251881Speter if (is_server_excluded) 619251881Speter *is_server_excluded = (status == svn_wc__db_status_server_excluded); 620251881Speter 621251881Speter return SVN_NO_ERROR; 622251881Speter} 623251881Speter 624251881Spetersvn_error_t * 625251881Spetersvn_wc__node_is_added(svn_boolean_t *is_added, 626251881Speter svn_wc_context_t *wc_ctx, 627251881Speter const char *local_abspath, 628251881Speter apr_pool_t *scratch_pool) 629251881Speter{ 630251881Speter svn_wc__db_status_t status; 631251881Speter 632251881Speter SVN_ERR(svn_wc__db_read_info(&status, 633251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 634251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 635251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 636251881Speter NULL, NULL, NULL, NULL, NULL, 637251881Speter wc_ctx->db, local_abspath, 638251881Speter scratch_pool, scratch_pool)); 639251881Speter *is_added = (status == svn_wc__db_status_added); 640251881Speter 641251881Speter return SVN_NO_ERROR; 642251881Speter} 643251881Speter 644251881Spetersvn_error_t * 645251881Spetersvn_wc__node_has_working(svn_boolean_t *has_working, 646251881Speter svn_wc_context_t *wc_ctx, 647251881Speter const char *local_abspath, 648251881Speter apr_pool_t *scratch_pool) 649251881Speter{ 650251881Speter svn_wc__db_status_t status; 651251881Speter 652251881Speter SVN_ERR(svn_wc__db_read_info(&status, 653251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 654251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 655251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 656251881Speter NULL, NULL, NULL, NULL, has_working, 657251881Speter wc_ctx->db, local_abspath, 658251881Speter scratch_pool, scratch_pool)); 659251881Speter 660251881Speter return SVN_NO_ERROR; 661251881Speter} 662251881Speter 663251881Speter 664251881Spetersvn_error_t * 665251881Spetersvn_wc__node_get_base(svn_node_kind_t *kind, 666251881Speter svn_revnum_t *revision, 667251881Speter const char **repos_relpath, 668251881Speter const char **repos_root_url, 669251881Speter const char **repos_uuid, 670251881Speter const char **lock_token, 671251881Speter svn_wc_context_t *wc_ctx, 672251881Speter const char *local_abspath, 673251881Speter svn_boolean_t ignore_enoent, 674251881Speter svn_boolean_t show_hidden, 675251881Speter apr_pool_t *result_pool, 676251881Speter apr_pool_t *scratch_pool) 677251881Speter{ 678251881Speter svn_error_t *err; 679251881Speter svn_wc__db_status_t status; 680251881Speter svn_wc__db_lock_t *lock; 681251881Speter svn_node_kind_t db_kind; 682251881Speter 683251881Speter err = svn_wc__db_base_get_info(&status, &db_kind, revision, repos_relpath, 684251881Speter repos_root_url, repos_uuid, NULL, 685251881Speter NULL, NULL, NULL, NULL, NULL, 686251881Speter lock_token ? &lock : NULL, 687251881Speter NULL, NULL, NULL, 688251881Speter wc_ctx->db, local_abspath, 689251881Speter result_pool, scratch_pool); 690251881Speter 691251881Speter if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND) 692251881Speter return svn_error_trace(err); 693251881Speter else if (err 694251881Speter || (!err && !show_hidden 695251881Speter && (status != svn_wc__db_status_normal 696251881Speter && status != svn_wc__db_status_incomplete))) 697251881Speter { 698251881Speter if (!ignore_enoent) 699251881Speter { 700251881Speter if (err) 701251881Speter return svn_error_trace(err); 702251881Speter else 703251881Speter return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, 704251881Speter _("The node '%s' was not found."), 705251881Speter svn_dirent_local_style(local_abspath, 706251881Speter scratch_pool)); 707251881Speter } 708251881Speter svn_error_clear(err); 709251881Speter 710251881Speter if (kind) 711251881Speter *kind = svn_node_unknown; 712251881Speter if (revision) 713251881Speter *revision = SVN_INVALID_REVNUM; 714251881Speter if (repos_relpath) 715251881Speter *repos_relpath = NULL; 716251881Speter if (repos_root_url) 717251881Speter *repos_root_url = NULL; 718251881Speter if (repos_uuid) 719251881Speter *repos_uuid = NULL; 720251881Speter if (lock_token) 721251881Speter *lock_token = NULL; 722251881Speter return SVN_NO_ERROR; 723251881Speter } 724251881Speter 725251881Speter if (kind) 726251881Speter *kind = db_kind; 727251881Speter if (lock_token) 728251881Speter *lock_token = lock ? lock->token : NULL; 729251881Speter 730251881Speter SVN_ERR_ASSERT(!revision || SVN_IS_VALID_REVNUM(*revision)); 731251881Speter SVN_ERR_ASSERT(!repos_relpath || *repos_relpath); 732251881Speter SVN_ERR_ASSERT(!repos_root_url || *repos_root_url); 733251881Speter SVN_ERR_ASSERT(!repos_uuid || *repos_uuid); 734251881Speter return SVN_NO_ERROR; 735251881Speter} 736251881Speter 737251881Spetersvn_error_t * 738251881Spetersvn_wc__node_get_pre_ng_status_data(svn_revnum_t *revision, 739251881Speter svn_revnum_t *changed_rev, 740251881Speter apr_time_t *changed_date, 741251881Speter const char **changed_author, 742251881Speter svn_wc_context_t *wc_ctx, 743251881Speter const char *local_abspath, 744251881Speter apr_pool_t *result_pool, 745251881Speter apr_pool_t *scratch_pool) 746251881Speter{ 747251881Speter svn_wc__db_status_t status; 748251881Speter svn_boolean_t have_base, have_more_work, have_work; 749251881Speter 750251881Speter SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, NULL, NULL, NULL, 751251881Speter changed_rev, changed_date, changed_author, 752251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 753251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 754251881Speter &have_base, &have_more_work, &have_work, 755251881Speter wc_ctx->db, local_abspath, 756251881Speter result_pool, scratch_pool)); 757251881Speter 758251881Speter if (!have_work 759251881Speter || ((!changed_rev || SVN_IS_VALID_REVNUM(*changed_rev)) 760251881Speter && (!revision || SVN_IS_VALID_REVNUM(*revision))) 761251881Speter || ((status != svn_wc__db_status_added) 762251881Speter && (status != svn_wc__db_status_deleted))) 763251881Speter { 764251881Speter return SVN_NO_ERROR; /* We got everything we need */ 765251881Speter } 766251881Speter 767251881Speter if (have_base && !have_more_work) 768251881Speter SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, revision, NULL, NULL, NULL, 769251881Speter changed_rev, changed_date, changed_author, 770251881Speter NULL, NULL, NULL, 771251881Speter NULL, NULL, NULL, NULL, 772251881Speter wc_ctx->db, local_abspath, 773251881Speter result_pool, scratch_pool)); 774251881Speter else if (status == svn_wc__db_status_deleted) 775251881Speter /* Check the information below a WORKING delete */ 776251881Speter SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, changed_rev, 777251881Speter changed_date, changed_author, NULL, 778251881Speter NULL, NULL, NULL, NULL, 779251881Speter wc_ctx->db, local_abspath, 780251881Speter result_pool, scratch_pool)); 781251881Speter 782251881Speter return SVN_NO_ERROR; 783251881Speter} 784251881Speter 785251881Spetersvn_error_t * 786251881Spetersvn_wc__internal_node_get_schedule(svn_wc_schedule_t *schedule, 787251881Speter svn_boolean_t *copied, 788251881Speter svn_wc__db_t *db, 789251881Speter const char *local_abspath, 790251881Speter apr_pool_t *scratch_pool) 791251881Speter{ 792251881Speter svn_wc__db_status_t status; 793251881Speter svn_boolean_t op_root; 794251881Speter svn_boolean_t have_base; 795251881Speter svn_boolean_t have_work; 796251881Speter svn_boolean_t have_more_work; 797251881Speter const char *copyfrom_relpath; 798251881Speter 799251881Speter if (schedule) 800251881Speter *schedule = svn_wc_schedule_normal; 801251881Speter if (copied) 802251881Speter *copied = FALSE; 803251881Speter 804251881Speter SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL, 805251881Speter NULL, NULL, NULL, NULL, NULL, ©from_relpath, 806251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 807251881Speter &op_root, NULL, NULL, 808251881Speter &have_base, &have_more_work, &have_work, 809251881Speter db, local_abspath, scratch_pool, scratch_pool)); 810251881Speter 811251881Speter switch (status) 812251881Speter { 813251881Speter case svn_wc__db_status_not_present: 814251881Speter case svn_wc__db_status_server_excluded: 815251881Speter case svn_wc__db_status_excluded: 816251881Speter /* We used status normal in the entries world. */ 817251881Speter if (schedule) 818251881Speter *schedule = svn_wc_schedule_normal; 819251881Speter break; 820251881Speter case svn_wc__db_status_normal: 821251881Speter case svn_wc__db_status_incomplete: 822251881Speter break; 823251881Speter 824251881Speter case svn_wc__db_status_deleted: 825251881Speter { 826251881Speter if (schedule) 827251881Speter *schedule = svn_wc_schedule_delete; 828251881Speter 829251881Speter if (!copied) 830251881Speter break; 831251881Speter 832251881Speter if (have_more_work || !have_base) 833251881Speter *copied = TRUE; 834251881Speter else 835251881Speter { 836251881Speter const char *work_del_abspath; 837251881Speter 838251881Speter /* Find out details of our deletion. */ 839251881Speter SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, 840251881Speter &work_del_abspath, NULL, 841251881Speter db, local_abspath, 842251881Speter scratch_pool, scratch_pool)); 843251881Speter 844251881Speter if (work_del_abspath) 845251881Speter *copied = TRUE; /* Working deletion */ 846251881Speter } 847251881Speter break; 848251881Speter } 849251881Speter case svn_wc__db_status_added: 850251881Speter { 851251881Speter if (!op_root) 852251881Speter { 853251881Speter if (copied) 854251881Speter *copied = TRUE; 855251881Speter 856251881Speter if (schedule) 857251881Speter *schedule = svn_wc_schedule_normal; 858251881Speter 859251881Speter break; 860251881Speter } 861251881Speter 862251881Speter if (copied) 863251881Speter *copied = (copyfrom_relpath != NULL); 864251881Speter 865251881Speter if (schedule) 866251881Speter *schedule = svn_wc_schedule_add; 867251881Speter else 868251881Speter break; 869251881Speter 870251881Speter /* Check for replaced */ 871251881Speter if (have_base || have_more_work) 872251881Speter { 873251881Speter svn_wc__db_status_t below_working; 874251881Speter SVN_ERR(svn_wc__db_info_below_working(&have_base, &have_work, 875251881Speter &below_working, 876251881Speter db, local_abspath, 877251881Speter scratch_pool)); 878251881Speter 879251881Speter /* If the node is not present or deleted (read: not present 880251881Speter in working), then the node is not a replacement */ 881251881Speter if (below_working != svn_wc__db_status_not_present 882251881Speter && below_working != svn_wc__db_status_deleted) 883251881Speter { 884251881Speter *schedule = svn_wc_schedule_replace; 885251881Speter break; 886251881Speter } 887251881Speter } 888251881Speter break; 889251881Speter } 890251881Speter default: 891251881Speter SVN_ERR_MALFUNCTION(); 892251881Speter } 893251881Speter 894251881Speter return SVN_NO_ERROR; 895251881Speter} 896251881Speter 897251881Spetersvn_error_t * 898251881Spetersvn_wc__node_get_schedule(svn_wc_schedule_t *schedule, 899251881Speter svn_boolean_t *copied, 900251881Speter svn_wc_context_t *wc_ctx, 901251881Speter const char *local_abspath, 902251881Speter apr_pool_t *scratch_pool) 903251881Speter{ 904251881Speter return svn_error_trace( 905251881Speter svn_wc__internal_node_get_schedule(schedule, 906251881Speter copied, 907251881Speter wc_ctx->db, 908251881Speter local_abspath, 909251881Speter scratch_pool)); 910251881Speter} 911251881Speter 912251881Spetersvn_error_t * 913251881Spetersvn_wc__node_clear_dav_cache_recursive(svn_wc_context_t *wc_ctx, 914251881Speter const char *local_abspath, 915251881Speter apr_pool_t *scratch_pool) 916251881Speter{ 917251881Speter return svn_error_trace(svn_wc__db_base_clear_dav_cache_recursive( 918251881Speter wc_ctx->db, local_abspath, scratch_pool)); 919251881Speter} 920251881Speter 921251881Speter 922251881Spetersvn_error_t * 923251881Spetersvn_wc__node_get_lock_tokens_recursive(apr_hash_t **lock_tokens, 924251881Speter svn_wc_context_t *wc_ctx, 925251881Speter const char *local_abspath, 926251881Speter apr_pool_t *result_pool, 927251881Speter apr_pool_t *scratch_pool) 928251881Speter{ 929251881Speter return svn_error_trace(svn_wc__db_base_get_lock_tokens_recursive( 930251881Speter lock_tokens, wc_ctx->db, local_abspath, 931251881Speter result_pool, scratch_pool)); 932251881Speter} 933251881Speter 934251881Spetersvn_error_t * 935251881Spetersvn_wc__get_excluded_subtrees(apr_hash_t **server_excluded_subtrees, 936251881Speter svn_wc_context_t *wc_ctx, 937251881Speter const char *local_abspath, 938251881Speter apr_pool_t *result_pool, 939251881Speter apr_pool_t *scratch_pool) 940251881Speter{ 941251881Speter return svn_error_trace( 942251881Speter svn_wc__db_get_excluded_subtrees(server_excluded_subtrees, 943251881Speter wc_ctx->db, 944251881Speter local_abspath, 945251881Speter result_pool, 946251881Speter scratch_pool)); 947251881Speter} 948251881Speter 949251881Spetersvn_error_t * 950251881Spetersvn_wc__internal_get_origin(svn_boolean_t *is_copy, 951251881Speter svn_revnum_t *revision, 952251881Speter const char **repos_relpath, 953251881Speter const char **repos_root_url, 954251881Speter const char **repos_uuid, 955251881Speter const char **copy_root_abspath, 956251881Speter svn_wc__db_t *db, 957251881Speter const char *local_abspath, 958251881Speter svn_boolean_t scan_deleted, 959251881Speter apr_pool_t *result_pool, 960251881Speter apr_pool_t *scratch_pool) 961251881Speter{ 962251881Speter const char *original_repos_relpath; 963251881Speter const char *original_repos_root_url; 964251881Speter const char *original_repos_uuid; 965251881Speter svn_revnum_t original_revision; 966251881Speter svn_wc__db_status_t status; 967251881Speter 968251881Speter const char *tmp_repos_relpath; 969251881Speter 970251881Speter if (!repos_relpath) 971251881Speter repos_relpath = &tmp_repos_relpath; 972251881Speter 973251881Speter SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, repos_relpath, 974251881Speter repos_root_url, repos_uuid, NULL, NULL, NULL, 975251881Speter NULL, NULL, NULL, 976251881Speter &original_repos_relpath, 977251881Speter &original_repos_root_url, 978251881Speter &original_repos_uuid, &original_revision, 979251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 980251881Speter NULL, NULL, is_copy, 981251881Speter db, local_abspath, result_pool, scratch_pool)); 982251881Speter 983251881Speter if (*repos_relpath) 984251881Speter { 985251881Speter return SVN_NO_ERROR; /* Returned BASE information */ 986251881Speter } 987251881Speter 988251881Speter if (status == svn_wc__db_status_deleted && !scan_deleted) 989251881Speter { 990251881Speter if (is_copy) 991251881Speter *is_copy = FALSE; /* Deletes are stored in working; default to FALSE */ 992251881Speter 993251881Speter return SVN_NO_ERROR; /* No info */ 994251881Speter } 995251881Speter 996251881Speter if (original_repos_relpath) 997251881Speter { 998251881Speter *repos_relpath = original_repos_relpath; 999251881Speter if (revision) 1000251881Speter *revision = original_revision; 1001251881Speter if (repos_root_url) 1002251881Speter *repos_root_url = original_repos_root_url; 1003251881Speter if (repos_uuid) 1004251881Speter *repos_uuid = original_repos_uuid; 1005251881Speter 1006251881Speter if (copy_root_abspath == NULL) 1007251881Speter return SVN_NO_ERROR; 1008251881Speter } 1009251881Speter 1010251881Speter { 1011251881Speter svn_boolean_t scan_working = FALSE; 1012251881Speter 1013251881Speter if (status == svn_wc__db_status_added) 1014251881Speter scan_working = TRUE; 1015251881Speter else if (status == svn_wc__db_status_deleted) 1016251881Speter { 1017251881Speter svn_boolean_t have_base; 1018251881Speter /* Is this a BASE or a WORKING delete? */ 1019251881Speter SVN_ERR(svn_wc__db_info_below_working(&have_base, &scan_working, 1020251881Speter &status, db, local_abspath, 1021251881Speter scratch_pool)); 1022251881Speter } 1023251881Speter 1024251881Speter if (scan_working) 1025251881Speter { 1026251881Speter const char *op_root_abspath; 1027251881Speter 1028251881Speter SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath, NULL, 1029251881Speter NULL, NULL, &original_repos_relpath, 1030251881Speter repos_root_url, 1031251881Speter repos_uuid, revision, 1032251881Speter db, local_abspath, 1033251881Speter result_pool, scratch_pool)); 1034251881Speter 1035251881Speter if (status == svn_wc__db_status_added) 1036251881Speter { 1037251881Speter if (is_copy) 1038251881Speter *is_copy = FALSE; 1039251881Speter return SVN_NO_ERROR; /* Local addition */ 1040251881Speter } 1041251881Speter 1042251881Speter /* We don't know how the following error condition can be fulfilled 1043251881Speter * but we have seen that happening in the wild. Better to create 1044251881Speter * an error than a SEGFAULT. */ 1045251881Speter if (status == svn_wc__db_status_incomplete && !original_repos_relpath) 1046251881Speter return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, 1047251881Speter _("Incomplete copy information on path '%s'."), 1048251881Speter svn_dirent_local_style(local_abspath, 1049251881Speter scratch_pool)); 1050251881Speter 1051251881Speter *repos_relpath = svn_relpath_join( 1052251881Speter original_repos_relpath, 1053251881Speter svn_dirent_skip_ancestor(op_root_abspath, 1054251881Speter local_abspath), 1055251881Speter result_pool); 1056251881Speter if (copy_root_abspath) 1057251881Speter *copy_root_abspath = op_root_abspath; 1058251881Speter } 1059251881Speter else /* Deleted, excluded, not-present, server-excluded, ... */ 1060251881Speter { 1061251881Speter if (is_copy) 1062251881Speter *is_copy = FALSE; 1063251881Speter 1064251881Speter SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, revision, repos_relpath, 1065251881Speter repos_root_url, repos_uuid, NULL, 1066251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 1067251881Speter NULL, NULL, NULL, 1068251881Speter db, local_abspath, 1069251881Speter result_pool, scratch_pool)); 1070251881Speter } 1071251881Speter 1072251881Speter return SVN_NO_ERROR; 1073251881Speter } 1074251881Speter} 1075251881Speter 1076251881Spetersvn_error_t * 1077251881Spetersvn_wc__node_get_origin(svn_boolean_t *is_copy, 1078251881Speter svn_revnum_t *revision, 1079251881Speter const char **repos_relpath, 1080251881Speter const char **repos_root_url, 1081251881Speter const char **repos_uuid, 1082251881Speter const char **copy_root_abspath, 1083251881Speter svn_wc_context_t *wc_ctx, 1084251881Speter const char *local_abspath, 1085251881Speter svn_boolean_t scan_deleted, 1086251881Speter apr_pool_t *result_pool, 1087251881Speter apr_pool_t *scratch_pool) 1088251881Speter{ 1089251881Speter return svn_error_trace(svn_wc__internal_get_origin(is_copy, revision, 1090251881Speter repos_relpath, repos_root_url, repos_uuid, 1091251881Speter copy_root_abspath, 1092251881Speter wc_ctx->db, local_abspath, scan_deleted, 1093251881Speter result_pool, scratch_pool)); 1094251881Speter} 1095251881Speter 1096251881Spetersvn_error_t * 1097251881Spetersvn_wc__node_get_commit_status(svn_boolean_t *added, 1098251881Speter svn_boolean_t *deleted, 1099251881Speter svn_boolean_t *is_replace_root, 1100251881Speter svn_boolean_t *is_op_root, 1101251881Speter svn_revnum_t *revision, 1102251881Speter svn_revnum_t *original_revision, 1103251881Speter const char **original_repos_relpath, 1104251881Speter svn_wc_context_t *wc_ctx, 1105251881Speter const char *local_abspath, 1106251881Speter apr_pool_t *result_pool, 1107251881Speter apr_pool_t *scratch_pool) 1108251881Speter{ 1109251881Speter svn_wc__db_status_t status; 1110251881Speter svn_boolean_t have_base; 1111251881Speter svn_boolean_t have_more_work; 1112251881Speter svn_boolean_t op_root; 1113251881Speter 1114251881Speter /* ### All of this should be handled inside a single read transaction */ 1115251881Speter SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, NULL, 1116251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1117251881Speter original_repos_relpath, NULL, NULL, 1118251881Speter original_revision, NULL, NULL, NULL, 1119251881Speter NULL, NULL, 1120251881Speter &op_root, NULL, NULL, 1121251881Speter &have_base, &have_more_work, NULL, 1122251881Speter wc_ctx->db, local_abspath, 1123251881Speter result_pool, scratch_pool)); 1124251881Speter 1125251881Speter if (added) 1126251881Speter *added = (status == svn_wc__db_status_added); 1127251881Speter if (deleted) 1128251881Speter *deleted = (status == svn_wc__db_status_deleted); 1129251881Speter if (is_op_root) 1130251881Speter *is_op_root = op_root; 1131251881Speter 1132251881Speter if (is_replace_root) 1133251881Speter { 1134251881Speter if (status == svn_wc__db_status_added 1135251881Speter && op_root 1136251881Speter && (have_base || have_more_work)) 1137251881Speter SVN_ERR(svn_wc__db_node_check_replace(is_replace_root, NULL, NULL, 1138251881Speter wc_ctx->db, local_abspath, 1139251881Speter scratch_pool)); 1140251881Speter else 1141251881Speter *is_replace_root = FALSE; 1142251881Speter } 1143251881Speter 1144251881Speter /* Retrieve some information from BASE which is needed for replacing 1145251881Speter and/or deleting BASE nodes. */ 1146251881Speter if (have_base 1147251881Speter && !have_more_work 1148251881Speter && op_root 1149251881Speter && (revision && !SVN_IS_VALID_REVNUM(*revision))) 1150251881Speter { 1151251881Speter SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, revision, NULL, NULL, NULL, 1152251881Speter NULL, NULL, NULL, NULL, NULL, NULL, 1153251881Speter NULL, NULL, NULL, NULL, 1154251881Speter wc_ctx->db, local_abspath, 1155251881Speter scratch_pool, scratch_pool)); 1156251881Speter } 1157251881Speter 1158251881Speter return SVN_NO_ERROR; 1159251881Speter} 1160251881Speter 1161251881Spetersvn_error_t * 1162251881Spetersvn_wc__node_get_md5_from_sha1(const svn_checksum_t **md5_checksum, 1163251881Speter svn_wc_context_t *wc_ctx, 1164251881Speter const char *wri_abspath, 1165251881Speter const svn_checksum_t *sha1_checksum, 1166251881Speter apr_pool_t *result_pool, 1167251881Speter apr_pool_t *scratch_pool) 1168251881Speter{ 1169251881Speter return svn_error_trace(svn_wc__db_pristine_get_md5(md5_checksum, 1170251881Speter wc_ctx->db, 1171251881Speter wri_abspath, 1172251881Speter sha1_checksum, 1173251881Speter result_pool, 1174251881Speter scratch_pool)); 1175251881Speter} 1176251881Speter 1177251881Spetersvn_error_t * 1178251881Spetersvn_wc__get_not_present_descendants(const apr_array_header_t **descendants, 1179251881Speter svn_wc_context_t *wc_ctx, 1180251881Speter const char *local_abspath, 1181251881Speter apr_pool_t *result_pool, 1182251881Speter apr_pool_t *scratch_pool) 1183251881Speter{ 1184251881Speter return svn_error_trace( 1185251881Speter svn_wc__db_get_not_present_descendants(descendants, 1186251881Speter wc_ctx->db, 1187251881Speter local_abspath, 1188251881Speter result_pool, 1189251881Speter scratch_pool)); 1190251881Speter} 1191251881Speter 1192251881Spetersvn_error_t * 1193251881Spetersvn_wc__rename_wc(svn_wc_context_t *wc_ctx, 1194251881Speter const char *from_abspath, 1195251881Speter const char *dst_abspath, 1196251881Speter apr_pool_t *scratch_pool) 1197251881Speter{ 1198251881Speter const char *wcroot_abspath; 1199251881Speter SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath, wc_ctx->db, from_abspath, 1200251881Speter scratch_pool, scratch_pool)); 1201251881Speter 1202251881Speter if (! strcmp(from_abspath, wcroot_abspath)) 1203251881Speter { 1204251881Speter SVN_ERR(svn_wc__db_drop_root(wc_ctx->db, wcroot_abspath, scratch_pool)); 1205251881Speter 1206251881Speter SVN_ERR(svn_io_file_rename(from_abspath, dst_abspath, scratch_pool)); 1207251881Speter } 1208251881Speter else 1209251881Speter return svn_error_createf( 1210251881Speter SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, 1211251881Speter _("'%s' is not the root of the working copy '%s'"), 1212251881Speter svn_dirent_local_style(from_abspath, scratch_pool), 1213251881Speter svn_dirent_local_style(wcroot_abspath, scratch_pool)); 1214251881Speter 1215251881Speter return SVN_NO_ERROR; 1216251881Speter} 1217251881Speter 1218251881Spetersvn_error_t * 1219251881Spetersvn_wc__check_for_obstructions(svn_wc_notify_state_t *obstruction_state, 1220251881Speter svn_node_kind_t *kind, 1221251881Speter svn_boolean_t *deleted, 1222251881Speter svn_boolean_t *excluded, 1223251881Speter svn_depth_t *parent_depth, 1224251881Speter svn_wc_context_t *wc_ctx, 1225251881Speter const char *local_abspath, 1226251881Speter svn_boolean_t no_wcroot_check, 1227251881Speter apr_pool_t *scratch_pool) 1228251881Speter{ 1229251881Speter svn_wc__db_status_t status; 1230251881Speter svn_node_kind_t db_kind; 1231251881Speter svn_node_kind_t disk_kind; 1232251881Speter svn_error_t *err; 1233251881Speter 1234251881Speter *obstruction_state = svn_wc_notify_state_inapplicable; 1235251881Speter if (kind) 1236251881Speter *kind = svn_node_none; 1237251881Speter if (deleted) 1238251881Speter *deleted = FALSE; 1239251881Speter if (excluded) 1240251881Speter *excluded = FALSE; 1241251881Speter if (parent_depth) 1242251881Speter *parent_depth = svn_depth_unknown; 1243251881Speter 1244251881Speter SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool)); 1245251881Speter 1246251881Speter err = svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL, NULL, 1247251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1248251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1249251881Speter NULL, NULL, NULL, NULL, NULL, 1250251881Speter wc_ctx->db, local_abspath, 1251251881Speter scratch_pool, scratch_pool); 1252251881Speter 1253251881Speter if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 1254251881Speter { 1255251881Speter svn_error_clear(err); 1256251881Speter 1257251881Speter if (disk_kind != svn_node_none) 1258251881Speter { 1259251881Speter /* Nothing in the DB, but something on disk */ 1260251881Speter *obstruction_state = svn_wc_notify_state_obstructed; 1261251881Speter return SVN_NO_ERROR; 1262251881Speter } 1263251881Speter 1264251881Speter err = svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL, 1265251881Speter NULL, NULL, NULL, parent_depth, NULL, NULL, 1266251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1267251881Speter NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1268251881Speter NULL, 1269251881Speter wc_ctx->db, svn_dirent_dirname(local_abspath, 1270251881Speter scratch_pool), 1271251881Speter scratch_pool, scratch_pool); 1272251881Speter 1273251881Speter if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 1274251881Speter { 1275251881Speter svn_error_clear(err); 1276251881Speter /* No versioned parent; we can't add a node here */ 1277251881Speter *obstruction_state = svn_wc_notify_state_obstructed; 1278251881Speter return SVN_NO_ERROR; 1279251881Speter } 1280251881Speter else 1281251881Speter SVN_ERR(err); 1282251881Speter 1283251881Speter if (db_kind != svn_node_dir 1284251881Speter || (status != svn_wc__db_status_normal 1285251881Speter && status != svn_wc__db_status_added)) 1286251881Speter { 1287251881Speter /* The parent doesn't allow nodes to be added below it */ 1288251881Speter *obstruction_state = svn_wc_notify_state_obstructed; 1289251881Speter } 1290251881Speter 1291251881Speter return SVN_NO_ERROR; 1292251881Speter } 1293251881Speter else 1294251881Speter SVN_ERR(err); 1295251881Speter 1296251881Speter /* Check for obstructing working copies */ 1297251881Speter if (!no_wcroot_check 1298251881Speter && db_kind == svn_node_dir 1299251881Speter && status == svn_wc__db_status_normal) 1300251881Speter { 1301251881Speter svn_boolean_t is_root; 1302251881Speter SVN_ERR(svn_wc__db_is_wcroot(&is_root, wc_ctx->db, local_abspath, 1303251881Speter scratch_pool)); 1304251881Speter 1305251881Speter if (is_root) 1306251881Speter { 1307251881Speter /* Callers should handle this as unversioned */ 1308251881Speter *obstruction_state = svn_wc_notify_state_obstructed; 1309251881Speter return SVN_NO_ERROR; 1310251881Speter } 1311251881Speter } 1312251881Speter 1313251881Speter if (kind) 1314251881Speter SVN_ERR(convert_db_kind_to_node_kind(kind, db_kind, status, FALSE)); 1315251881Speter 1316251881Speter switch (status) 1317251881Speter { 1318251881Speter case svn_wc__db_status_deleted: 1319251881Speter if (deleted) 1320251881Speter *deleted = TRUE; 1321251881Speter /* Fall through to svn_wc__db_status_not_present */ 1322251881Speter case svn_wc__db_status_not_present: 1323251881Speter if (disk_kind != svn_node_none) 1324251881Speter *obstruction_state = svn_wc_notify_state_obstructed; 1325251881Speter break; 1326251881Speter 1327251881Speter case svn_wc__db_status_excluded: 1328251881Speter case svn_wc__db_status_server_excluded: 1329251881Speter if (excluded) 1330251881Speter *excluded = TRUE; 1331251881Speter /* fall through */ 1332251881Speter case svn_wc__db_status_incomplete: 1333251881Speter *obstruction_state = svn_wc_notify_state_missing; 1334251881Speter break; 1335251881Speter 1336251881Speter case svn_wc__db_status_added: 1337251881Speter case svn_wc__db_status_normal: 1338251881Speter if (disk_kind == svn_node_none) 1339251881Speter *obstruction_state = svn_wc_notify_state_missing; 1340251881Speter else 1341251881Speter { 1342251881Speter svn_node_kind_t expected_kind; 1343251881Speter 1344251881Speter SVN_ERR(convert_db_kind_to_node_kind(&expected_kind, db_kind, 1345251881Speter status, FALSE)); 1346251881Speter 1347251881Speter if (disk_kind != expected_kind) 1348251881Speter *obstruction_state = svn_wc_notify_state_obstructed; 1349251881Speter } 1350251881Speter break; 1351251881Speter default: 1352251881Speter SVN_ERR_MALFUNCTION(); 1353251881Speter } 1354251881Speter 1355251881Speter return SVN_NO_ERROR; 1356251881Speter} 1357251881Speter 1358251881Speter 1359251881Spetersvn_error_t * 1360251881Spetersvn_wc__node_was_moved_away(const char **moved_to_abspath, 1361251881Speter const char **op_root_abspath, 1362251881Speter svn_wc_context_t *wc_ctx, 1363251881Speter const char *local_abspath, 1364251881Speter apr_pool_t *result_pool, 1365251881Speter apr_pool_t *scratch_pool) 1366251881Speter{ 1367251881Speter svn_boolean_t is_deleted; 1368251881Speter 1369251881Speter if (moved_to_abspath) 1370251881Speter *moved_to_abspath = NULL; 1371251881Speter if (op_root_abspath) 1372251881Speter *op_root_abspath = NULL; 1373251881Speter 1374251881Speter SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, wc_ctx, local_abspath, 1375251881Speter scratch_pool)); 1376251881Speter if (is_deleted) 1377251881Speter SVN_ERR(svn_wc__db_scan_deletion(NULL, moved_to_abspath, NULL, 1378251881Speter op_root_abspath, wc_ctx->db, 1379251881Speter local_abspath, 1380251881Speter result_pool, scratch_pool)); 1381251881Speter 1382251881Speter return SVN_NO_ERROR; 1383251881Speter} 1384251881Speter 1385251881Speter 1386251881Spetersvn_error_t * 1387251881Spetersvn_wc__node_was_moved_here(const char **moved_from_abspath, 1388251881Speter const char **delete_op_root_abspath, 1389251881Speter svn_wc_context_t *wc_ctx, 1390251881Speter const char *local_abspath, 1391251881Speter apr_pool_t *result_pool, 1392251881Speter apr_pool_t *scratch_pool) 1393251881Speter{ 1394251881Speter svn_error_t *err; 1395251881Speter 1396251881Speter if (moved_from_abspath) 1397251881Speter *moved_from_abspath = NULL; 1398251881Speter if (delete_op_root_abspath) 1399251881Speter *delete_op_root_abspath = NULL; 1400251881Speter 1401251881Speter err = svn_wc__db_scan_moved(moved_from_abspath, NULL, NULL, 1402251881Speter delete_op_root_abspath, 1403251881Speter wc_ctx->db, local_abspath, 1404251881Speter result_pool, scratch_pool); 1405251881Speter 1406251881Speter if (err) 1407251881Speter { 1408251881Speter /* Return error for not added nodes */ 1409251881Speter if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS) 1410251881Speter return svn_error_trace(err); 1411251881Speter 1412251881Speter /* Path not moved here */ 1413251881Speter svn_error_clear(err); 1414251881Speter return SVN_NO_ERROR; 1415251881Speter } 1416251881Speter 1417251881Speter return SVN_NO_ERROR; 1418251881Speter} 1419