Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2E737712E for ; Thu, 25 Aug 2011 12:58:25 +0000 (UTC) Received: (qmail 63849 invoked by uid 500); 25 Aug 2011 12:58:25 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 63754 invoked by uid 500); 25 Aug 2011 12:58:24 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 63747 invoked by uid 99); 25 Aug 2011 12:58:23 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 25 Aug 2011 12:58:23 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 25 Aug 2011 12:58:20 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 9F1A623889D5 for ; Thu, 25 Aug 2011 12:58:00 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1161547 - in /subversion/branches/1.7.x: ./ STATUS subversion/libsvn_client/merge.c subversion/tests/cmdline/merge_authz_tests.py subversion/tests/cmdline/merge_reintegrate_tests.py subversion/tests/cmdline/merge_tests.py Date: Thu, 25 Aug 2011 12:58:00 -0000 To: commits@subversion.apache.org From: hwright@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110825125800.9F1A623889D5@eris.apache.org> Author: hwright Date: Thu Aug 25 12:57:59 2011 New Revision: 1161547 URL: http://svn.apache.org/viewvc?rev=1161547&view=rev Log: Reintegrate the 1.7.x-issue3975 branch: * r1152809, r1152267, r1152286, r1160756 Fixes issue #3975 'adds with explicit mergeinfo don't get mergeinfo describing merge which added them'. Justification: Avoid repeat merges and possible spurious conflicts in merges subsequent to one which adds a subtree with its own explicit mergeinfo. Since merge tracking's raison d'être is keeping track of what's been merged and thus avoiding repeat merges and the possible conflicts that go with them, this is a *bit* of a problem. Branch: branches/1.7.x-issue3975 Notes: r1152809 is a comment only change made to avoid a conflict with r1160756. r1152267 and r1152286 is a new test for issue #3975 and a tweak to that test respectively. r1160756 is the reintegration of the branch ^/subversion/branches/issue-3975, where the actual fixes were made. Votes: +1: pburba, rhuijben, philip Modified: subversion/branches/1.7.x/ (props changed) subversion/branches/1.7.x/STATUS subversion/branches/1.7.x/subversion/libsvn_client/merge.c subversion/branches/1.7.x/subversion/tests/cmdline/merge_authz_tests.py subversion/branches/1.7.x/subversion/tests/cmdline/merge_reintegrate_tests.py subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py Propchange: subversion/branches/1.7.x/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Aug 25 12:57:59 2011 @@ -1,6 +1,7 @@ /subversion/branches/1.5.x-r30215:870312 /subversion/branches/1.7.x-JavaHL-pools:1158684-1158722 /subversion/branches/1.7.x-issue3888:1148937-1149162 +/subversion/branches/1.7.x-issue3975:1160761-1161546 /subversion/branches/1.7.x-neon-default:1148803-1158680 /subversion/branches/1.7.x-r1152189:1152759-1154249 /subversion/branches/1.7.x-r1155160:1158704-1159223 @@ -37,6 +38,7 @@ /subversion/branches/issue-3242-dev:879653-896436 /subversion/branches/issue-3334-dirs:875156-875867 /subversion/branches/issue-3668-3669:1031000-1035744 +/subversion/branches/issue-3975:1152931-1160746 /subversion/branches/kwallet:870785-871314 /subversion/branches/log-g-performance:870941-871032 /subversion/branches/merge-skips-obstructions:874525-874615 @@ -59,4 +61,4 @@ /subversion/branches/tree-conflicts:868291-873154 /subversion/branches/tree-conflicts-notify:873926-874008 /subversion/branches/uris-as-urls:1060426-1064427 -/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148853,1148877,1148882,1148936,1149105,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151906,1151911,1152129,1152140,1152189-1152190,1152282,1152726,1153138,1153141,1153416,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,1156098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,115 8201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158924,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705,1161080,1161185 +/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148853,1148877,1148882,1148936,1149105,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151906,1151911,1152129,1152140,1152189-1152190,1152267,1152282,1152286,1152726,1152809,1153138,1153141,1153416,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,1156098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,115 8193-1158194,1158196,1158201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158924,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705,1160756,1161080,1161185 Modified: subversion/branches/1.7.x/STATUS URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1161547&r1=1161546&r2=1161547&view=diff ============================================================================== --- subversion/branches/1.7.x/STATUS (original) +++ subversion/branches/1.7.x/STATUS Thu Aug 25 12:57:59 2011 @@ -71,23 +71,3 @@ Veto-blocked changes: Approved changes: ================= - - * r1152809, r1152267, r1152286, r1160756 - Fixes issue #3975 'adds with explicit mergeinfo don't get mergeinfo - describing merge which added them'. - Justification: - Avoid repeat merges and possible spurious conflicts in merges subsequent - to one which adds a subtree with its own explicit mergeinfo. Since - merge tracking's raison d'être is keeping track of what's been merged and - thus avoiding repeat merges and the possible conflicts that go with - them, this is a *bit* of a problem. - Branch: - branches/1.7.x-issue3975 - Notes: - r1152809 is a comment only change made to avoid a conflict with - r1160756. r1152267 and r1152286 is a new test for issue #3975 - and a tweak to that test respectively. r1160756 is the reintegration - of the branch ^/subversion/branches/issue-3975, where the actual fixes - were made. - Votes: - +1: pburba, rhuijben, philip Modified: subversion/branches/1.7.x/subversion/libsvn_client/merge.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_client/merge.c?rev=1161547&r1=1161546&r2=1161547&view=diff ============================================================================== --- subversion/branches/1.7.x/subversion/libsvn_client/merge.c (original) +++ subversion/branches/1.7.x/subversion/libsvn_client/merge.c Thu Aug 25 12:57:59 2011 @@ -4448,7 +4448,8 @@ populate_remaining_ranges(apr_array_head /* Helper for record_mergeinfo_for_dir_merge(). Adjust, in place, the inheritability of the ranges in RANGELIST to - describe a merge of RANGELIST into WC_WCPATH at depth DEPTH. + describe a merge of RANGELIST into WC_WCPATH at depth DEPTH. Set + *RANGELIST_INHERITANCE to the inheritability set. WC_PATH_IS_MERGE_TARGET is true if WC_PATH is the target of the merge, otherwise WC_PATH is a subtree. @@ -4460,6 +4461,7 @@ populate_remaining_ranges(apr_array_head Perform any temporary allocations in SCRATCH_POOL. */ static svn_error_t * calculate_merge_inheritance(apr_array_header_t *rangelist, + svn_boolean_t *rangelist_inheritance, const char *local_abspath, svn_boolean_t wc_path_is_merge_target, svn_boolean_t wc_path_has_missing_child, @@ -4471,6 +4473,10 @@ calculate_merge_inheritance(apr_array_he SVN_ERR(svn_wc_read_kind(&path_kind, wc_ctx, local_abspath, FALSE, scratch_pool)); + + /* Starting assumption. */ + *rangelist_inheritance = TRUE; + if (path_kind == svn_node_file) { /* Files *never* have non-inheritable mergeinfo. */ @@ -4483,17 +4489,27 @@ calculate_merge_inheritance(apr_array_he if (wc_path_has_missing_child || depth == svn_depth_files || depth == svn_depth_empty) - svn_rangelist__set_inheritance(rangelist, FALSE); + { + svn_rangelist__set_inheritance(rangelist, FALSE); + *rangelist_inheritance = FALSE; + } else /* depth == svn_depth_files || depth == svn_depth_empty */ - svn_rangelist__set_inheritance(rangelist, TRUE); + { + svn_rangelist__set_inheritance(rangelist, TRUE); + } } else /* WC_PATH is a directory subtree of the target. */ { if (wc_path_has_missing_child || depth == svn_depth_immediates) - svn_rangelist__set_inheritance(rangelist, FALSE); + { + svn_rangelist__set_inheritance(rangelist, FALSE); + *rangelist_inheritance = FALSE; + } else /* depth == infinity */ - svn_rangelist__set_inheritance(rangelist, TRUE); + { + svn_rangelist__set_inheritance(rangelist, TRUE); + } } } return SVN_NO_ERROR; @@ -7568,6 +7584,7 @@ record_mergeinfo_for_dir_merge(svn_merge else /* Record mergeinfo on CHILD. */ { svn_boolean_t child_is_deleted; + svn_boolean_t rangelist_inheritance; /* If CHILD is deleted we don't need to set mergeinfo on it. */ SVN_ERR(svn_wc__node_is_status_deleted(&child_is_deleted, @@ -7630,6 +7647,7 @@ record_mergeinfo_for_dir_merge(svn_merge continue; SVN_ERR(calculate_merge_inheritance(child_merge_rangelist, + &rangelist_inheritance, child->abspath, i == 0, child->missing_child, @@ -7663,6 +7681,66 @@ record_mergeinfo_for_dir_merge(svn_merge } child_merges = apr_hash_make(iterpool); + + /* If CHILD is the merge target we then know that the mergeinfo + described by MERGE_SOURCE_PATH:MERGED_RANGE->START- + MERGED_RANGE->END describes existent path-revs in the repository, + see normalize_merge_sources() and the global comment + 'MERGEINFO MERGE SOURCE NORMALIZATION'. + + If CHILD is a subtree of the merge target however, then no such + guarantee holds. The mergeinfo described by + (MERGE_SOURCE_PATH + CHILD_REPOS_PATH):MERGED_RANGE->START- + MERGED_RANGE->END might contain merge sources which don't + exist or refer to unrelated lines of history. */ + if (i > 0 + && (!merge_b->record_only || merge_b->reintegrate_merge) + && (!is_rollback)) + { + svn_opt_revision_t peg_revision; + svn_mergeinfo_t subtree_history_as_mergeinfo; + apr_array_header_t *child_merge_src_rangelist; + const char *old_session_url; + const char *subtree_mergeinfo_url = + svn_path_url_add_component2(merge_b->repos_root_url, + child_merge_src_canon_path + 1, + iterpool); + + /* Confirm that the naive mergeinfo we want to set on + CHILD->ABSPATH both exists and is part of + (MERGE_SOURCE_PATH+CHILD_REPOS_PATH)@MERGED_RANGE->END's + history. */ + peg_revision.kind = svn_opt_revision_number; + + /* We know MERGED_RANGE->END is younger than MERGE_RANGE->START + because we only do this for forward merges. */ + peg_revision.value.number = merged_range->end; + SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, + merge_b->ra_session2, + subtree_mergeinfo_url, + iterpool)); + SVN_ERR(svn_client__get_history_as_mergeinfo( + &subtree_history_as_mergeinfo, NULL, + subtree_mergeinfo_url, &peg_revision, + MAX(merged_range->start, merged_range->end), + MIN(merged_range->start, merged_range->end), + merge_b->ra_session2, merge_b->ctx, iterpool)); + + if (old_session_url) + SVN_ERR(svn_ra_reparent(merge_b->ra_session2, + old_session_url, iterpool)); + child_merge_src_rangelist = apr_hash_get( + subtree_history_as_mergeinfo, + child_merge_src_canon_path, + APR_HASH_KEY_STRING); + SVN_ERR(svn_rangelist_intersect(&child_merge_rangelist, + child_merge_rangelist, + child_merge_src_rangelist, + FALSE, iterpool)); + if (!rangelist_inheritance) + svn_rangelist__set_inheritance(child_merge_rangelist, FALSE); + } + apr_hash_set(child_merges, child->abspath, APR_HASH_KEY_STRING, child_merge_rangelist); SVN_ERR(update_wc_mergeinfo(result_catalog, @@ -7716,15 +7794,11 @@ record_mergeinfo_for_dir_merge(svn_merge /* Helper for do_directory_merge(). - Similar to record_mergeinfo_for_dir_merge in that it records mergeinfo - describing a merge of MERGED_RANGE->START:MERGED_RANGE->END from the - repository relative path MERGEINFO_PATH to MERGE->TARGET_ABSPATH. - Unlike record_mergeinfo_for_dir_merge() though, this - funtion only records mergeinfo on *new* subtrees added by the merge which - are children of paths with non-inheritable ranges or which have missing - siblings - see criteria 3 and 5 in the doc string for get_mergeinfo_paths. - See also issue #2829 - http://subversion.tigris.org/issues/show_bug.cgi?id=2829#desc14. + Record mergeinfo describing a merge of + MERGED_RANGE->START:MERGED_RANGE->END from the repository relative path + MERGEINFO_PATH to each path in NOTIFY_B->ADDED_ABSPATHS which has explicit + mergeinfo or is the immediate child of a parent with explicit + non-inheritable mergeinfo. DEPTH, NOTIFY_B, MERGE_B, and SQUELCH_MERGEINFO_NOTIFICATIONS, are cascaded from do_directory_merge's arguments of the same names. @@ -7758,34 +7832,48 @@ record_mergeinfo_for_added_subtrees( const char *added_abspath = svn__apr_hash_index_key(hi); const char *dir_abspath; svn_mergeinfo_t parent_mergeinfo; + svn_mergeinfo_t added_path_mergeinfo; svn_boolean_t inherited; /* used multiple times, but ignored */ apr_pool_clear(iterpool); dir_abspath = svn_dirent_dirname(added_abspath, iterpool); - /* Does ADDED_ABSPATH's immediate parent have non-inheritable - mergeinfo? */ - SVN_ERR(svn_client__get_wc_mergeinfo(&parent_mergeinfo, &inherited, + /* Grab the added path's explicit mergeinfo. */ + SVN_ERR(svn_client__get_wc_mergeinfo(&added_path_mergeinfo, &inherited, svn_mergeinfo_explicit, - dir_abspath, NULL, NULL, FALSE, - merge_b->ctx, - iterpool, iterpool)); - if (svn_mergeinfo__is_noninheritable(parent_mergeinfo, iterpool)) + added_abspath, NULL, NULL, FALSE, + merge_b->ctx, iterpool, iterpool)); + + /* If the added path doesn't have explicit mergeinfo, does its immediate + parent have non-inheritable mergeinfo? */ + if (!added_path_mergeinfo) + SVN_ERR(svn_client__get_wc_mergeinfo(&parent_mergeinfo, &inherited, + svn_mergeinfo_explicit, + dir_abspath, NULL, NULL, FALSE, + merge_b->ctx, + iterpool, iterpool)); + + if (added_path_mergeinfo + || svn_mergeinfo__is_noninheritable(parent_mergeinfo, iterpool)) { svn_client__merge_path_t *target_merge_path = APR_ARRAY_IDX(notify_b->children_with_mergeinfo, 0, svn_client__merge_path_t *); svn_merge_range_t *rng; svn_node_kind_t added_path_kind; - svn_mergeinfo_t merge_mergeinfo, added_path_mergeinfo; + svn_mergeinfo_t merge_mergeinfo; + svn_mergeinfo_t adds_history_as_mergeinfo; apr_array_header_t *rangelist; const char *rel_added_path; const char *added_path_mergeinfo_path; + const char *old_session_url; + const char *added_path_mergeinfo_url; + svn_opt_revision_t peg_revision; SVN_ERR(svn_wc_read_kind(&added_path_kind, merge_b->ctx->wc_ctx, added_abspath, FALSE, iterpool)); - /* Calculate the mergeinfo resulting from this merge. */ + /* Calculate the naive mergeinfo describing the merge. */ merge_mergeinfo = apr_hash_make(iterpool); rangelist = apr_array_make(iterpool, 1, sizeof(svn_merge_range_t *)); rng = svn_merge_range_dup(merged_range, iterpool); @@ -7812,14 +7900,46 @@ record_mergeinfo_for_added_subtrees( apr_hash_set(merge_mergeinfo, added_path_mergeinfo_path, APR_HASH_KEY_STRING, rangelist); - /* Get any explicit mergeinfo the added path has. */ - SVN_ERR(svn_client__get_wc_mergeinfo( - &added_path_mergeinfo, &inherited, - svn_mergeinfo_explicit, added_abspath, - NULL, NULL, FALSE, merge_b->ctx, iterpool, iterpool)); + /* Don't add new mergeinfo to describe the merge if that mergeinfo + contains non-existent merge sources. + + We know that MERGEINFO_PATH/rel_added_path's history does not + span MERGED_RANGE->START:MERGED_RANGE->END but rather that it + was added at some revions greater than MERGED_RANGE->START + (assuming this is a forward merge). It may have been added, + deleted, and re-added many times. The point is that we cannot + blindly apply the naive mergeinfo calculated above because it + will describe non-existent merge sources. To avoid this we get + take the intersection of the naive mergeinfo with + MERGEINFO_PATH/rel_added_path's history. */ + added_path_mergeinfo_url = + svn_path_url_add_component2(merge_b->repos_root_url, + added_path_mergeinfo_path + 1, + iterpool); + peg_revision.kind = svn_opt_revision_number; + peg_revision.value.number = MAX(merged_range->start, + merged_range->end); + SVN_ERR(svn_client__ensure_ra_session_url( + &old_session_url, merge_b->ra_session2, + added_path_mergeinfo_url, iterpool)); + SVN_ERR(svn_client__get_history_as_mergeinfo( + &adds_history_as_mergeinfo, NULL, + added_path_mergeinfo_url, &peg_revision, + MAX(merged_range->start, merged_range->end), + MIN(merged_range->start, merged_range->end), + merge_b->ra_session2, merge_b->ctx, iterpool)); + + if (old_session_url) + SVN_ERR(svn_ra_reparent(merge_b->ra_session2, + old_session_url, iterpool)); + + SVN_ERR(svn_mergeinfo_intersect2(&merge_mergeinfo, + merge_mergeinfo, + adds_history_as_mergeinfo, + FALSE, iterpool, iterpool)); /* Combine the explict mergeinfo on the added path (if any) - with the mergeinfo for this merge. */ + with the mergeinfo describing this merge. */ if (added_path_mergeinfo) SVN_ERR(svn_mergeinfo_merge(merge_mergeinfo, added_path_mergeinfo, iterpool)); Modified: subversion/branches/1.7.x/subversion/tests/cmdline/merge_authz_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/merge_authz_tests.py?rev=1161547&r1=1161546&r2=1161547&view=diff ============================================================================== --- subversion/branches/1.7.x/subversion/tests/cmdline/merge_authz_tests.py (original) +++ subversion/branches/1.7.x/subversion/tests/cmdline/merge_authz_tests.py Thu Aug 25 12:57:59 2011 @@ -420,7 +420,7 @@ def mergeinfo_and_skipped_paths(sbox): props={SVN_PROP_MERGEINFO : '/A/D/H/omega:8-9'}), 'chi' : Item("This is the file 'chi'.\n"), 'zeta' : Item("This is the file 'zeta'.\n", - props={SVN_PROP_MERGEINFO : '/A/D/H/zeta:8-9'}), + props={SVN_PROP_MERGEINFO : '/A/D/H/zeta:9'}), }) expected_skip = wc.State(A_COPY_2_H_path, {}) svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9', Modified: subversion/branches/1.7.x/subversion/tests/cmdline/merge_reintegrate_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1161547&r1=1161546&r2=1161547&view=diff ============================================================================== --- subversion/branches/1.7.x/subversion/tests/cmdline/merge_reintegrate_tests.py (original) +++ subversion/branches/1.7.x/subversion/tests/cmdline/merge_reintegrate_tests.py Thu Aug 25 12:57:59 2011 @@ -486,22 +486,9 @@ def reintegrate_with_rename(sbox): "" : Item(status=' M', wc_rev=9), }) k_expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-9'}) - - # Why do we expect mergeinfo of '/A_COPY/D/G/tauprime:2-9' on - # A/D/G/tauprime? Because this --reintegrate merge is effectively a - # two URL merge of %URL%/A@9 %URL%/A_COPY@9 to 'A'. Since %URL%/A@9 and - # %URL%/A_COPY@9 have a common ancestor in %URL%/A@1 we expect this 2-URL - # merge to record mergeinfo and a component of that mergeinfo describes - # the merge of %URL%/A_COPY@2 to %URL%/A_COPY@9. We see that above on - # A. But we also get it on A's subtrees with explicit mergeinfo, namely - # A/D/G/tauprime. Now I know what you are thinking, "'A_COPY/D/G/tauprime' - # doesn't even exist until r9!", and you are quite right. But this - # inheritance of bogus mergeinfo is a known problem, see - # http://subversion.tigris.org/issues/show_bug.cgi?id=3157#desc8, - # and is not what this test is about, so we won't fail because of it. k_expected_disk.add({ 'D/G/tauprime' : Item(props={SVN_PROP_MERGEINFO : - '/A/D/G/tau:2-7\n/A_COPY/D/G/tauprime:2-9'}, + '/A/D/G/tau:2-7\n/A_COPY/D/G/tauprime:9'}, contents="This is the file 'tau'.\n") }) expected_skip = wc.State(A_path, {}) @@ -1290,7 +1277,8 @@ def reintegrate_with_subtree_mergeinfo(s 'A ' + gamma_moved_COPY_path + '\n', 'D ' + gamma_COPY_path + '\n', ' U ' + A_COPY_path + '\n', - ' U ' + D_COPY_path + '\n',]), + ' U ' + D_COPY_path + '\n', + ' U ' + gamma_moved_COPY_path + '\n']), [], 'merge', sbox.repo_url + '/A', A_COPY_path) expected_output = wc.State( wc_dir, @@ -1365,7 +1353,7 @@ def reintegrate_with_subtree_mergeinfo(s '' : Item(status=' U'), 'mu' : Item(status=' G'), 'D' : Item(status=' U'), - 'D/gamma_moved' : Item(status=' G'), + 'D/gamma_moved' : Item(status=' U'), }) expected_elision_output = wc.State(A_path, { }) @@ -1423,8 +1411,7 @@ def reintegrate_with_subtree_mergeinfo(s # and is not what this test is about, so we won't fail because of it. 'D/gamma_moved' : Item( "Even newer content", props={SVN_PROP_MERGEINFO : - '/A/D/gamma_moved:2-15\n' - '/A_COPY/D/gamma_moved:2-19\n' + '/A_COPY/D/gamma_moved:17-19\n' '/A_COPY_3/D/gamma:9'}), 'D/H' : Item(), 'D/H/chi' : Item("This is the file 'chi'.\n"), @@ -2062,7 +2049,7 @@ def added_subtrees_with_mergeinfo_break_ 'C' : Item(), 'C/nu' : Item("Trunk work on nu.\n", props={SVN_PROP_MERGEINFO : - '/A_COPY/C/nu:16-18\n' + '/A_COPY/C/nu:13,16-18\n' '/A_COPY_2/C/nu:10'}), # <-- From cyclic # merge in r11 'D' : Item(), Modified: subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py?rev=1161547&r1=1161546&r2=1161547&view=diff ============================================================================== --- subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py (original) +++ subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py Thu Aug 25 12:57:59 2011 @@ -7681,7 +7681,7 @@ def merge_away_subtrees_noninheritable_r expected_output = svntest.verify.UnorderedOutput( [A_COPY_path + ' - /A:2-13*\n', mu_COPY_path + ' - /A/mu:2-13\n', - nu_COPY_path + ' - /A/nu:2-13\n',]) + nu_COPY_path + ' - /A/nu:10-13\n',]) svntest.actions.run_and_verify_svn(None, expected_output, [], 'pg', SVN_PROP_MERGEINFO, @@ -11582,24 +11582,7 @@ def dont_explicitly_record_implicit_merg svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir) wc_status.tweak(wc_rev=10) - # Now do a cherry harvest merge to 'A_copy'. We should pick up the - # change to 'A_copy/D/H/nu' from r10, the mergeinfo on 'A_copy' should - # reflect the entire eligible revision range from 'A', r2-10. - # 'A_copy/D/H/nu' should have get the equivalent mergeinfo to 'A_copy' - # which should elide to the latter, leaving no explicit mergeinfo... - # - # ...or should it? For the mergeinfo on ' A_copy/D/H/nu' to elide, it - # needs mergeinfo '/A/D/H/nu:2-10', but 'A/D/H/nu' doesn't exist prior to - # r6...Anyhow, regardless of what the mergeinfo on ' A_copy/D/H/nu' should - # be prior to elision, if we have the following conditions: - # - # 1) A uniform working revision merge target. - # - # 2) Explicit mergeinfo on the target/subtrees from the same - # source ('A' in this case). - # - # Then a cherry harvest from the same source should leave explicit - # mergeinfo *only* on the merge target no? + # Now do a cherry harvest merge to 'A_copy'. expected_output = wc.State(A_copy_path, { 'D/H/nu' : Item(status='U '), }) @@ -11608,7 +11591,6 @@ def dont_explicitly_record_implicit_merg 'D/H/nu' : Item(status=' U'), }) expected_elision_output = wc.State(A_copy_path, { - 'D/H/nu' : Item(status=' U'), }) expected_A_copy_status = wc.State(A_copy_path, { '' : Item(status=' M', wc_rev=10), @@ -11652,7 +11634,8 @@ def dont_explicitly_record_implicit_merg 'D/H/chi' : Item("This is the file 'chi'.\n"), 'D/H/psi' : Item("This is the file 'psi'.\n"), 'D/H/omega' : Item("This is the file 'omega'.\n"), - 'D/H/nu' : Item("Even nuer content"), + 'D/H/nu' : Item("Even nuer content", + props={SVN_PROP_MERGEINFO : '/A/D/H/nu:6-10'}), }) expected_A_copy_skip = wc.State(A_copy_path, {}) svntest.actions.run_and_verify_merge(A_copy_path, None, None, @@ -13975,7 +13958,7 @@ def no_self_referential_filtering_on_add 'B/E/beta' : Item("New content"), 'B/lambda' : Item("This is the file 'lambda'.\n"), 'B/F' : Item(), - 'C_MOVED' : Item(props={SVN_PROP_MERGEINFO : '/A/C_MOVED:3-10\n' + + 'C_MOVED' : Item(props={SVN_PROP_MERGEINFO : '/A/C_MOVED:10\n' + '/A_COPY/C:8\n' + '/A_COPY/C_MOVED:8', 'propname' : 'propval'}), @@ -16932,6 +16915,131 @@ def merged_deletion_causes_tree_conflict None, None, None, None, None, 1, False) +#---------------------------------------------------------------------- +# Test for issue #3975 'adds with explicit mergeinfo don't get mergeinfo +# describing merge which added them' +@Issue(3975) +@SkipUnless(server_has_mergeinfo) +def merge_adds_subtree_with_mergeinfo(sbox): + "merge adds subtree with mergeinfo" + + sbox.build() + wc_dir = sbox.wc_dir + wc_disk, wc_status = set_up_branch(sbox, False, 2) + + A_path = os.path.join(wc_dir, 'A') + nu_path = os.path.join(wc_dir, 'A', 'C', 'nu') + nu_COPY_path = os.path.join(wc_dir, 'A_COPY', 'C', 'nu') + A_COPY2_path = os.path.join(wc_dir, 'A_COPY_2') + + # r8 - Add the file A_COPY/C/nu. + svntest.main.file_write(nu_COPY_path, "This is the file 'nu'.\n") + svntest.actions.run_and_verify_svn(None, None, [], 'add', nu_COPY_path) + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'Add a file on the A_COPY branch', + wc_dir) + + # r9 - Cherry pick r8 from A_COPY to A. + svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir) + svntest.actions.run_and_verify_svn(None, None, [], 'merge', + sbox.repo_url + '/A_COPY', + A_path, '-c8') + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'Merge r8 from A_COPY to A', wc_dir) + + # r10 - Make a modification to A_COPY/C/nu + svntest.main.file_append(nu_COPY_path, + "More work on the A_COPY branch.\n") + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'Some work on the A_COPY branch', wc_dir) + + # r9 - Cherry pick r10 from A_COPY/C/nu to A/C/nu. Make some + # changes to A/C/nu before committing the merge. + svntest.actions.run_and_verify_svn(None, None, [], 'merge', + sbox.repo_url + '/A_COPY/C/nu', + nu_path, '-c10') + svntest.main.file_append(nu_path, "A faux conflict resolution.\n") + svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m', + 'Merge r8 from A_COPY to A', wc_dir) + + # Sync merge A to A_COPY_2 + svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir) + expected_output = wc.State(A_COPY2_path, { + 'B/E/beta' : Item(status='U '), + 'C/nu' : Item(status='A '), + 'D/G/rho' : Item(status='U '), + 'D/H/omega' : Item(status='U '), + 'D/H/psi' : Item(status='U '), + '' : Item(status=' U'), + }) + expected_mergeinfo_output = wc.State(A_COPY2_path, { + '' : Item(status=' G'), + 'C/nu' : Item(status=' U'), + }) + expected_elision_output = wc.State(A_COPY2_path, { + }) + expected_status = wc.State(A_COPY2_path, { + '' : Item(status=' M'), + 'B' : Item(status=' '), + 'mu' : Item(status=' '), + 'B/E' : Item(status=' '), + 'B/E/alpha' : Item(status=' '), + 'B/E/beta' : Item(status='M '), + 'B/lambda' : Item(status=' '), + 'B/F' : Item(status=' '), + 'C' : Item(status=' '), + 'C/nu' : Item(status='A ', copied='+'), + 'D' : Item(status=' '), + 'D/G' : Item(status=' '), + 'D/G/pi' : Item(status=' '), + 'D/G/rho' : Item(status='M '), + 'D/G/tau' : Item(status=' '), + 'D/gamma' : Item(status=' '), + 'D/H' : Item(status=' '), + 'D/H/chi' : Item(status=' '), + 'D/H/psi' : Item(status='M '), + 'D/H/omega' : Item(status='M '), + }) + expected_status.tweak(wc_rev=11) + expected_status.tweak('C/nu', wc_rev='-') + expected_disk = wc.State('', { + '' : Item(props={SVN_PROP_MERGEINFO : '/A:3-11\n/A_COPY:8'}), + 'B' : Item(), + 'mu' : Item("This is the file 'mu'.\n"), + 'B/E' : Item(), + 'B/E/alpha' : Item("This is the file 'alpha'.\n"), + 'B/E/beta' : Item("New content"), + 'B/lambda' : Item("This is the file 'lambda'.\n"), + 'B/F' : Item(), + 'C' : Item(), + 'C/nu' : Item("This is the file 'nu'.\n" \ + "More work on the A_COPY branch.\n" \ + "A faux conflict resolution.\n", + props={SVN_PROP_MERGEINFO : + '/A/C/nu:9-11\n/A_COPY/C/nu:10'}), + 'D' : Item(), + 'D/G' : Item(), + 'D/G/pi' : Item("This is the file 'pi'.\n"), + 'D/G/rho' : Item("New content"), + 'D/G/tau' : Item("This is the file 'tau'.\n"), + 'D/gamma' : Item("This is the file 'gamma'.\n"), + 'D/H' : Item(), + 'D/H/chi' : Item("This is the file 'chi'.\n"), + 'D/H/psi' : Item("New content"), + 'D/H/omega' : Item("New content"), + }) + expected_skip = wc.State('.', { }) + svntest.actions.run_and_verify_merge(A_COPY2_path, None, None, + sbox.repo_url + '/A', None, + expected_output, + expected_mergeinfo_output, + expected_elision_output, + expected_disk, + expected_status, + expected_skip, + None, None, None, None, + None, 1, False) + ######################################################################## # Run the tests @@ -17058,6 +17166,7 @@ test_list = [ None, foreign_repos_prop_conflict, reverse_merge_adds_subtree, merged_deletion_causes_tree_conflict, + merge_adds_subtree_with_mergeinfo, ] if __name__ == '__main__':