Author: pburba Date: Fri Dec 18 01:39:55 2009 New Revision: 892085 URL: http://svn.apache.org/viewvc?rev=892085&view=rev Log: Fix a reintegrate bug which can occur when the merge source has mergeinfo that explicitly describes common history with the reintegrate target.
We encountered this in our own repos, see http://svn.haxx.se/dev/archive-2009-12/0338.shtml. * subversion/libsvn_client/merge.c (find_unmerged_mergeinfo): Add an argument for the youngest common ancestor revision of the reintegrate target and source. Use the new arg to stop being fooled by "phantom" merges from the reintegrate target to the source. (calculate_left_hand_side): Always find the branch point of the reintegrate target and source, rather than only finding it if the source was never synced with the target. Pass this info to find_unmerged_mergeinfo(). * subversion/tests/cmdline/merge_tests.py (reintegrate_with_self_referential_mergeinfo): Adjust comment re failure status. (test_list): Remove XFail. 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=892085&r1=892084&r2=892085&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/merge.c (original) +++ subversion/trunk/subversion/libsvn_client/merge.c Fri Dec 18 01:39:55 2009 @@ -8561,6 +8561,9 @@ p...@target_rev. Effectively this is the mergeinfo catalog on the reintegrate target. + YC_ANCESTOR_REV is the revision of the youngest common ancestor of the + reintegrate source and the reintegrate target. + SOURCE_REPOS_REL_PATH is the path of the reintegrate source relative to the root of the repository. TARGET_REPOS_REL_PATH is the path of the reintegrate target relative to the root of the repository. @@ -8594,6 +8597,7 @@ find_unmerged_mergeinfo(svn_mergeinfo_catalog_t *unmerged_to_source_catalog, svn_boolean_t *never_synched, svn_revnum_t *youngest_merged_rev, + svn_revnum_t yc_ancestor_rev, svn_mergeinfo_catalog_t source_catalog, apr_hash_t *target_segments_hash, const char *source_repos_rel_path, @@ -8639,6 +8643,16 @@ segments, iterpool)); + /* Remove any target history that is also part of the source's history, + i.e. their common ancestry. By definition this has already been + "merged" from the target to the source. If the source has explict + self referential mergeinfo it would intersect with the target's + history below, making it appear that some merges had been done from + the target to the source, when this might not actually be the case. */ + SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges( + &target_history_as_mergeinfo, target_history_as_mergeinfo, + source_rev, yc_ancestor_rev, iterpool)); + /* Look for any explicit mergeinfo on the source path corresponding to the target path. If we find any remove that from SOURCE_CATALOG. When this iteration over TARGET_SEGMENTS_HASH is complete all that @@ -8925,6 +8939,9 @@ apr_hash_t *segments_hash = apr_hash_make(pool); svn_boolean_t never_synced; svn_revnum_t youngest_merged_rev; + const char *yc_ancestor_path; + const char *source_url; + const char *target_url; /* Get the history (segments) for the target and any of its subtrees with explicit mergeinfo. */ @@ -8945,6 +8962,26 @@ APR_HASH_KEY_STRING, segments); } + /* Check that source_...@source_rev and target_...@target_rev are + actually related, we can't reintegrate if they are not. Also + get an initial value for *REV_LEFT. */ + source_url = svn_path_url_add_component2(source_repos_root, + source_repos_rel_path, + subpool), + target_url = svn_path_url_add_component2(source_repos_root, + target_repos_rel_path, + subpool); + SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_path, + rev_left, + source_url, source_rev, + target_url, target_rev, + ctx, subpool)); + if (!(yc_ancestor_path && SVN_IS_VALID_REVNUM(*rev_left))) + return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL, + _("'%...@%ld' must be ancestrally related to " + "'%...@%ld'"), source_url, source_rev, + target_url, target_rev); + /* Get the mergeinfo from the source, including its descendants with differing explicit mergeinfo. */ APR_ARRAY_PUSH(source_repos_rel_path_as_array, const char *) @@ -8962,6 +8999,7 @@ SVN_ERR(find_unmerged_mergeinfo(&unmerged_catalog, &never_synced, &youngest_merged_rev, + *rev_left, mergeinfo_catalog, segments_hash, source_repos_rel_path, @@ -8981,24 +9019,6 @@ if (never_synced) { /* We never merged to the source. Just return the branch point. */ - const char *yc_ancestor_path, - *source_url = svn_path_url_add_component2(source_repos_root, - source_repos_rel_path, - subpool), - *target_url = svn_path_url_add_component2(source_repos_root, - target_repos_rel_path, - subpool); - - SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_path, - rev_left, - source_url, source_rev, - target_url, target_rev, - ctx, subpool)); - if (!(yc_ancestor_path && SVN_IS_VALID_REVNUM(*rev_left))) - return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL, - _("'%...@%ld' must be ancestrally related to " - "'%...@%ld'"), source_url, source_rev, - target_url, target_rev); *url_left = svn_path_url_add_component2(source_repos_root, yc_ancestor_path, pool); } Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=892085&r1=892084&r2=892085&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Fri Dec 18 01:39:55 2009 @@ -17165,6 +17165,10 @@ None, None, None, None, None, 1, 0) +# Test for a reintegrate bug which can occur when the merge source +# has mergeinfo that explicitly describes common history with the reintegrate +# target, see http://mail-archives.apache.org/mod_mbox/subversion-dev/ +# 200912.mbox/%[email protected]%3e def reintegrate_with_self_referential_mergeinfo(sbox): "source has target's history as explicit mergeinfo" @@ -17263,7 +17267,7 @@ 'D/H/omega' : Item("New content"), }) expected_skip = wc.State(A2_path, { }) - # Currently failing with this error: + # Previously failed with this error: # # svn merge ^/A2.1" A2 --reintegrate # ..\..\..\subversion\svn\merge-cmd.c:349: (apr_err=160013) @@ -17514,7 +17518,7 @@ XFail(committed_case_only_move_and_revert, is_fs_case_insensitive), merge_into_wc_for_deleted_branch, - XFail(reintegrate_with_self_referential_mergeinfo), + reintegrate_with_self_referential_mergeinfo, ] if __name__ == '__main__':
