Author: svn-role Date: Thu Mar 19 18:23:48 2015 New Revision: 1667834 URL: http://svn.apache.org/r1667834 Log: Merge r1666690 from trunk:
* r1666690 Record skipped tree during merge on the skip root instead of leaves Justification: Resolves a user reported problem in merge handling. Avoids unnecessary mergeinfo recording on multiple leaves when a single ancestor is shadowed. Votes: +1: rhuijben, brane, philip Modified: subversion/branches/1.9.x/ (props changed) subversion/branches/1.9.x/STATUS subversion/branches/1.9.x/subversion/libsvn_client/merge.c subversion/branches/1.9.x/subversion/tests/cmdline/merge_tree_conflict_tests.py Propchange: subversion/branches/1.9.x/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Mar 19 18:23:48 2015 @@ -89,4 +89,4 @@ /subversion/branches/verify-at-commit:1462039-1462408 /subversion/branches/verify-keep-going:1439280-1546110 /subversion/branches/wc-collate-path:1402685-1480384 -/subversion/trunk:1660545-1660547,1660549-1662901,1663003,1663338,1663347,1663374,1663450,1663697,1663706,1663749,1664078,1664080,1664084-1664085,1664187,1664191,1664200,1664344,1664476,1664480-1664481,1664483,1664507,1664520-1664521,1664523,1664526-1664527,1664531-1664532,1664588,1664927,1665164,1665611-1665612,1665845,1665850,1665852,1665886,1666270,1666272,1666851 +/subversion/trunk:1660545-1660547,1660549-1662901,1663003,1663338,1663347,1663374,1663450,1663697,1663706,1663749,1664078,1664080,1664084-1664085,1664187,1664191,1664200,1664344,1664476,1664480-1664481,1664483,1664507,1664520-1664521,1664523,1664526-1664527,1664531-1664532,1664588,1664927,1665164,1665611-1665612,1665845,1665850,1665852,1665886,1666270,1666272,1666690,1666851 Modified: subversion/branches/1.9.x/STATUS URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/STATUS?rev=1667834&r1=1667833&r2=1667834&view=diff ============================================================================== --- subversion/branches/1.9.x/STATUS (original) +++ subversion/branches/1.9.x/STATUS Thu Mar 19 18:23:48 2015 @@ -178,14 +178,6 @@ Veto-blocked changes: Approved changes: ================= - * r1666690 - Record skipped tree during merge on the skip root instead of leaves - Justification: - Resolves a user reported problem in merge handling. Avoids unnecessary - mergeinfo recording on multiple leaves when a single ancestor is shadowed. - Votes: - +1: rhuijben, brane, philip - * r1663183, r1663184 Introduce build support for Visual Studio "2015" Justification: Modified: subversion/branches/1.9.x/subversion/libsvn_client/merge.c URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_client/merge.c?rev=1667834&r1=1667833&r2=1667834&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/libsvn_client/merge.c (original) +++ subversion/branches/1.9.x/subversion/libsvn_client/merge.c Thu Mar 19 18:23:48 2015 @@ -1267,13 +1267,14 @@ record_skip(merge_cmd_baton_t *merge_b, svn_node_kind_t kind, svn_wc_notify_action_t action, svn_wc_notify_state_t state, + struct merge_dir_baton_t *pdb, apr_pool_t *scratch_pool) { if (merge_b->record_only) return SVN_NO_ERROR; /* ### Why? - Legacy compatibility */ - if (merge_b->merge_source.ancestral - || merge_b->reintegrate_merge) + if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge) + && !(pdb && pdb->shadowed)) { store_path(merge_b->skipped_abspaths, local_abspath); } @@ -2020,7 +2021,8 @@ merge_file_changed(const char *relpath, /* We haven't notified for this node yet: report a skip */ SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file, svn_wc_notify_update_shadowed_update, - fb->skip_reason, scratch_pool)); + fb->skip_reason, fb->parent_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -2190,7 +2192,8 @@ merge_file_added(const char *relpath, /* We haven't notified for this node yet: report a skip */ SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file, svn_wc_notify_update_shadowed_add, - fb->skip_reason, scratch_pool)); + fb->skip_reason, fb->parent_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -2401,7 +2404,8 @@ merge_file_deleted(const char *relpath, /* We haven't notified for this node yet: report a skip */ SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file, svn_wc_notify_update_shadowed_delete, - fb->skip_reason, scratch_pool)); + fb->skip_reason, fb->parent_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -2790,6 +2794,12 @@ merge_dir_opened(void **new_dir_baton, db->tree_conflict_reason = added ? svn_wc_conflict_reason_added : svn_wc_conflict_reason_obstructed; + + if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge) + && !(pdb && pdb->shadowed)) + { + store_path(merge_b->skipped_abspaths, local_abspath); + } } } @@ -2917,7 +2927,8 @@ merge_dir_changed(const char *relpath, /* We haven't notified for this node yet: report a skip */ SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir, svn_wc_notify_update_shadowed_update, - db->skip_reason, scratch_pool)); + db->skip_reason, db->parent_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -3002,7 +3013,8 @@ merge_dir_added(const char *relpath, /* We haven't notified for this node yet: report a skip */ SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir, svn_wc_notify_update_shadowed_add, - db->skip_reason, scratch_pool)); + db->skip_reason, db->parent_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -3169,7 +3181,8 @@ merge_dir_deleted(const char *relpath, /* We haven't notified for this node yet: report a skip */ SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir, svn_wc_notify_update_shadowed_delete, - db->skip_reason, scratch_pool)); + db->skip_reason, db->parent_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -3351,13 +3364,14 @@ merge_node_absent(const char *relpath, apr_pool_t *scratch_pool) { merge_cmd_baton_t *merge_b = processor->baton; + struct merge_dir_baton_t *db = dir_baton; const char *local_abspath = svn_dirent_join(merge_b->target->abspath, relpath, scratch_pool); SVN_ERR(record_skip(merge_b, local_abspath, svn_node_unknown, svn_wc_notify_skip, svn_wc_notify_state_missing, - scratch_pool)); + db, scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/1.9.x/subversion/tests/cmdline/merge_tree_conflict_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1667834&r1=1667833&r2=1667834&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/tests/cmdline/merge_tree_conflict_tests.py (original) +++ subversion/branches/1.9.x/subversion/tests/cmdline/merge_tree_conflict_tests.py Thu Mar 19 18:23:48 2015 @@ -2087,6 +2087,116 @@ def merge_conflict_details(sbox): svntest.actions.run_and_verify_info(expected_info, sbox.ospath('B'), '--depth', 'infinity') +def merge_obstruction_recording(sbox): + "merge obstruction recording" + + sbox.build(empty=True) + wc_dir = sbox.wc_dir + + sbox.simple_mkdir('trunk') + sbox.simple_mkdir('branches') + sbox.simple_commit() #r1 + + svntest.actions.run_and_verify_svn(None, [], + 'copy', sbox.repo_url + '/trunk', + sbox.repo_url + '/branches/branch', + '-mCopy') # r2 + + sbox.simple_mkdir('trunk/dir') + sbox.simple_add_text('The file on trunk\n', 'trunk/dir/file.txt') + sbox.simple_commit() #r3 + + sbox.simple_update() + + sbox.simple_mkdir('branches/branch/dir') + sbox.simple_add_text('The file on branch\n', 'branches/branch/dir/file.txt') + sbox.simple_commit() #r4 + + sbox.simple_update() + + svntest.actions.run_and_verify_svn(None, [], + 'switch', '^/branches/branch', wc_dir, + '--ignore-ancestry') + + expected_output = wc.State(wc_dir, { + 'dir' : Item(status=' ', treeconflict='C'), + 'dir/file.txt' : Item(status=' ', treeconflict='A'), + }) + expected_mergeinfo_output = wc.State(wc_dir, { + '' : Item(status=' U'), + 'dir' : Item(status=' U'), # Because dir already exists + }) + expected_elision_output = wc.State(wc_dir, { + }) + expected_disk = wc.State('', { + 'dir/file.txt' : Item(contents="The file on branch\n"), + 'dir' : Item(props={'svn:mergeinfo':''}), + '.' : Item(props={'svn:mergeinfo':'/trunk:2-4'}), + }) + expected_status = wc.State(wc_dir, { + '' : Item(status=' M', wc_rev='4'), + 'dir' : Item(status=' M', treeconflict='C', wc_rev='4'), + 'dir/file.txt' : Item(status=' ', wc_rev='4'), + }) + expected_skip = wc.State('', { + }) + svntest.actions.run_and_verify_merge(wc_dir, '1', '4', sbox.repo_url + '/trunk', + None, + expected_output, + expected_mergeinfo_output, + expected_elision_output, + expected_disk, + expected_status, + expected_skip, + check_props=True) + expected_info = [ + { + "Path" : re.escape(sbox.ospath('dir')), + "Tree conflict": re.escape( + 'local dir obstruction, incoming dir add upon merge' + + ' Source left: (none) ^/trunk/dir@1' + + ' Source right: (dir) ^/trunk/dir@4') + }, + ] + + svntest.actions.run_and_verify_info(expected_info, sbox.ospath('dir')) + + # How should the user handle this conflict? + # ### Would be nice if we could just accept mine (leave as is, fix mergeinfo) + # ### or accept theirs (delete what is here and insert copy + svntest.actions.run_and_verify_svn(None, [], + 'resolve', '--accept=working', + sbox.ospath('dir')) + + # Redo the skipped merge as record only merge + expected_output = [ + '--- Recording mergeinfo for merge of r4 into \'%s\':\n' % \ + sbox.ospath('dir'), + ' G %s\n' % sbox.ospath('dir'), + ] + # ### Why are r1-r3 not recorded? + # ### Guess: Because dir's history only exists since r4. + svntest.actions.run_and_verify_svn(expected_output, [], + 'merge', '--record-only', + sbox.repo_url + '/trunk/dir', + sbox.ospath('dir'), + '-c', '1-4') + + expected_disk = wc.State('', { + 'dir' : Item(props={'svn:mergeinfo':'/trunk/dir:4'}), + 'dir/file.txt' : Item(contents="The file on branch\n"), + '.' : Item(props={'svn:mergeinfo':'/trunk:2-4'}), + }) + svntest.actions.verify_disk(wc_dir, expected_disk, check_props=True) + + # Because r1-r3 are not recorded, the mergeinfo is not elided :( + + # Even something like a two url merge wouldn't work, because dir + # didn't exist below trunk in r1 either. + + # A resolver action could be smarter though... + + ######################################################################## # Run the tests @@ -2118,6 +2228,7 @@ test_list = [ None, merge_replace_causes_tree_conflict2, merge_replace_on_del_fails, merge_conflict_details, + merge_obstruction_recording, ] if __name__ == '__main__':