From cc6b9896260edea3744c8a7ed837c0c05c4b7bb0 Mon Sep 17 00:00:00 2001 From: Timofei Zhakov Date: Mon, 2 Dec 2024 18:48:29 +0000 Subject: [PATCH] In the trunk, at merge.c: Open the root directory baton for each operation. After this change we should always have a parent directory opened, even if we are given NULL as the parent_dir_baton argument of merge_dir_opened() or when merge_file_opened() is invoked with NULL dir_baton. In these cases we will access a "virtual" directory baton of the whole operation from the global merge_cmd_baton. We'll detect which baton to use by evaluating ternary operator, that checks the directory baton for NULL, and returns the global one if so. This will lead the merge implementation to the state, where we are always having the parent directory "opened" and we have an ability to access their resources, even if it hasn't been opened. There are a lot of checks such `if (pdb)`, which might be removed then. I'll commit them separately to optimize the diff and keep the correct structure. Additionally, there was a hack in the do_file_merge() function, that was opening a parent directory using the open_dir_for_replace_single_file() function. Now we can just do the sequence of tree-processor's invocations, provided below: [[[ file_opened() file_deleted() file_opened() file_added() ]]] * subversion/libsvn_client/merge.c (merge_cmd_baton_t): Declare target_dir_baton field. (merge_file_opened, merge_dir_opened): Check the directory for NULL, and take it from merge_b->target_dir_baton if it is. (open_dir_for_replace_single_file): Remove this function, since it is no longer referenced. (do_file_merge): No longer open directory using open_dir_for_replace_single_file(), but rely to the recent changes. (do_merge): Initialize merge_cmd_baton.target_dir_baton with a new baton, created using the create_dir_baton() function. git-svn-id: https://svn.apache.org/repos/asf/subversion/trunk@1922266 13f79535-47bb-0310-9956-ffa450edef68 --- subversion/libsvn_client/merge.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/subversion/libsvn_client/merge.c b/subversion/libsvn_client/merge.c index c153f1375e02a..bb74435c87a48 100644 --- a/subversion/libsvn_client/merge.c +++ b/subversion/libsvn_client/merge.c @@ -254,6 +254,9 @@ typedef struct merge_cmd_baton_t { /* Description of merge target node */ const svn_client__merge_target_t *target; + /* Directory baton for the root of the operation's target */ + struct merge_dir_baton_t *target_dir_baton; + /* The left and right URLs and revs. The value of this field changes to reflect the merge_source_t *currently* being merged by do_merge(). */ svn_client__merge_source_t merge_source; @@ -1851,7 +1854,8 @@ merge_file_opened(void **new_file_baton, apr_pool_t *scratch_pool) { merge_cmd_baton_t *merge_b = processor->baton; - struct merge_dir_baton_t *pdb = dir_baton; + struct merge_dir_baton_t *pdb = + dir_baton ? dir_baton : merge_b->target_dir_baton; struct merge_file_baton_t *fb = create_file_baton(result_pool); const char *local_abspath = svn_dirent_join(merge_b->target->abspath, relpath, scratch_pool); @@ -2630,7 +2634,8 @@ merge_dir_opened(void **new_dir_baton, { merge_cmd_baton_t *merge_b = processor->baton; struct merge_dir_baton_t *db = create_dir_baton(result_pool); - struct merge_dir_baton_t *pdb = parent_dir_baton; + struct merge_dir_baton_t *pdb = + parent_dir_baton ? parent_dir_baton : merge_b->target_dir_baton; const char *local_abspath = svn_dirent_join(merge_b->target->abspath, relpath, scratch_pool); @@ -3514,14 +3519,6 @@ merge_apply_processor(merge_cmd_baton_t *merge_cmd_baton, return merge_processor; } -/* Initialize minimal dir baton to allow calculating 'R'eplace - from 'D'elete + 'A'dd. */ -static void * -open_dir_for_replace_single_file(apr_pool_t *result_pool) -{ - return create_dir_baton(result_pool); -} - /*-----------------------------------------------------------------------*/ /*** Merge Notification ***/ @@ -7773,7 +7770,6 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog, do a text-n-props merge; otherwise, do a delete-n-add merge. */ if (! (merge_b->diff_ignore_ancestry || sources_related)) { - void *dir_baton = open_dir_for_replace_single_file(iterpool); void *file_baton; svn_boolean_t skip; @@ -7784,7 +7780,7 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog, left_source, NULL /* right_source */, NULL /* copyfrom_source */, - dir_baton, + NULL /* dir_baton */, processor, iterpool, iterpool)); if (! skip) @@ -7803,7 +7799,7 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog, NULL /* left_source */, right_source, NULL /* copyfrom_source */, - dir_baton, + NULL /* dir_baton */, processor, iterpool, iterpool)); if (! skip) @@ -9992,6 +9988,7 @@ do_merge(apr_hash_t **modified_subtrees, merge_cmd_baton.ctx = ctx; merge_cmd_baton.reintegrate_merge = reintegrate_merge; merge_cmd_baton.target = target; + merge_cmd_baton.target_dir_baton = create_dir_baton(result_pool); merge_cmd_baton.pool = iterpool; merge_cmd_baton.merge_options = merge_options; merge_cmd_baton.diff3_cmd = diff3_cmd;