Index: subversion/libsvn_client/diff.c =================================================================== --- subversion/libsvn_client/diff.c (revision 23830) +++ subversion/libsvn_client/diff.c (working copy) @@ -1799,8 +1799,6 @@ const char *walk_path = ""; apr_hash_t *wc_mergeinfo; - SVN_ERR(svn_path_get_absolute(&wcpath, wcpath, pool)); - while (TRUE) { /* Look for merge info on WCPATH. If there isn't any, walk @@ -1810,6 +1808,12 @@ SVN_ERR(svn_client__parse_merge_info(&wc_mergeinfo, entry, wcpath, adm_access, ctx, pool)); + /* Subsequent svn_wc_adm_access_t need to be opened with + an absolute path so we can walk up and out of the WC + if necessary. */ + if (!svn_path_is_absolute(wcpath, strlen(wcpath))) + SVN_ERR(svn_path_get_absolute(&wcpath, wcpath, pool)); + if (apr_hash_count(wc_mergeinfo) == 0 && !svn_path_is_root(wcpath, strlen(wcpath))) { @@ -2573,14 +2577,14 @@ apr_hash_t **props, svn_revnum_t rev, const char *url, - struct merge_cmd_baton *merge_b, + const char *wc_target, apr_pool_t *pool) { apr_file_t *fp; svn_stream_t *stream; SVN_ERR(svn_io_open_unique_file2(&fp, filename, - merge_b->target, ".tmp", + wc_target, ".tmp", svn_io_file_del_none, pool)); stream = svn_stream_from_aprfile2(fp, FALSE, pool); SVN_ERR(svn_ra_get_file(ra_session, "", rev, @@ -2739,11 +2743,11 @@ fetching two fulltexts from two different repositories here. */ SVN_ERR(single_file_merge_get_file(&tmpfile1, ra_session1, &props1, is_revert ? r->start : r->start - 1, - URL1, merge_b, pool)); + URL1, target_wcpath, pool)); SVN_ERR(single_file_merge_get_file(&tmpfile2, ra_session2, &props2, is_revert ? r->end - 1 : r->end, - URL2, merge_b, pool)); + URL2, target_wcpath, pool)); /* Discover any svn:mime-type values in the proplists */ pval = apr_hash_get(props1, SVN_PROP_MIME_TYPE, @@ -2759,7 +2763,7 @@ SVN_ERR(merge_file_changed(adm_access, &text_state, &prop_state, - merge_b->target, + target_wcpath, tmpfile1, tmpfile2, is_revert ? r->start : r->start - 1, @@ -2780,7 +2784,7 @@ { svn_wc_notify_t *notify - = svn_wc_create_notify(merge_b->target, svn_wc_notify_update_update, + = svn_wc_create_notify(target_wcpath, svn_wc_notify_update_update, pool); notify->kind = svn_node_file; notify->content_state = text_state; Index: subversion/tests/cmdline/merge_tests.py =================================================================== --- subversion/tests/cmdline/merge_tests.py (revision 23830) +++ subversion/tests/cmdline/merge_tests.py (working copy) @@ -306,7 +306,6 @@ 'tau' : wc.StateItem("This is the file 'tau'.\n"), }) expected_disk.tweak('rho', - props={SVN_PROP_MERGE_INFO : '/A/D/G/rho:2-3'}, contents=other_rho_text + expected_disk.desc['rho'].contents + rho_text @@ -324,15 +323,15 @@ ) expected_status = wc.State(os.path.join(other_wc, 'A', 'D', 'G'), - { '' : Item(wc_rev=1, status=' M'), - 'rho' : Item(wc_rev=1, status='G '), - 'pi' : Item(wc_rev=1, status='G '), + { '' : Item(wc_rev=1, status=' '), + 'rho' : Item(wc_rev=1, status='MM'), + 'pi' : Item(wc_rev=1, status='M '), 'tau' : Item(wc_rev=1, status='C '), }) - expected_status.tweak('pi', status='M ') - expected_status.tweak('rho', status='MM') - expected_status.tweak('tau', status='C ') + # Do the merge, but check svn:mergeinfo props separately since + # run_and_verify_merge would attempt to proplist tau's conflict + # files if we asked it to check props. svntest.actions.run_and_verify_merge( os.path.join(other_wc, 'A', 'D', 'G'), '2', '3', @@ -343,6 +342,10 @@ expected_skip, None, merge_singleton_handler) + svntest.actions.run_and_verify_svn(None, ["/A/D/G/rho:2-3\n"], [], + 'propget', SVN_PROP_MERGE_INFO, + os.path.join(other_wc, + "A", "D", "G", "rho")) #---------------------------------------------------------------------- @@ -4491,7 +4494,25 @@ # this file, to understand why we shorten and chdir() below. short_copy_of_A_D_path = shorten_path_kludge(copy_of_A_D_path) + # We still need to determine how we will handle notification + # callbacks for multiple merges into a single versioned resource. + # Currently every merge range applied to a target is reported + # separately...but eventually we'll probably change the expected + # output. expected_output = wc.State(short_copy_of_A_D_path, { + 'G/pi' : Item(status='G '), + 'G/rho' : Item(status='G '), + 'G/rho' : Item(status='G '), + 'G/tau' : Item(status='G '), + 'G/tau' : Item(status='G '), + 'H/chi' : Item(status='G '), + 'H/chi' : Item(status='G '), + 'H/omega' : Item(status='G '), + 'H/omega' : Item(status='G '), + 'H/psi' : Item(status='G '), + 'H/psi' : Item(status='G '), + 'gamma' : Item(status='G '), + 'gamma' : Item(status='G '), 'umlaut' : Item(status='A '), }) @@ -4950,7 +4971,7 @@ # list all tests here, starting with None: test_list = [ None, - XFail(textual_merges_galore), + textual_merges_galore, add_with_history, delete_file_and_dir, simple_property_merges,