Index: subversion/libsvn_client/copy.c =================================================================== --- subversion/libsvn_client/copy.c (revision 25819) +++ subversion/libsvn_client/copy.c (working copy) @@ -83,7 +83,7 @@ return SVN_NO_ERROR; range = apr_palloc(pool, sizeof(*range)); - range->start = oldest_rev; + range->start = oldest_rev - 1; range->end = rev; rangelist = apr_array_make(pool, 1, sizeof(range)); APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = range; Index: subversion/libsvn_client/merge.c =================================================================== --- subversion/libsvn_client/merge.c (revision 25819) +++ subversion/libsvn_client/merge.c (working copy) @@ -1919,17 +1919,13 @@ would be required). */ if (same_urls) { - /* Handle the fact that a svn_merge_range_t's "start" and "end" - are inclusive. */ if (range->start < range->end) { *merge_type = merge_type_merge; - range->start += 1; } else if (range->start > range->end) { *merge_type = merge_type_rollback; - range->end += 1; } else /* No revisions to merge. */ { @@ -1940,7 +1936,6 @@ else { *merge_type = merge_type_merge; - range->start += 1; } return SVN_NO_ERROR; @@ -2233,7 +2228,7 @@ depth, merge_b->dry_run, ra_session2, - is_rollback ? r->start : r->start-1, + r->start, notification_receiver, ¬ify_b, ctx->cancel_func, @@ -2244,7 +2239,7 @@ SVN_ERR(svn_ra_do_diff3(ra_session, &reporter, &report_baton, - is_rollback ? r->end - 1 : r->end, + r->end, "", depth, ignore_ancestry, @@ -2253,7 +2248,7 @@ diff_editor, diff_edit_baton, subpool)); SVN_ERR(reporter->set_path(report_baton, "", - is_rollback ? r->start : r->start - 1, + r->start, depth, FALSE, NULL, subpool)); if (notify_b.same_urls && children_sw_or_with_mergeinfo && @@ -2279,7 +2274,7 @@ child_repos_path = child_wcpath + (target_wcpath_len ? target_wcpath_len + 1 : 0); SVN_ERR(reporter->set_path(report_baton, child_repos_path, - is_rollback ? r->end - 1 : r->end, + r->end, depth, FALSE, NULL, subpool)); } } @@ -2580,11 +2575,11 @@ /* While we currently don't allow it, in theory we could be fetching two fulltexts from two different repositories here. */ SVN_ERR(single_file_merge_get_file(&tmpfile1, ra_session1, &props1, - is_rollback ? r->start : r->start - 1, + r->start, URL1, target_wcpath, subpool)); SVN_ERR(single_file_merge_get_file(&tmpfile2, ra_session2, &props2, - is_rollback ? r->end - 1 : r->end, + r->end, URL2, target_wcpath, subpool)); /* Discover any svn:mime-type values in the proplists */ @@ -2604,8 +2599,8 @@ target_wcpath, tmpfile1, tmpfile2, - is_rollback ? r->start : r->start - 1, - is_rollback ? r->end - 1 : r->end, + r->start, + r->end, mimetype1, mimetype2, propchanges, props1, merge_b)); Index: subversion/libsvn_repos/log.c =================================================================== --- subversion/libsvn_repos/log.c (revision 25819) +++ subversion/libsvn_repos/log.c (working copy) @@ -879,7 +879,7 @@ svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - if (revision >= range->start && revision <= range->end) + if (revision > range->start && revision <= range->end) { *merge_source = key; return SVN_NO_ERROR; Index: subversion/libsvn_subr/mergeinfo.c =================================================================== --- subversion/libsvn_subr/mergeinfo.c (revision 25819) +++ subversion/libsvn_subr/mergeinfo.c (working copy) @@ -38,7 +38,7 @@ combine_ranges(svn_merge_range_t **output, svn_merge_range_t *in1, svn_merge_range_t *in2) { - if (in1->start <= in2->end + 1 && in2->start <= in1->end + 1) + if (in1->start <= in2->end && in2->start <= in1->end) { (*output)->start = MIN(in1->start, in2->start); (*output)->end = MAX(in1->end, in2->end); @@ -135,7 +135,7 @@ return svn_error_createf(SVN_ERR_MERGE_INFO_PARSE_ERROR, NULL, _("Invalid character '%c' found in revision " "list"), *curr); - mrange->start = firstrev; + mrange->start = firstrev - 1; mrange->end = firstrev; if (*curr == '-') @@ -295,7 +295,7 @@ static svn_boolean_t range_intersect(svn_merge_range_t *first, svn_merge_range_t *second) { - return (first->start <= second->end) && (second->start <= first->end); + return (first->start + 1 <= second->end) && (second->start + 1 <= first->end); } static svn_boolean_t @@ -405,7 +405,7 @@ { /* Retain the range that falls before the eraser start. */ tmp_range.start = elt1->start; - tmp_range.end = elt2->start - 1; + tmp_range.end = elt2->start; } else { @@ -435,7 +435,7 @@ *output, pool); } - wboardelt.start = elt2->end + 1; + wboardelt.start = elt2->end; wboardelt.end = elt1->end; } else @@ -565,7 +565,7 @@ { svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - nbr_revs += range->end - range->start + 1; + nbr_revs += range->end - range->start; } return nbr_revs; @@ -584,7 +584,7 @@ { svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - svn_revnum_t rev = range->start; + svn_revnum_t rev = range->start + 1; while (rev <= range->end) { @@ -779,10 +779,10 @@ svn_range_to_stringbuf(svn_stringbuf_t **result, svn_merge_range_t *range, apr_pool_t *pool) { - if (range->start == range->end) - *result = svn_stringbuf_createf(pool, "%ld", range->start); + if (range->start == range->end - 1) + *result = svn_stringbuf_createf(pool, "%ld", range->end); else - *result = svn_stringbuf_createf(pool, "%ld-%ld",range->start, + *result = svn_stringbuf_createf(pool, "%ld-%ld", range->start + 1, range->end); return SVN_NO_ERROR; } Index: subversion/svn/notify.c =================================================================== --- subversion/svn/notify.c (revision 25819) +++ subversion/svn/notify.c (working copy) @@ -411,12 +411,21 @@ break; case svn_wc_notify_merge_begin: - if (n->merge_range->start == n->merge_range->end) + if (n->merge_range->start == n->merge_range->end + || n->merge_range->start == n->merge_range->end - 1) err = svn_cmdline_printf(pool, _("--- Merging r%ld:\n"), + n->merge_range->end); + else if (n->merge_range->start - 1 == n->merge_range->end) + err = svn_cmdline_printf(pool, _("--- Merging r-%ld:\n"), n->merge_range->start); - else + else if (n->merge_range->start < n->merge_range->end) err = svn_cmdline_printf(pool, _("--- Merging r%ld through r%ld:\n"), - n->merge_range->start, n->merge_range->end); + n->merge_range->start + 1, + n->merge_range->end); + else /* n->merge_range->start > n->merge_range->end - 1 */ + err = svn_cmdline_printf(pool, _("--- Merging r%ld through r%ld:\n"), + n->merge_range->start, + n->merge_range->end + 1); if (err) goto print_error; break; Index: subversion/tests/cmdline/merge_tests.py =================================================================== --- subversion/tests/cmdline/merge_tests.py (revision 25819) +++ subversion/tests/cmdline/merge_tests.py (working copy) @@ -276,7 +276,7 @@ # # run_and_verify_merge doesn't support merging to a file WCPATH # so use run_and_verify_svn. - svntest.actions.run_and_verify_svn(None, [svntest.main.merge_notify_line(3), + svntest.actions.run_and_verify_svn(None, [svntest.main.merge_notify_line(-3), 'G ' + other_rho_path + '\n'], [], 'merge', '-c-3', sbox.repo_url + '/A/D/G/rho', @@ -1294,12 +1294,12 @@ # merge using URL for sourcepath if arg_flav == 'r': svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(2), + [svntest.main.merge_notify_line(-2), 'U mu\n'], [], 'merge', '-r', '2:1', mu_url) elif arg_flav == 'c': svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(2), + [svntest.main.merge_notify_line(-2), 'U mu\n'], [], 'merge', '-c', '-2', mu_url) elif arg_flav == '*': @@ -1307,7 +1307,7 @@ # forward merges only (e.g. non-reverts). Undo application of # r2 to enable continuation of the test case. svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(2), + [svntest.main.merge_notify_line(-2), 'U mu\n'], [], 'merge', '-c', '-2', mu_url) @@ -1409,7 +1409,7 @@ # Try to revert the last change to mu via svn merge # Cannot use run_and_verify_merge with a file target svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(2), + [svntest.main.merge_notify_line(-2), 'U mu\n'], [], 'merge', '-r', 'HEAD:PREV', 'mu') @@ -2297,7 +2297,7 @@ theta_J_url = sbox.repo_url + '/J/theta' theta_L_url = sbox.repo_url + '/L/theta' svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(8, 7), + [svntest.main.merge_notify_line(7), 'U theta\n'], [], 'merge', theta_J_url, theta_L_url) os.chdir(saved_cwd) @@ -2974,7 +2974,7 @@ # We can't use run_and_verify_merge because it doesn't support this # syntax of the merge command. ### TODO: We can use run_and_verify_merge2() here now. - expected_output = [svntest.main.merge_notify_line(3, 2), + expected_output = [svntest.main.merge_notify_line(2), "A " + foo_path + "\n"] svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge', C_url, F_url, wc_dir) @@ -5230,7 +5230,7 @@ # run_and_verify_merge doesn't support merging to a file WCPATH # so use run_and_verify_svn. svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(5), + [svntest.main.merge_notify_line(-5), 'U ' + short_beta_COPY_path + \ '\n'], [], 'merge', '-c-5', sbox.repo_url + '/A/B/E/beta', @@ -6097,7 +6097,7 @@ # merge info for A_COPY/D/H, A/D/H's merge info should elide to A/D. os.chdir(svntest.main.work_dir) svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(3), + [svntest.main.merge_notify_line(-3), 'G ' + os.path.join(short_H_path, "psi") + '\n'], [], 'merge', '-r3:2', @@ -6189,7 +6189,7 @@ short_D_path = shorten_path_kludge(A_D_path) os.chdir(svntest.main.work_dir) svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(4), + [svntest.main.merge_notify_line(-4), 'U ' + os.path.join(short_D_path, "G", "rho") + '\n'], @@ -6265,7 +6265,7 @@ # path 'A_COPY/D/H/omega', so all the merge info elides. os.chdir(svntest.main.work_dir) svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(5), + [svntest.main.merge_notify_line(-5), ' U ' + short_other_omega_path + \ '\n'], [], 'merge', '-c-5', sbox.repo_url + '/A_COPY/B/E/beta', @@ -6284,7 +6284,7 @@ def merge_r4_into_Other_A_D_H_omega(): os.chdir(svntest.main.work_dir) svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(4)], + [svntest.main.merge_notify_line(-4)], [], 'merge', '-c-4', sbox.repo_url + '/A_COPY/D/H/omega', short_other_omega_path) @@ -6314,7 +6314,7 @@ # since that path doesn't exist in A/D/H/omeaga's nearest ancestor. os.chdir(svntest.main.work_dir) svntest.actions.run_and_verify_svn(None, - [svntest.main.merge_notify_line(5), + [svntest.main.merge_notify_line(-5), ' U ' + short_other_omega_path + \ '\n'], [], 'merge', '-c-5', sbox.repo_url + '/A_COPY/B/E/beta', Index: subversion/tests/libsvn_subr/mergeinfo-test.c =================================================================== --- subversion/tests/libsvn_subr/mergeinfo-test.c (revision 25819) +++ subversion/tests/libsvn_subr/mergeinfo-test.c (working copy) @@ -109,9 +109,9 @@ /* First ranges from the paths identified by mergeinfo_paths. */ static svn_merge_range_t mergeinfo_ranges[NBR_MERGEINFO_VALS] = { - { 1, 1 }, - { 1, 6 }, - { 5, 5 } + { 0, 1 }, + { 0, 6 }, + { 4, 5 } }; static svn_error_t * @@ -204,17 +204,17 @@ resultrange = APR_ARRAY_IDX(result, 0, svn_merge_range_t *); - if (resultrange->start != 5 || resultrange->end != 5) + if (resultrange->start != 4 || resultrange->end != 5) return fail(pool, "Range combining produced wrong result"); resultrange = APR_ARRAY_IDX(result, 1, svn_merge_range_t *); - if (resultrange->start != 7 || resultrange->end != 11) + if (resultrange->start != 6 || resultrange->end != 11) return fail(pool, "Range combining produced wrong result"); resultrange = APR_ARRAY_IDX(result, 2, svn_merge_range_t *); - if (resultrange->start != 13 || resultrange->end != 14) + if (resultrange->start != 12 || resultrange->end != 14) return fail(pool, "Range combining produced wrong result"); return SVN_NO_ERROR; @@ -353,9 +353,9 @@ { apr_hash_t *deleted, *added, *from, *to; svn_merge_range_t expected_rangelist_deletions[NBR_RANGELIST_DELTAS] = - { {7, 7}, {9, 9}, {11, 11}, {33, 34} }; + { {6, 7}, {8, 9}, {10, 11}, {32, 34} }; svn_merge_range_t expected_rangelist_additions[NBR_RANGELIST_DELTAS] = - { {2, 2}, {5, 6}, {13, 16}, {30, 30} }; + { {1, 2}, {4, 6}, {12, 16}, {29, 30} }; *msg = "diff of mergeinfo"; if (msg_only) @@ -382,7 +382,7 @@ apr_pool_t *pool) { apr_array_header_t *rangelist; - svn_merge_range_t expected_rangelist[3] = { {10, 10}, {7, 5}, {3, 3} }; + svn_merge_range_t expected_rangelist[3] = { {10, 9}, {7, 4}, {3, 2} }; *msg = "reversal of rangelist"; if (msg_only) @@ -460,7 +460,7 @@ { apr_array_header_t *rangelist1, *rangelist2, *intersection; svn_merge_range_t expected_intersection[4] = - { {1, 1}, {3, 4}, {12, 12}, {31, 32} }; + { {0, 1}, {2, 4}, {11, 12}, {30, 32} }; *msg = "intersection of rangelists"; if (msg_only) @@ -509,7 +509,7 @@ resultrange = APR_ARRAY_IDX(result, 0, svn_merge_range_t *); - if (resultrange->start != 8 || resultrange->end != 12) + if (resultrange->start != 7 || resultrange->end != 12) return fail(pool, "Range combining produced wrong result"); result = apr_hash_get(info1, "/trunk", APR_HASH_KEY_STRING); @@ -523,12 +523,12 @@ resultrange = APR_ARRAY_IDX(result, 0, svn_merge_range_t *); - if (resultrange->start != 1 || resultrange->end != 11) + if (resultrange->start != 0 || resultrange->end != 11) return fail(pool, "Range combining produced wrong result"); resultrange = APR_ARRAY_IDX(result, 1, svn_merge_range_t *); - if (resultrange->start != 13 || resultrange->end != 14) + if (resultrange->start != 12 || resultrange->end != 14) return fail(pool, "Range combining produced wrong result"); return SVN_NO_ERROR; @@ -611,7 +611,7 @@ { apr_hash_t *output, *whiteboard, *eraser; svn_merge_range_t expected_rangelist_remainder[NBR_RANGELIST_DELTAS] = - { {7, 7}, {9, 9}, {11, 11}, {33, 34} }; + { {6, 7}, {8, 9}, {10, 11}, {32, 34} }; *msg = "remove of mergeinfo"; if (msg_only)