Author: pburba Date: Wed Oct 24 23:14:12 2012 New Revision: 1401915 URL: http://svn.apache.org/viewvc?rev=1401915&view=rev Log: Prevent segfault when merge target has file externals with mergeinfo.
See http://svn.haxx.se/dev/archive-2012-10/0364.shtml * subversion/libsvn_client/merge.c (get_wc_explicit_mergeinfo_catalog): Prune file externals with explicit mergeinfo from the catalog. * subversion/tests/cmdline/merge_tests.py (merge_with_externals_with_mergeinfo): New regression test. (test_list): Add merge_with_externals_with_mergeinfo. 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=1401915&r1=1401914&r2=1401915&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/merge.c (original) +++ subversion/trunk/subversion/libsvn_client/merge.c Wed Oct 24 23:14:12 2012 @@ -5731,12 +5731,17 @@ get_wc_explicit_mergeinfo_catalog(apr_ha svn_opt_revision_t working_revision = { svn_opt_revision_working, { 0 } }; apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_hash_index_t *hi; + apr_hash_t *externals; SVN_ERR(svn_client_propget5(subtrees_with_mergeinfo, NULL, SVN_PROP_MERGEINFO, target_abspath, &working_revision, &working_revision, NULL, depth, NULL, ctx, result_pool, scratch_pool)); + SVN_ERR(svn_wc__externals_defined_below(&externals, ctx->wc_ctx, + target_abspath, scratch_pool, + scratch_pool)); + /* Convert property values to svn_mergeinfo_t. */ for (hi = apr_hash_first(scratch_pool, *subtrees_with_mergeinfo); hi; @@ -5747,6 +5752,15 @@ get_wc_explicit_mergeinfo_catalog(apr_ha svn_mergeinfo_t mergeinfo; svn_error_t *err; + /* svn_client_propget5 picks up file externals with + mergeinfo, but we don't want those. */ + if (apr_hash_get(externals, wc_path, APR_HASH_KEY_STRING)) + { + apr_hash_set(*subtrees_with_mergeinfo, wc_path, + APR_HASH_KEY_STRING, NULL); + continue; + } + svn_pool_clear(iterpool); err = svn_mergeinfo_parse(&mergeinfo, mergeinfo_string->data, Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=1401915&r1=1401914&r2=1401915&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Wed Oct 24 23:14:12 2012 @@ -17826,6 +17826,60 @@ def merge_with_added_subtrees_with_merge None, None, None, None, None, 1, 0) +#---------------------------------------------------------------------- +@SkipUnless(server_has_mergeinfo) +def merge_with_externals_with_mergeinfo(sbox): + "merge with externals with mergeinfo" + + # Some paths we'll care about. + A_path = sbox.ospath('A') + A_COPY_path = sbox.ospath('A_COPY') + file_external_path = sbox.ospath('A/file-external') + mu_COPY_path = sbox.ospath('A_COPY/mu') + mu_path = sbox.ospath('A/mu') + + sbox.build() + wc_dir = sbox.wc_dir + + # Make a branch of ^/A and then make a few edits under A in r3-6: + wc_disk, wc_status = set_up_branch(sbox) + + svntest.main.file_write(mu_COPY_path, "branch edit") + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'file edit on the branch', wc_dir) + svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir) + + # Create a file external under 'A' and set some bogus mergeinfo + # on it (the fact that this mergeinfo is bogus has no bearing on + # this test). + svntest.actions.run_and_verify_svn(None, None, [], 'propset', + 'svn:externals', + '^/iota file-external', A_path) + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'set file external', wc_dir) + svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir) + svntest.actions.run_and_verify_svn(None, None, [], 'ps', SVN_PROP_MERGEINFO, + "/bogus-mergeinfo:5", file_external_path) + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'set mergeinfo on file external', + file_external_path) + + # Sync merge ^/A to A_COPY and then reintegrate A_COPY back to A. + svntest.actions.run_and_verify_svn(None, None, [], 'merge', + sbox.repo_url + '/A', A_COPY_path) + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'sync merge', wc_dir) + # This was segfaulting, see + # http://svn.haxx.se/dev/archive-2012-10/0364.shtml + svntest.actions.run_and_verify_svn( + None, + expected_merge_output(None, + ['U ' + mu_path + '\n', + ' U ' + A_path + '\n'], + two_url=True), + [], 'merge', '--reintegrate', sbox.repo_url + '/A_COPY', + A_path) + ######################################################################## # Run the tests @@ -17961,6 +18015,7 @@ test_list = [ None, reverse_merge_with_rename, merge_adds_then_deletes_subtree, merge_with_added_subtrees_with_mergeinfo, + merge_with_externals_with_mergeinfo, ] if __name__ == '__main__':
