Author: julianfoad
Date: Thu Jul 23 09:19:11 2020
New Revision: 1880192
URL: http://svn.apache.org/viewvc?rev=1880192&view=rev
Log:
Fix issue #4862 "Merge: the resulting mergeinfo is non-deterministic".
In certain merge scenarios where the merge added new paths, the mergeinfo
change notifications and the resulting mergeinfo were non-deterministic.
* subversion/libsvn_client/merge.c
(process_children_with_new_mergeinfo): Process these paths in parent-to-
child order so that inherited mergeinfo is propagated consistently.
* subversion/tests/cmdline/merge_tests.py
(merge_deleted_folder_with_mergeinfo_2): Check the mergeinfo change
notifications and the resulting mergeinfo, as these are now stable.
Modified:
subversion/trunk/subversion/libsvn_client/merge.c
subversion/trunk/subversion/tests/cmdline/merge_tests.py
Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1880192&r1=1880191&r2=1880192&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Jul 23 09:19:11 2020
@@ -7915,18 +7915,23 @@ process_children_with_new_mergeinfo(merg
apr_pool_t *pool)
{
apr_pool_t *iterpool;
- apr_hash_index_t *hi;
+ apr_array_header_t *a;
+ int i;
if (!merge_b->paths_with_new_mergeinfo || merge_b->dry_run)
return SVN_NO_ERROR;
/* Iterate over each path with explicit mergeinfo added by the merge. */
+ /* Iterate over the paths in a parent-to-child order so that inherited
+ * mergeinfo is propagated consistently from each parent path to its
+ * children. (Issue #4862) */
+ a = svn_sort__hash(merge_b->paths_with_new_mergeinfo,
+ svn_sort_compare_items_as_paths, pool);
iterpool = svn_pool_create(pool);
- for (hi = apr_hash_first(pool, merge_b->paths_with_new_mergeinfo);
- hi;
- hi = apr_hash_next(hi))
+ for (i = 0; i < a->nelts; i++)
{
- const char *abspath_with_new_mergeinfo = apr_hash_this_key(hi);
+ svn_sort__item_t *item = &APR_ARRAY_IDX(a, i, svn_sort__item_t);
+ const char *abspath_with_new_mergeinfo = item->key;
svn_mergeinfo_t path_inherited_mergeinfo;
svn_mergeinfo_t path_explicit_mergeinfo;
svn_client__merge_path_t *new_child;
Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=1880192&r1=1880191&r2=1880192&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Thu Jul 23
09:19:11 2020
@@ -18609,12 +18609,12 @@ def merge_deleted_folder_with_mergeinfo_
'A/D/G2' : Item(status='A '),
})
# verify that mergeinfo is set/changed on A/D, A/D/G, A/D/G2.
- #expected_mergeinfo_output = wc.State(sbox.ospath(''), {
- # 'A' : Item(status=' U'),
- # 'A/D' : Item(status=' G'),
- # 'A/D/G' : Item(status=' G'), # varies, G or U: see issue #4862
- # 'A/D/G2' : Item(status=' G'), # varies, G or U: see issue #4862
- # })
+ expected_mergeinfo_output = wc.State(sbox.ospath(''), {
+ 'A' : Item(status=' U'),
+ 'A/D' : Item(status=' G'),
+ 'A/D/G' : Item(status=' G'),
+ 'A/D/G2' : Item(status=' G'),
+ })
expected_status = svntest.actions.get_virginal_state(sbox.ospath('A'),
7).subtree('A')
expected_status.tweak_some(
lambda path, item: [True] if path.split('/')[0] == 'D' else [],
@@ -18628,7 +18628,7 @@ def merge_deleted_folder_with_mergeinfo_
svntest.actions.run_and_verify_merge(sbox.ospath('A'), None, None,
'^/branch_A', None,
expected_output,
- None, #expected_mergeinfo_output
+ expected_mergeinfo_output,
None,
None,
expected_status,
@@ -18638,6 +18638,17 @@ def merge_deleted_folder_with_mergeinfo_
dry_run=False # as dry run is broken
)
+ # verify that mergeinfo is set/changed on A/D, A/D/G, A/D/G2.
+ expected_mergeinfo = [
+ ('A', ['/branch_A:3-7']),
+ ('A/D', ['/branch_A/D:5-7\n', '/branch_B/C:1*']),
+ ('A/D/G', ['/branch_A/D/G:5-7\n', '/branch_B/C/G:1*']),
+ ('A/D/G2', ['/branch_A/D/G2:5-7\n', '/branch_B/C/G2:1*']),
+ ]
+ for path, mergeinfo in expected_mergeinfo:
+ svntest.actions.check_prop('svn:mergeinfo', sbox.ospath(path),
+ [m.encode() for m in mergeinfo])
+
os.chdir(was_cwd)
########################################################################