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 *) 55289180Speter = 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 145251881Speter if (op_root) 146251881Speter { 147251881Speter svn_error_t *err; 148251881Speter wc_info->copyfrom_url = 149251881Speter svn_path_url_add_component2(tmpinfo->repos_root_URL, 150251881Speter original_repos_relpath, 151251881Speter result_pool); 152251881Speter 153251881Speter wc_info->copyfrom_rev = original_revision; 154251881Speter 155251881Speter err = svn_wc__db_scan_moved(&wc_info->moved_from_abspath, 156251881Speter NULL, NULL, NULL, 157251881Speter db, local_abspath, 158251881Speter result_pool, scratch_pool); 159251881Speter 160251881Speter if (err) 161251881Speter { 162251881Speter if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS) 163251881Speter return svn_error_trace(err); 164251881Speter svn_error_clear(err); 165251881Speter wc_info->moved_from_abspath = NULL; 166251881Speter } 167251881Speter } 168251881Speter } 169251881Speter 170251881Speter /* ### We should be able to avoid both these calls with the information 171251881Speter from read_info() in most cases */ 172251881Speter if (! op_root) 173251881Speter wc_info->schedule = svn_wc_schedule_normal; 174251881Speter else if (! have_more_work && ! have_base) 175251881Speter wc_info->schedule = svn_wc_schedule_add; 176251881Speter else 177251881Speter { 178251881Speter svn_wc__db_status_t below_working; 179251881Speter svn_boolean_t have_work; 180251881Speter 181251881Speter SVN_ERR(svn_wc__db_info_below_working(&have_base, &have_work, 182251881Speter &below_working, 183251881Speter db, local_abspath, 184251881Speter scratch_pool)); 185251881Speter 186251881Speter /* If the node is not present or deleted (read: not present 187251881Speter in working), then the node is not a replacement */ 188251881Speter if (below_working != svn_wc__db_status_not_present 189251881Speter && below_working != svn_wc__db_status_deleted) 190251881Speter { 191251881Speter wc_info->schedule = svn_wc_schedule_replace; 192251881Speter } 193251881Speter else 194251881Speter wc_info->schedule = svn_wc_schedule_add; 195251881Speter } 196289180Speter SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath, 197289180Speter &tmpinfo->repos_root_URL, 198289180Speter &tmpinfo->repos_UUID, 199289180Speter db, local_abspath, 200289180Speter result_pool, scratch_pool)); 201289180Speter 202289180Speter tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, 203289180Speter repos_relpath, result_pool); 204251881Speter } 205251881Speter else if (status == svn_wc__db_status_deleted) 206251881Speter { 207289180Speter svn_wc__db_status_t w_status; 208251881Speter 209289180Speter SVN_ERR(svn_wc__db_read_pristine_info(&w_status, &tmpinfo->kind, 210251881Speter &tmpinfo->last_changed_rev, 211251881Speter &tmpinfo->last_changed_date, 212251881Speter &tmpinfo->last_changed_author, 213251881Speter &wc_info->depth, 214251881Speter &wc_info->checksum, 215251881Speter NULL, NULL, NULL, 216251881Speter db, local_abspath, 217251881Speter result_pool, scratch_pool)); 218251881Speter 219289180Speter if (w_status == svn_wc__db_status_deleted) 220289180Speter { 221289180Speter /* We have a working not-present status. We don't know anything 222289180Speter about this node, but it *is visible* in STATUS. 223289180Speter 224289180Speter Let's tell that it is excluded */ 225289180Speter 226289180Speter wc_info->depth = svn_depth_exclude; 227289180Speter tmpinfo->kind = svn_node_unknown; 228289180Speter } 229289180Speter 230251881Speter /* And now fetch the url and revision of what will be deleted */ 231251881Speter SVN_ERR(svn_wc__db_scan_deletion(NULL, &wc_info->moved_to_abspath, 232289180Speter NULL, NULL, 233251881Speter db, local_abspath, 234251881Speter scratch_pool, scratch_pool)); 235251881Speter 236289180Speter SVN_ERR(svn_wc__db_read_repos_info(&tmpinfo->rev, &repos_relpath, 237289180Speter &tmpinfo->repos_root_URL, 238289180Speter &tmpinfo->repos_UUID, 239289180Speter db, local_abspath, 240289180Speter result_pool, scratch_pool)); 241251881Speter 242251881Speter wc_info->schedule = svn_wc_schedule_delete; 243289180Speter tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, 244289180Speter repos_relpath, result_pool); 245251881Speter } 246251881Speter else if (status == svn_wc__db_status_not_present 247251881Speter || status == svn_wc__db_status_server_excluded) 248251881Speter { 249251881Speter *info = NULL; 250251881Speter return SVN_NO_ERROR; 251251881Speter } 252289180Speter else if (status == svn_wc__db_status_excluded && !repos_relpath) 253289180Speter { 254289180Speter /* We have a WORKING exclude. Avoid segfault on no repos info */ 255289180Speter 256289180Speter SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath, 257289180Speter &tmpinfo->repos_root_URL, 258289180Speter &tmpinfo->repos_UUID, 259289180Speter db, local_abspath, 260289180Speter result_pool, scratch_pool)); 261289180Speter 262289180Speter wc_info->schedule = svn_wc_schedule_normal; 263289180Speter tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, 264289180Speter repos_relpath, result_pool); 265289180Speter tmpinfo->wc_info->depth = svn_depth_exclude; 266289180Speter } 267251881Speter else 268251881Speter { 269251881Speter /* Just a BASE node. We have all the info we need */ 270251881Speter tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, 271251881Speter repos_relpath, 272251881Speter result_pool); 273251881Speter wc_info->schedule = svn_wc_schedule_normal; 274289180Speter 275289180Speter if (status == svn_wc__db_status_excluded) 276289180Speter wc_info->depth = svn_depth_exclude; 277251881Speter } 278251881Speter 279251881Speter /* A default */ 280251881Speter tmpinfo->size = SVN_INVALID_FILESIZE; 281251881Speter 282251881Speter SVN_ERR(svn_wc__db_get_wcroot(&tmpinfo->wc_info->wcroot_abspath, db, 283251881Speter local_abspath, result_pool, scratch_pool)); 284251881Speter 285251881Speter if (conflicted) 286289180Speter SVN_ERR(svn_wc__read_conflicts(&wc_info->conflicts, NULL, 287289180Speter db, local_abspath, 288289180Speter FALSE /* create tempfiles */, 289289180Speter FALSE /* only tree conflicts */, 290251881Speter result_pool, scratch_pool)); 291251881Speter else 292251881Speter wc_info->conflicts = NULL; 293251881Speter 294251881Speter /* lock stuff */ 295251881Speter if (lock != NULL) 296251881Speter { 297251881Speter tmpinfo->lock = apr_pcalloc(result_pool, sizeof(*(tmpinfo->lock))); 298251881Speter tmpinfo->lock->token = lock->token; 299251881Speter tmpinfo->lock->owner = lock->owner; 300251881Speter tmpinfo->lock->comment = lock->comment; 301251881Speter tmpinfo->lock->creation_date = lock->date; 302251881Speter } 303251881Speter 304251881Speter *info = tmpinfo; 305251881Speter return SVN_NO_ERROR; 306251881Speter} 307251881Speter 308251881Speter 309251881Speter/* Set *INFO to a new struct with minimal content, to be 310251881Speter used in reporting info for unversioned tree conflict victims. */ 311251881Speter/* ### Some fields we could fill out based on the parent dir's entry 312251881Speter or by looking at an obstructing item. */ 313251881Speterstatic svn_error_t * 314251881Speterbuild_info_for_unversioned(svn_wc__info2_t **info, 315251881Speter apr_pool_t *pool) 316251881Speter{ 317251881Speter svn_wc__info2_t *tmpinfo = apr_pcalloc(pool, sizeof(*tmpinfo)); 318251881Speter svn_wc_info_t *wc_info = apr_pcalloc(pool, sizeof (*wc_info)); 319251881Speter 320251881Speter tmpinfo->URL = NULL; 321251881Speter tmpinfo->repos_UUID = NULL; 322251881Speter tmpinfo->repos_root_URL = NULL; 323251881Speter tmpinfo->rev = SVN_INVALID_REVNUM; 324251881Speter tmpinfo->kind = svn_node_none; 325251881Speter tmpinfo->size = SVN_INVALID_FILESIZE; 326251881Speter tmpinfo->last_changed_rev = SVN_INVALID_REVNUM; 327251881Speter tmpinfo->last_changed_date = 0; 328251881Speter tmpinfo->last_changed_author = NULL; 329251881Speter tmpinfo->lock = NULL; 330251881Speter 331251881Speter tmpinfo->wc_info = wc_info; 332251881Speter 333251881Speter wc_info->copyfrom_rev = SVN_INVALID_REVNUM; 334251881Speter wc_info->depth = svn_depth_unknown; 335251881Speter wc_info->recorded_size = SVN_INVALID_FILESIZE; 336251881Speter 337251881Speter *info = tmpinfo; 338251881Speter return SVN_NO_ERROR; 339251881Speter} 340251881Speter 341251881Speter/* Callback and baton for crawl_entries() walk over entries files. */ 342251881Speterstruct found_entry_baton 343251881Speter{ 344251881Speter svn_wc__info_receiver2_t receiver; 345251881Speter void *receiver_baton; 346251881Speter svn_wc__db_t *db; 347251881Speter svn_boolean_t actual_only; 348251881Speter svn_boolean_t first; 349251881Speter /* The set of tree conflicts that have been found but not (yet) visited by 350289180Speter * the tree walker. Map of abspath -> empty string. */ 351251881Speter apr_hash_t *tree_conflicts; 352251881Speter apr_pool_t *pool; 353251881Speter}; 354251881Speter 355251881Speter/* Call WALK_BATON->receiver with WALK_BATON->receiver_baton, passing to it 356251881Speter * info about the path LOCAL_ABSPATH. 357251881Speter * An svn_wc__node_found_func_t callback function. */ 358251881Speterstatic svn_error_t * 359251881Speterinfo_found_node_callback(const char *local_abspath, 360251881Speter svn_node_kind_t kind, 361251881Speter void *walk_baton, 362251881Speter apr_pool_t *scratch_pool) 363251881Speter{ 364251881Speter struct found_entry_baton *fe_baton = walk_baton; 365251881Speter svn_wc__info2_t *info; 366251881Speter 367251881Speter SVN_ERR(build_info_for_node(&info, fe_baton->db, local_abspath, 368251881Speter kind, scratch_pool, scratch_pool)); 369251881Speter 370251881Speter if (info == NULL) 371251881Speter { 372251881Speter if (!fe_baton->first) 373251881Speter return SVN_NO_ERROR; /* not present or server excluded descendant */ 374251881Speter 375251881Speter /* If the info root is not found, that is an error */ 376251881Speter return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, 377251881Speter _("The node '%s' was not found."), 378251881Speter svn_dirent_local_style(local_abspath, 379251881Speter scratch_pool)); 380251881Speter } 381251881Speter 382251881Speter fe_baton->first = FALSE; 383251881Speter 384251881Speter SVN_ERR_ASSERT(info->wc_info != NULL); 385251881Speter SVN_ERR(fe_baton->receiver(fe_baton->receiver_baton, local_abspath, 386251881Speter info, scratch_pool)); 387251881Speter 388251881Speter /* If this node is a versioned directory, make a note of any tree conflicts 389251881Speter * on all immediate children. Some of these may be visited later in this 390251881Speter * walk, at which point they will be removed from the list, while any that 391251881Speter * are not visited will remain in the list. */ 392251881Speter if (fe_baton->actual_only && kind == svn_node_dir) 393251881Speter { 394251881Speter const apr_array_header_t *victims; 395251881Speter int i; 396251881Speter 397251881Speter SVN_ERR(svn_wc__db_read_conflict_victims(&victims, 398251881Speter fe_baton->db, local_abspath, 399251881Speter scratch_pool, scratch_pool)); 400251881Speter 401251881Speter for (i = 0; i < victims->nelts; i++) 402251881Speter { 403251881Speter const char *this_basename = APR_ARRAY_IDX(victims, i, const char *); 404251881Speter 405251881Speter svn_hash_sets(fe_baton->tree_conflicts, 406251881Speter svn_dirent_join(local_abspath, this_basename, 407251881Speter fe_baton->pool), 408251881Speter ""); 409251881Speter } 410251881Speter } 411251881Speter 412251881Speter /* Delete this path which we are currently visiting from the list of tree 413251881Speter * conflicts. This relies on the walker visiting a directory before visiting 414251881Speter * its children. */ 415251881Speter svn_hash_sets(fe_baton->tree_conflicts, local_abspath, NULL); 416251881Speter 417251881Speter return SVN_NO_ERROR; 418251881Speter} 419251881Speter 420251881Speter 421251881Speter/* Return TRUE iff the subtree at ROOT_ABSPATH, restricted to depth DEPTH, 422251881Speter * would include the path CHILD_ABSPATH of kind CHILD_KIND. */ 423251881Speterstatic svn_boolean_t 424251881Speterdepth_includes(const char *root_abspath, 425251881Speter svn_depth_t depth, 426251881Speter const char *child_abspath, 427251881Speter svn_node_kind_t child_kind, 428251881Speter apr_pool_t *scratch_pool) 429251881Speter{ 430251881Speter const char *parent_abspath = svn_dirent_dirname(child_abspath, scratch_pool); 431251881Speter 432251881Speter return (depth == svn_depth_infinity 433251881Speter || ((depth == svn_depth_immediates 434251881Speter || (depth == svn_depth_files && child_kind == svn_node_file)) 435251881Speter && strcmp(root_abspath, parent_abspath) == 0) 436251881Speter || strcmp(root_abspath, child_abspath) == 0); 437251881Speter} 438251881Speter 439251881Speter 440251881Spetersvn_error_t * 441251881Spetersvn_wc__get_info(svn_wc_context_t *wc_ctx, 442251881Speter const char *local_abspath, 443251881Speter svn_depth_t depth, 444251881Speter svn_boolean_t fetch_excluded, 445251881Speter svn_boolean_t fetch_actual_only, 446251881Speter const apr_array_header_t *changelist_filter, 447251881Speter svn_wc__info_receiver2_t receiver, 448251881Speter void *receiver_baton, 449251881Speter svn_cancel_func_t cancel_func, 450251881Speter void *cancel_baton, 451251881Speter apr_pool_t *scratch_pool) 452251881Speter{ 453251881Speter struct found_entry_baton fe_baton; 454251881Speter svn_error_t *err; 455251881Speter apr_pool_t *iterpool = svn_pool_create(scratch_pool); 456251881Speter apr_hash_index_t *hi; 457251881Speter const char *repos_root_url = NULL; 458251881Speter const char *repos_uuid = NULL; 459251881Speter 460251881Speter fe_baton.receiver = receiver; 461251881Speter fe_baton.receiver_baton = receiver_baton; 462251881Speter fe_baton.db = wc_ctx->db; 463251881Speter fe_baton.actual_only = fetch_actual_only; 464251881Speter fe_baton.first = TRUE; 465251881Speter fe_baton.tree_conflicts = apr_hash_make(scratch_pool); 466251881Speter fe_baton.pool = scratch_pool; 467251881Speter 468251881Speter err = svn_wc__internal_walk_children(wc_ctx->db, local_abspath, 469251881Speter fetch_excluded, 470251881Speter changelist_filter, 471251881Speter info_found_node_callback, 472251881Speter &fe_baton, depth, 473251881Speter cancel_func, cancel_baton, 474251881Speter iterpool); 475251881Speter 476251881Speter /* If the target root node is not present, svn_wc__internal_walk_children() 477251881Speter returns a PATH_NOT_FOUND error and doesn't call the callback. If there 478251881Speter is a tree conflict on this node, that is not an error. */ 479251881Speter if (fe_baton.first /* not visited by walk_children */ 480251881Speter && fetch_actual_only 481251881Speter && err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 482251881Speter { 483251881Speter svn_boolean_t tree_conflicted; 484251881Speter svn_error_t *err2; 485251881Speter 486251881Speter err2 = svn_wc__internal_conflicted_p(NULL, NULL, &tree_conflicted, 487251881Speter wc_ctx->db, local_abspath, 488251881Speter iterpool); 489251881Speter 490251881Speter if ((err2 && err2->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)) 491251881Speter { 492251881Speter svn_error_clear(err2); 493251881Speter return svn_error_trace(err); 494251881Speter } 495251881Speter else if (err2 || !tree_conflicted) 496251881Speter return svn_error_compose_create(err, err2); 497251881Speter 498251881Speter svn_error_clear(err); 499251881Speter 500251881Speter svn_hash_sets(fe_baton.tree_conflicts, local_abspath, ""); 501251881Speter } 502251881Speter else 503251881Speter SVN_ERR(err); 504251881Speter 505251881Speter /* If there are any tree conflicts that we have found but have not reported, 506251881Speter * send a minimal info struct for each one now. */ 507251881Speter for (hi = apr_hash_first(scratch_pool, fe_baton.tree_conflicts); hi; 508251881Speter hi = apr_hash_next(hi)) 509251881Speter { 510289180Speter const char *this_abspath = apr_hash_this_key(hi); 511251881Speter const svn_wc_conflict_description2_t *tree_conflict; 512251881Speter svn_wc__info2_t *info; 513289180Speter const apr_array_header_t *conflicts; 514251881Speter 515251881Speter svn_pool_clear(iterpool); 516251881Speter 517251881Speter SVN_ERR(build_info_for_unversioned(&info, iterpool)); 518251881Speter 519251881Speter if (!repos_root_url) 520251881Speter { 521289180Speter SVN_ERR(svn_wc__db_read_repos_info(NULL, NULL, 522289180Speter &repos_root_url, 523289180Speter &repos_uuid, 524289180Speter wc_ctx->db, 525289180Speter svn_dirent_dirname( 526257936Speter this_abspath, 527251881Speter iterpool), 528289180Speter scratch_pool, iterpool)); 529251881Speter } 530251881Speter 531251881Speter info->repos_root_URL = repos_root_url; 532251881Speter info->repos_UUID = repos_uuid; 533251881Speter 534289180Speter SVN_ERR(svn_wc__read_conflicts(&conflicts, NULL, 535251881Speter wc_ctx->db, this_abspath, 536289180Speter FALSE /* create tempfiles */, 537289180Speter FALSE /* only tree conflicts */, 538251881Speter iterpool, iterpool)); 539289180Speter if (! conflicts || ! conflicts->nelts) 540251881Speter continue; 541251881Speter 542289180Speter tree_conflict = APR_ARRAY_IDX(conflicts, 0, 543289180Speter const svn_wc_conflict_description2_t *); 544251881Speter 545251881Speter if (!depth_includes(local_abspath, depth, tree_conflict->local_abspath, 546251881Speter tree_conflict->node_kind, iterpool)) 547251881Speter continue; 548251881Speter 549289180Speter info->wc_info->conflicts = conflicts; 550251881Speter SVN_ERR(receiver(receiver_baton, this_abspath, info, iterpool)); 551251881Speter } 552251881Speter svn_pool_destroy(iterpool); 553251881Speter 554251881Speter return SVN_NO_ERROR; 555251881Speter} 556