Index: subversion/libsvn_client/merge.c =================================================================== --- subversion/libsvn_client/merge.c (revision 26929) +++ subversion/libsvn_client/merge.c (working copy) @@ -1758,62 +1758,73 @@ return SVN_NO_ERROR; } -/* Gets the smallest end_rev from all the ranges from remaining_ranges[0]. - * If all childs have empty remaining_ranges returns SVN_INVALID_REVNUM. - */ - -static svn_revnum_t -get_nearest_end_rev(apr_array_header_t *children_with_mergeinfo) +/* Gets the biggest/smallest start/end revisions from all the ranges + from CHILDREN_WITH_MERGEINFO->REMAINING_RANGES and store the value in the + appropriate svn_revnum_t * argument. If a svn_revnum_t * is NULL don't + look for that revision. If all children have empty remaining_ranges + set any desired svn_revnum_t * to SVN_INVALID_REVNUM. */ +static void +get_big_small_start_end_revs(svn_revnum_t *smallest_start_rev, + svn_revnum_t *biggest_start_rev, + svn_revnum_t *smallest_end_rev, + svn_revnum_t *biggest_end_rev, + apr_array_header_t *children_with_mergeinfo) { int i; - svn_revnum_t nearest_end_rev = SVN_INVALID_REVNUM; - for (i = 0; i < children_with_mergeinfo->nelts; i++) - { - svn_client__merge_path_t *child = - APR_ARRAY_IDX(children_with_mergeinfo, i, - svn_client__merge_path_t *); - if (!child || child->absent) - continue; - if (child->remaining_ranges->nelts > 0) - { - svn_merge_range_t *range = APR_ARRAY_IDX(child->remaining_ranges, 0, - svn_merge_range_t *); - if (nearest_end_rev == SVN_INVALID_REVNUM) - nearest_end_rev = range->end; - else if (range->end < nearest_end_rev) - nearest_end_rev = range->end; - } - } - return nearest_end_rev; -} + + if (smallest_start_rev) + *smallest_start_rev = SVN_INVALID_REVNUM; + + if (biggest_start_rev) + *biggest_start_rev = SVN_INVALID_REVNUM; + + if (smallest_end_rev) + *smallest_end_rev = SVN_INVALID_REVNUM; + + if (biggest_end_rev) + *biggest_end_rev = SVN_INVALID_REVNUM; -/* Gets the biggest end_rev from all the ranges from remaining_ranges[0]. - * If all childs have empty remaining_ranges returns SVN_INVALID_REVNUM. - */ - -static svn_revnum_t -get_farthest_end_rev(apr_array_header_t *children_with_mergeinfo) -{ - int i; - svn_revnum_t farthest_end_rev = SVN_INVALID_REVNUM; for (i = 0; i < children_with_mergeinfo->nelts; i++) { svn_client__merge_path_t *child = - APR_ARRAY_IDX(children_with_mergeinfo, i, - svn_client__merge_path_t *); + APR_ARRAY_IDX(children_with_mergeinfo, i, + svn_client__merge_path_t *); if (!child || child->absent) continue; if (child->remaining_ranges->nelts > 0) { svn_merge_range_t *range = APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *); - if (farthest_end_rev == SVN_INVALID_REVNUM) - farthest_end_rev = range->end; - else if (range->end > farthest_end_rev) - farthest_end_rev = range->end; + if (smallest_start_rev) + { + if (*smallest_start_rev == SVN_INVALID_REVNUM) + *smallest_start_rev = range->start; + else if (range->start < *smallest_start_rev) + *smallest_start_rev = range->start; + } + if (biggest_start_rev) + { + if (*biggest_start_rev == SVN_INVALID_REVNUM) + *biggest_start_rev = range->start; + else if (range->start > *biggest_start_rev) + *biggest_start_rev = range->start; + } + if (smallest_end_rev) + { + if (*smallest_end_rev == SVN_INVALID_REVNUM) + *smallest_end_rev = range->end; + else if (range->end < *smallest_end_rev) + *smallest_end_rev = range->end; + } + if (biggest_end_rev) + { + if (*biggest_end_rev == SVN_INVALID_REVNUM) + *biggest_end_rev = range->end; + else if (range->end > *biggest_end_rev) + *biggest_end_rev = range->end; + } } } - return farthest_end_rev; } /* If first item in each child of CHILDREN_WITH_MERGEINFO's @@ -3188,16 +3199,17 @@ is_rollback, adm_access, merge_b)); if (is_rollback) - end_rev = get_farthest_end_rev(children_with_mergeinfo); + get_big_small_start_end_revs(NULL, &start_rev, NULL, &end_rev, + children_with_mergeinfo); else - end_rev = get_nearest_end_rev(children_with_mergeinfo); - start_rev = rev1; + get_big_small_start_end_revs(&start_rev, NULL, &end_rev, NULL, + children_with_mergeinfo); iterpool = svn_pool_create(pool); while(end_rev != SVN_INVALID_REVNUM) { - svn_revnum_t next_end_rev; + svn_revnum_t next_end_rev, next_start_rev; svn_pool_clear(iterpool); /* Use persistent pool while playing with remaining_ranges. */ slice_remaining_ranges(children_with_mergeinfo, is_rollback, @@ -3208,11 +3220,16 @@ adm_access, depth, ignore_ancestry, &merge_callbacks, notify_b, merge_b, children_with_mergeinfo, iterpool)); remove_first_range_from_remaining_ranges(children_with_mergeinfo, pool); - next_end_rev = get_nearest_end_rev(children_with_mergeinfo); + if (is_rollback) - next_end_rev = get_farthest_end_rev(children_with_mergeinfo); + get_big_small_start_end_revs(NULL, &next_start_rev, + NULL, &next_end_rev, + children_with_mergeinfo); else - next_end_rev = get_nearest_end_rev(children_with_mergeinfo); + get_big_small_start_end_revs(&next_start_rev, NULL, + &next_end_rev, NULL, + children_with_mergeinfo); + if (next_end_rev != SVN_INVALID_REVNUM && is_path_conflicted_by_merge(merge_b)) { @@ -3224,7 +3241,7 @@ range.end = end_rev; break; } - start_rev = end_rev; + start_rev = next_start_rev; end_rev = next_end_rev; } Index: subversion/tests/cmdline/merge_tests.py =================================================================== --- subversion/tests/cmdline/merge_tests.py (revision 26929) +++ subversion/tests/cmdline/merge_tests.py (working copy) @@ -5672,7 +5672,7 @@ svntest.actions.run_and_verify_svn(None, ["property '" + SVN_PROP_MERGE_INFO + "' set on '" + A_COPY_D_path+ "'" + - "\n"], [], 'ps', SVN_PROP_MERGE_INFO, + "\n"], [], 'ps', SVN_PROP_MERGE_INFO, '/A/D:', A_COPY_D_path) svntest.actions.run_and_verify_svn(None, expected_merge_output(-4, @@ -8757,8 +8757,7 @@ single_file_replace_style_merge_capability, merge_to_out_of_date_target, merge_with_depth_files, - XFail(merge_fails_if_subtree_is_deleted_on_src, - svntest.main.is_os_windows), + merge_fails_if_subtree_is_deleted_on_src, no_mergeinfo_from_no_op_merge, merge_to_sparse_directories, merge_old_and_new_revs_from_renamed_dir,