info.c revision 257936
1251881Speter/** 2251881Speter * @copyright 3251881Speter * ==================================================================== 4251881Speter * Licensed to the Apache Software Foundation (ASF) under one 5251881Speter * or more contributor license agreements. See the NOTICE file 6251881Speter * distributed with this work for additional information 7251881Speter * regarding copyright ownership. The ASF licenses this file 8251881Speter * to you under the Apache License, Version 2.0 (the 9251881Speter * "License"); you may not use this file except in compliance 10251881Speter * with the License. You may obtain a copy of the License at 11251881Speter * 12251881Speter * http://www.apache.org/licenses/LICENSE-2.0 13251881Speter * 14251881Speter * Unless required by applicable law or agreed to in writing, 15251881Speter * software distributed under the License is distributed on an 16251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17251881Speter * KIND, either express or implied. See the License for the 18251881Speter * specific language governing permissions and limitations 19251881Speter * under the License. 20251881Speter * ==================================================================== 21251881Speter * @endcopyright 22251881Speter */ 23251881Speter 24251881Speter#include "svn_dirent_uri.h" 25251881Speter#include "svn_hash.h" 26251881Speter#include "svn_path.h" 27251881Speter#include "svn_pools.h" 28251881Speter#include "svn_wc.h" 29251881Speter 30251881Speter#include "wc.h" 31251881Speter 32251881Speter#include "svn_private_config.h" 33251881Speter#include "private/svn_wc_private.h" 34251881Speter 35251881Speter 36251881Speter 37251881Spetersvn_wc_info_t * 38251881Spetersvn_wc_info_dup(const svn_wc_info_t *info, 39251881Speter apr_pool_t *pool) 40251881Speter{ 41251881Speter svn_wc_info_t *new_info = apr_pmemdup(pool, info, sizeof(*new_info)); 42251881Speter 43251881Speter if (info->changelist) 44251881Speter new_info->changelist = apr_pstrdup(pool, info->changelist); 45251881Speter new_info->checksum = svn_checksum_dup(info->checksum, pool); 46251881Speter if (info->conflicts) 47251881Speter { 48251881Speter int i; 49251881Speter 50251881Speter apr_array_header_t *new_conflicts 51251881Speter = apr_array_make(pool, info->conflicts->nelts, info->conflicts->elt_size); 52251881Speter for (i = 0; i < info->conflicts->nelts; i++) 53251881Speter { 54251881Speter APR_ARRAY_PUSH(new_conflicts, svn_wc_conflict_description2_t *) 55251881Speter = svn_wc__conflict_description2_dup( 56251881Speter APR_ARRAY_IDX(info->conflicts, i, 57251881Speter const svn_wc_conflict_description2_t *), 58251881Speter pool); 59251881Speter } 60251881Speter new_info->conflicts = new_conflicts; 61251881Speter } 62251881Speter if (info->copyfrom_url) 63251881Speter new_info->copyfrom_url = apr_pstrdup(pool, info->copyfrom_url); 64251881Speter if (info->wcroot_abspath) 65251881Speter new_info->wcroot_abspath = apr_pstrdup(pool, info->wcroot_abspath); 66251881Speter if (info->moved_from_abspath) 67251881Speter new_info->moved_from_abspath = apr_pstrdup(pool, info->moved_from_abspath); 68251881Speter if (info->moved_to_abspath) 69251881Speter new_info->moved_to_abspath = apr_pstrdup(pool, info->moved_to_abspath); 70251881Speter 71251881Speter return new_info; 72251881Speter} 73251881Speter 74251881Speter 75251881Speter/* Set *INFO to a new struct, allocated in RESULT_POOL, built from the WC 76251881Speter metadata of LOCAL_ABSPATH. Pointer fields are copied by reference, not 77251881Speter dup'd. */ 78251881Speterstatic svn_error_t * 79251881Speterbuild_info_for_node(svn_wc__info2_t **info, 80251881Speter svn_wc__db_t *db, 81251881Speter const char *local_abspath, 82251881Speter svn_node_kind_t kind, 83251881Speter apr_pool_t *result_pool, 84251881Speter apr_pool_t *scratch_pool) 85251881Speter{ 86251881Speter svn_wc__info2_t *tmpinfo; 87251881Speter const char *repos_relpath; 88251881Speter svn_wc__db_status_t status; 89251881Speter svn_node_kind_t db_kind; 90251881Speter const char *original_repos_relpath; 91251881Speter const char *original_repos_root_url; 92251881Speter const char *original_uuid; 93251881Speter svn_revnum_t original_revision; 94251881Speter svn_wc__db_lock_t *lock; 95251881Speter svn_boolean_t conflicted; 96251881Speter svn_boolean_t op_root; 97251881Speter svn_boolean_t have_base; 98251881Speter svn_boolean_t have_more_work; 99251881Speter svn_wc_info_t *wc_info; 100251881Speter 101251881Speter tmpinfo = apr_pcalloc(result_pool, sizeof(*tmpinfo)); 102251881Speter tmpinfo->kind = kind; 103251881Speter 104251881Speter wc_info = apr_pcalloc(result_pool, sizeof(*wc_info)); 105251881Speter tmpinfo->wc_info = wc_info; 106251881Speter 107251881Speter wc_info->copyfrom_rev = SVN_INVALID_REVNUM; 108251881Speter 109251881Speter SVN_ERR(svn_wc__db_read_info(&status, &db_kind, &tmpinfo->rev, 110251881Speter &repos_relpath, 111251881Speter &tmpinfo->repos_root_URL, &tmpinfo->repos_UUID, 112251881Speter &tmpinfo->last_changed_rev, 113251881Speter &tmpinfo->last_changed_date, 114251881Speter &tmpinfo->last_changed_author, 115251881Speter &wc_info->depth, &wc_info->checksum, NULL, 116251881Speter &original_repos_relpath, 117251881Speter &original_repos_root_url, &original_uuid, 118251881Speter &original_revision, &lock, 119251881Speter &wc_info->recorded_size, 120251881Speter &wc_info->recorded_time, 121251881Speter &wc_info->changelist, 122251881Speter &conflicted, &op_root, NULL, NULL, 123251881Speter &have_base, &have_more_work, NULL, 124251881Speter db, local_abspath, 125251881Speter result_pool, scratch_pool)); 126251881Speter 127251881Speter if (original_repos_root_url != NULL) 128251881Speter { 129251881Speter tmpinfo->repos_root_URL = original_repos_root_url; 130251881Speter tmpinfo->repos_UUID = original_uuid; 131251881Speter } 132251881Speter 133251881Speter if (status == svn_wc__db_status_added) 134251881Speter { 135251881Speter /* ### We should also just be fetching the true BASE revision 136251881Speter ### here, which means copied items would also not have a 137251881Speter ### revision to display. But WC-1 wants to show the revision of 138251881Speter ### copy targets as the copyfrom-rev. *sigh* */ 139251881Speter 140251881Speter if (original_repos_relpath) 141251881Speter { 142251881Speter /* Root or child of copy */ 143251881Speter tmpinfo->rev = original_revision; 144251881Speter repos_relpath = original_repos_relpath; 145251881Speter 146251881Speter if (op_root) 147251881Speter { 148251881Speter svn_error_t *err; 149251881Speter wc_info->copyfrom_url = 150251881Speter svn_path_url_add_component2(tmpinfo->repos_root_URL, 151251881Speter original_repos_relpath, 152251881Speter result_pool); 153251881Speter 154251881Speter wc_info->copyfrom_rev = original_revision; 155251881Speter 156251881Speter err = svn_wc__db_scan_moved(&wc_info->moved_from_abspath, 157251881Speter NULL, NULL, NULL, 158251881Speter db, local_abspath, 159251881Speter result_pool, scratch_pool); 160251881Speter 161251881Speter if (err) 162251881Speter { 163251881Speter if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS) 164251881Speter return svn_error_trace(err); 165251881Speter svn_error_clear(err); 166251881Speter wc_info->moved_from_abspath = NULL; 167251881Speter } 168251881Speter } 169251881Speter } 170251881Speter else if (op_root) 171251881Speter { 172251881Speter /* Local addition */ 173251881Speter SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath, 174251881Speter &tmpinfo->repos_root_URL, 175251881Speter &tmpinfo->repos_UUID, 176251881Speter NULL, NULL, NULL, NULL, 177251881Speter db, local_abspath, 178251881Speter result_pool, scratch_pool)); 179251881Speter 180251881Speter if (have_base) 181251881Speter SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &tmpinfo->rev, NULL, 182251881Speter NULL, NULL, NULL, NULL, NULL, 183251881Speter NULL, NULL, NULL, NULL, NULL, 184251881Speter NULL, NULL, 185251881Speter db, local_abspath, 186251881Speter scratch_pool, scratch_pool)); 187251881Speter } 188251881Speter else 189251881Speter { 190251881Speter /* Child of copy. ### Not WC-NG like */ 191251881Speter SVN_ERR(svn_wc__internal_get_origin(NULL, &tmpinfo->rev, 192251881Speter &repos_relpath, 193251881Speter &tmpinfo->repos_root_URL, 194251881Speter &tmpinfo->repos_UUID, NULL, 195251881Speter db, local_abspath, TRUE, 196251881Speter result_pool, scratch_pool)); 197251881Speter } 198251881Speter 199251881Speter /* ### We should be able to avoid both these calls with the information 200251881Speter from read_info() in most cases */ 201251881Speter if (! op_root) 202251881Speter wc_info->schedule = svn_wc_schedule_normal; 203251881Speter else if (! have_more_work && ! have_base) 204251881Speter wc_info->schedule = svn_wc_schedule_add; 205251881Speter else 206251881Speter { 207251881Speter svn_wc__db_status_t below_working; 208251881Speter svn_boolean_t have_work; 209251881Speter 210251881Speter SVN_ERR(svn_wc__db_info_below_working(&have_base, &have_work, 211251881Speter &below_working, 212251881Speter db, local_abspath, 213251881Speter scratch_pool)); 214251881Speter 215251881Speter /* If the node is not present or deleted (read: not present 216251881Speter in working), then the node is not a replacement */ 217251881Speter if (below_working != svn_wc__db_status_not_present 218251881Speter && below_working != svn_wc__db_status_deleted) 219251881Speter { 220251881Speter wc_info->schedule = svn_wc_schedule_replace; 221251881Speter } 222251881Speter else 223251881Speter wc_info->schedule = svn_wc_schedule_add; 224251881Speter } 225251881Speter SVN_ERR(svn_wc__db_read_url(&tmpinfo->URL, db, local_abspath, 226251881Speter result_pool, scratch_pool)); 227251881Speter } 228251881Speter else if (status == svn_wc__db_status_deleted) 229251881Speter { 230251881Speter const char *work_del_abspath; 231251881Speter 232251881Speter SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, 233251881Speter &tmpinfo->last_changed_rev, 234251881Speter &tmpinfo->last_changed_date, 235251881Speter &tmpinfo->last_changed_author, 236251881Speter &wc_info->depth, 237251881Speter &wc_info->checksum, 238251881Speter NULL, NULL, NULL, 239251881Speter db, local_abspath, 240251881Speter result_pool, scratch_pool)); 241251881Speter 242251881Speter /* And now fetch the url and revision of what will be deleted */ 243251881Speter SVN_ERR(svn_wc__db_scan_deletion(NULL, &wc_info->moved_to_abspath, 244251881Speter &work_del_abspath, NULL, 245251881Speter db, local_abspath, 246251881Speter scratch_pool, scratch_pool)); 247251881Speter if (work_del_abspath != NULL) 248251881Speter { 249251881Speter /* This is a deletion within a copied subtree. Get the copied-from 250251881Speter * revision. */ 251251881Speter const char *added_abspath = svn_dirent_dirname(work_del_abspath, 252251881Speter scratch_pool); 253251881Speter 254251881Speter SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath, 255251881Speter &tmpinfo->repos_root_URL, 256251881Speter &tmpinfo->repos_UUID, 257251881Speter NULL, NULL, NULL, 258251881Speter &tmpinfo->rev, 259251881Speter db, added_abspath, 260251881Speter result_pool, scratch_pool)); 261251881Speter 262251881Speter tmpinfo->URL = svn_path_url_add_component2( 263251881Speter tmpinfo->repos_root_URL, 264251881Speter svn_relpath_join(repos_relpath, 265251881Speter svn_dirent_skip_ancestor(added_abspath, 266251881Speter local_abspath), 267251881Speter scratch_pool), 268251881Speter result_pool); 269251881Speter } 270251881Speter else 271251881Speter { 272251881Speter SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &tmpinfo->rev, 273251881Speter &repos_relpath, 274251881Speter &tmpinfo->repos_root_URL, 275251881Speter &tmpinfo->repos_UUID, NULL, NULL, 276251881Speter NULL, NULL, NULL, NULL, 277251881Speter NULL, NULL, NULL, NULL, 278251881Speter db, local_abspath, 279251881Speter result_pool, scratch_pool)); 280251881Speter 281251881Speter tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, 282251881Speter repos_relpath, 283251881Speter result_pool); 284251881Speter } 285251881Speter 286251881Speter wc_info->schedule = svn_wc_schedule_delete; 287251881Speter } 288251881Speter else if (status == svn_wc__db_status_not_present 289251881Speter || status == svn_wc__db_status_server_excluded) 290251881Speter { 291251881Speter *info = NULL; 292251881Speter return SVN_NO_ERROR; 293251881Speter } 294251881Speter else 295251881Speter { 296251881Speter /* Just a BASE node. We have all the info we need */ 297251881Speter tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, 298251881Speter repos_relpath, 299251881Speter result_pool); 300251881Speter wc_info->schedule = svn_wc_schedule_normal; 301251881Speter } 302251881Speter 303251881Speter if (status == svn_wc__db_status_excluded) 304251881Speter tmpinfo->wc_info->depth = svn_depth_exclude; 305251881Speter 306251881Speter /* A default */ 307251881Speter tmpinfo->size = SVN_INVALID_FILESIZE; 308251881Speter 309251881Speter SVN_ERR(svn_wc__db_get_wcroot(&tmpinfo->wc_info->wcroot_abspath, db, 310251881Speter local_abspath, result_pool, scratch_pool)); 311251881Speter 312251881Speter if (conflicted) 313251881Speter SVN_ERR(svn_wc__read_conflicts(&wc_info->conflicts, db, 314251881Speter local_abspath, 315251881Speter TRUE /* ### create tempfiles */, 316251881Speter result_pool, scratch_pool)); 317251881Speter else 318251881Speter wc_info->conflicts = NULL; 319251881Speter 320251881Speter /* lock stuff */ 321251881Speter if (lock != NULL) 322251881Speter { 323251881Speter tmpinfo->lock = apr_pcalloc(result_pool, sizeof(*(tmpinfo->lock))); 324251881Speter tmpinfo->lock->token = lock->token; 325251881Speter tmpinfo->lock->owner = lock->owner; 326251881Speter tmpinfo->lock->comment = lock->comment; 327251881Speter tmpinfo->lock->creation_date = lock->date; 328251881Speter } 329251881Speter 330251881Speter *info = tmpinfo; 331251881Speter return SVN_NO_ERROR; 332251881Speter} 333251881Speter 334251881Speter 335251881Speter/* Set *INFO to a new struct with minimal content, to be 336251881Speter used in reporting info for unversioned tree conflict victims. */ 337251881Speter/* ### Some fields we could fill out based on the parent dir's entry 338251881Speter or by looking at an obstructing item. */ 339251881Speterstatic svn_error_t * 340251881Speterbuild_info_for_unversioned(svn_wc__info2_t **info, 341251881Speter apr_pool_t *pool) 342251881Speter{ 343251881Speter svn_wc__info2_t *tmpinfo = apr_pcalloc(pool, sizeof(*tmpinfo)); 344251881Speter svn_wc_info_t *wc_info = apr_pcalloc(pool, sizeof (*wc_info)); 345251881Speter 346251881Speter tmpinfo->URL = NULL; 347251881Speter tmpinfo->repos_UUID = NULL; 348251881Speter tmpinfo->repos_root_URL = NULL; 349251881Speter tmpinfo->rev = SVN_INVALID_REVNUM; 350251881Speter tmpinfo->kind = svn_node_none; 351251881Speter tmpinfo->size = SVN_INVALID_FILESIZE; 352251881Speter tmpinfo->last_changed_rev = SVN_INVALID_REVNUM; 353251881Speter tmpinfo->last_changed_date = 0; 354251881Speter tmpinfo->last_changed_author = NULL; 355251881Speter tmpinfo->lock = NULL; 356251881Speter 357251881Speter tmpinfo->wc_info = wc_info; 358251881Speter 359251881Speter wc_info->copyfrom_rev = SVN_INVALID_REVNUM; 360251881Speter wc_info->depth = svn_depth_unknown; 361251881Speter wc_info->recorded_size = SVN_INVALID_FILESIZE; 362251881Speter 363251881Speter *info = tmpinfo; 364251881Speter return SVN_NO_ERROR; 365251881Speter} 366251881Speter 367251881Speter/* Callback and baton for crawl_entries() walk over entries files. */ 368251881Speterstruct found_entry_baton 369251881Speter{ 370251881Speter svn_wc__info_receiver2_t receiver; 371251881Speter void *receiver_baton; 372251881Speter svn_wc__db_t *db; 373251881Speter svn_boolean_t actual_only; 374251881Speter svn_boolean_t first; 375251881Speter /* The set of tree conflicts that have been found but not (yet) visited by 376251881Speter * the tree walker. Map of abspath -> svn_wc_conflict_description2_t. */ 377251881Speter apr_hash_t *tree_conflicts; 378251881Speter apr_pool_t *pool; 379251881Speter}; 380251881Speter 381251881Speter/* Call WALK_BATON->receiver with WALK_BATON->receiver_baton, passing to it 382251881Speter * info about the path LOCAL_ABSPATH. 383251881Speter * An svn_wc__node_found_func_t callback function. */ 384251881Speterstatic svn_error_t * 385251881Speterinfo_found_node_callback(const char *local_abspath, 386251881Speter svn_node_kind_t kind, 387251881Speter void *walk_baton, 388251881Speter apr_pool_t *scratch_pool) 389251881Speter{ 390251881Speter struct found_entry_baton *fe_baton = walk_baton; 391251881Speter svn_wc__info2_t *info; 392251881Speter 393251881Speter SVN_ERR(build_info_for_node(&info, fe_baton->db, local_abspath, 394251881Speter kind, scratch_pool, scratch_pool)); 395251881Speter 396251881Speter if (info == NULL) 397251881Speter { 398251881Speter if (!fe_baton->first) 399251881Speter return SVN_NO_ERROR; /* not present or server excluded descendant */ 400251881Speter 401251881Speter /* If the info root is not found, that is an error */ 402251881Speter return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, 403251881Speter _("The node '%s' was not found."), 404251881Speter svn_dirent_local_style(local_abspath, 405251881Speter scratch_pool)); 406251881Speter } 407251881Speter 408251881Speter fe_baton->first = FALSE; 409251881Speter 410251881Speter SVN_ERR_ASSERT(info->wc_info != NULL); 411251881Speter SVN_ERR(fe_baton->receiver(fe_baton->receiver_baton, local_abspath, 412251881Speter info, scratch_pool)); 413251881Speter 414251881Speter /* If this node is a versioned directory, make a note of any tree conflicts 415251881Speter * on all immediate children. Some of these may be visited later in this 416251881Speter * walk, at which point they will be removed from the list, while any that 417251881Speter * are not visited will remain in the list. */ 418251881Speter if (fe_baton->actual_only && kind == svn_node_dir) 419251881Speter { 420251881Speter const apr_array_header_t *victims; 421251881Speter int i; 422251881Speter 423251881Speter SVN_ERR(svn_wc__db_read_conflict_victims(&victims, 424251881Speter fe_baton->db, local_abspath, 425251881Speter scratch_pool, scratch_pool)); 426251881Speter 427251881Speter for (i = 0; i < victims->nelts; i++) 428251881Speter { 429251881Speter const char *this_basename = APR_ARRAY_IDX(victims, i, const char *); 430251881Speter 431251881Speter svn_hash_sets(fe_baton->tree_conflicts, 432251881Speter svn_dirent_join(local_abspath, this_basename, 433251881Speter fe_baton->pool), 434251881Speter ""); 435251881Speter } 436251881Speter } 437251881Speter 438251881Speter /* Delete this path which we are currently visiting from the list of tree 439251881Speter * conflicts. This relies on the walker visiting a directory before visiting 440251881Speter * its children. */ 441251881Speter svn_hash_sets(fe_baton->tree_conflicts, local_abspath, NULL); 442251881Speter 443251881Speter return SVN_NO_ERROR; 444251881Speter} 445251881Speter 446251881Speter 447251881Speter/* Return TRUE iff the subtree at ROOT_ABSPATH, restricted to depth DEPTH, 448251881Speter * would include the path CHILD_ABSPATH of kind CHILD_KIND. */ 449251881Speterstatic svn_boolean_t 450251881Speterdepth_includes(const char *root_abspath, 451251881Speter svn_depth_t depth, 452251881Speter const char *child_abspath, 453251881Speter svn_node_kind_t child_kind, 454251881Speter apr_pool_t *scratch_pool) 455251881Speter{ 456251881Speter const char *parent_abspath = svn_dirent_dirname(child_abspath, scratch_pool); 457251881Speter 458251881Speter return (depth == svn_depth_infinity 459251881Speter || ((depth == svn_depth_immediates 460251881Speter || (depth == svn_depth_files && child_kind == svn_node_file)) 461251881Speter && strcmp(root_abspath, parent_abspath) == 0) 462251881Speter || strcmp(root_abspath, child_abspath) == 0); 463251881Speter} 464251881Speter 465251881Speter 466251881Spetersvn_error_t * 467251881Spetersvn_wc__get_info(svn_wc_context_t *wc_ctx, 468251881Speter const char *local_abspath, 469251881Speter svn_depth_t depth, 470251881Speter svn_boolean_t fetch_excluded, 471251881Speter svn_boolean_t fetch_actual_only, 472251881Speter const apr_array_header_t *changelist_filter, 473251881Speter svn_wc__info_receiver2_t receiver, 474251881Speter void *receiver_baton, 475251881Speter svn_cancel_func_t cancel_func, 476251881Speter void *cancel_baton, 477251881Speter apr_pool_t *scratch_pool) 478251881Speter{ 479251881Speter struct found_entry_baton fe_baton; 480251881Speter svn_error_t *err; 481251881Speter apr_pool_t *iterpool = svn_pool_create(scratch_pool); 482251881Speter apr_hash_index_t *hi; 483251881Speter const char *repos_root_url = NULL; 484251881Speter const char *repos_uuid = NULL; 485251881Speter 486251881Speter fe_baton.receiver = receiver; 487251881Speter fe_baton.receiver_baton = receiver_baton; 488251881Speter fe_baton.db = wc_ctx->db; 489251881Speter fe_baton.actual_only = fetch_actual_only; 490251881Speter fe_baton.first = TRUE; 491251881Speter fe_baton.tree_conflicts = apr_hash_make(scratch_pool); 492251881Speter fe_baton.pool = scratch_pool; 493251881Speter 494251881Speter err = svn_wc__internal_walk_children(wc_ctx->db, local_abspath, 495251881Speter fetch_excluded, 496251881Speter changelist_filter, 497251881Speter info_found_node_callback, 498251881Speter &fe_baton, depth, 499251881Speter cancel_func, cancel_baton, 500251881Speter iterpool); 501251881Speter 502251881Speter /* If the target root node is not present, svn_wc__internal_walk_children() 503251881Speter returns a PATH_NOT_FOUND error and doesn't call the callback. If there 504251881Speter is a tree conflict on this node, that is not an error. */ 505251881Speter if (fe_baton.first /* not visited by walk_children */ 506251881Speter && fetch_actual_only 507251881Speter && err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 508251881Speter { 509251881Speter svn_boolean_t tree_conflicted; 510251881Speter svn_error_t *err2; 511251881Speter 512251881Speter err2 = svn_wc__internal_conflicted_p(NULL, NULL, &tree_conflicted, 513251881Speter wc_ctx->db, local_abspath, 514251881Speter iterpool); 515251881Speter 516251881Speter if ((err2 && err2->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)) 517251881Speter { 518251881Speter svn_error_clear(err2); 519251881Speter return svn_error_trace(err); 520251881Speter } 521251881Speter else if (err2 || !tree_conflicted) 522251881Speter return svn_error_compose_create(err, err2); 523251881Speter 524251881Speter svn_error_clear(err); 525251881Speter 526251881Speter svn_hash_sets(fe_baton.tree_conflicts, local_abspath, ""); 527251881Speter } 528251881Speter else 529251881Speter SVN_ERR(err); 530251881Speter 531251881Speter /* If there are any tree conflicts that we have found but have not reported, 532251881Speter * send a minimal info struct for each one now. */ 533251881Speter for (hi = apr_hash_first(scratch_pool, fe_baton.tree_conflicts); hi; 534251881Speter hi = apr_hash_next(hi)) 535251881Speter { 536251881Speter const char *this_abspath = svn__apr_hash_index_key(hi); 537251881Speter const svn_wc_conflict_description2_t *tree_conflict; 538251881Speter svn_wc__info2_t *info; 539251881Speter 540251881Speter svn_pool_clear(iterpool); 541251881Speter 542251881Speter SVN_ERR(build_info_for_unversioned(&info, iterpool)); 543251881Speter 544251881Speter if (!repos_root_url) 545251881Speter { 546251881Speter SVN_ERR(svn_wc__internal_get_repos_info(NULL, NULL, 547251881Speter &repos_root_url, 548251881Speter &repos_uuid, 549251881Speter wc_ctx->db, 550251881Speter svn_dirent_dirname( 551257936Speter this_abspath, 552251881Speter iterpool), 553251881Speter scratch_pool, 554251881Speter iterpool)); 555251881Speter } 556251881Speter 557251881Speter info->repos_root_URL = repos_root_url; 558251881Speter info->repos_UUID = repos_uuid; 559251881Speter 560251881Speter SVN_ERR(svn_wc__read_conflicts(&info->wc_info->conflicts, 561251881Speter wc_ctx->db, this_abspath, 562251881Speter TRUE /* ### create tempfiles */, 563251881Speter iterpool, iterpool)); 564251881Speter 565251881Speter if (! info->wc_info->conflicts || ! info->wc_info->conflicts->nelts) 566251881Speter continue; 567251881Speter 568251881Speter tree_conflict = APR_ARRAY_IDX(info->wc_info->conflicts, 0, 569251881Speter svn_wc_conflict_description2_t *); 570251881Speter 571251881Speter if (!depth_includes(local_abspath, depth, tree_conflict->local_abspath, 572251881Speter tree_conflict->node_kind, iterpool)) 573251881Speter continue; 574251881Speter 575251881Speter SVN_ERR(receiver(receiver_baton, this_abspath, info, iterpool)); 576251881Speter } 577251881Speter svn_pool_destroy(iterpool); 578251881Speter 579251881Speter return SVN_NO_ERROR; 580251881Speter} 581