Author: pburba
Date: Wed Jul 7 01:59:34 2010
New Revision: 961055
URL: http://svn.apache.org/viewvc?rev=961055&view=rev
Log:
Fix issue #3648 '2-URL merges incorrectly reverse-merge mergeinfo for merge
target' and issue #3671 'mergeinfo notifications for reintegrate and 2-URL
merges are overly verbose'.
* subversion/include/svn_mergeinfo.h
(svn_mergeinfo_catalog_merge): New.
* subversion/libsvn_subr/mergeinfo.c
(svn_mergeinfo_catalog_merge): New.
* subversion/libsvn_client/merge.c
(merge_props_changed): Filter out self-referential mergeinfo during
two-URL and reintegrate merges.
(update_wc_mergeinfo): Allow the option to return a mergeinfo catalog
describing the new mergeinfo which we want to record on the WC to
describe a merge, but without actually recording it. Improve the
doc string a bit too.
(record_skips): Update call to update_wc_mergeinfo(), passing NULL,
so no new behavior changes here.
(do_file_merge,
record_mergeinfo_for_dir_merge,
do_directory_merge,
do_merge):
Add a new mergeinfo catalog argument anlogous to update_wc_mergeinfo's new
arg, and pass it along.
(merge_cousins_and_supplement_mergeinfo): Update calls to do_merge. The
first time pass NULL, so nothing new there. But on the second two
record-only calls pass mergeinfo catalogs, then combine the catalogs,
and only then record them in the WC; this is the core of the issue #3648
fix.
(merge_locked,
merge_peg_locked):
Update calls to do_merge(), passing NULL, so no new behavior changes here.
* subversion/tests/cmdline/merge_authz_tests.py
(reintegrate_fails_if_no_root_access): Expect only one notification when
setting mergeinfo describing the merge (issue #3617).
* subversion/tests/cmdline/merge_reintegrate_tests.py
(basic merge --reintegrate support,
reintegrate_with_rename,
reintegrate_with_subtree_mergeinfo,
multiple_reintegrates_from_the_same_branch,
added_subtrees_with_mergeinfo_break_reintegrate,
two_URL_merge_removes_valid_mergefino_from_target): Expect only one
notification when setting mergeinfo describing the merge (issue #3617).
(test_list): Remove XFail from
two_URL_merge_removes_valid_mergefino_from_target.
A note about the changes above to the reintegrate and authz tests: Prior
to this change there is *only* one expected expected mergeinfo
notification output. That is because actions.run_and_verify_merge only
handles a single expected output per path-key and uses the last output
it finds in the actual output, which is the second ' G' notification.
With this change there is only one notification per path and it is
' U' (unless the application of the diff made a local change to the
path's mergeinfo).
* subversion/tests/cmdline/merge_tree_conflict_tests.py
(merge_replace_causes_tree_conflict): Expect only one notification when
setting mergeinfo describing the merge (issue #3617).
Modified:
subversion/trunk/subversion/include/svn_mergeinfo.h
subversion/trunk/subversion/libsvn_client/merge.c
subversion/trunk/subversion/libsvn_subr/mergeinfo.c
subversion/trunk/subversion/tests/cmdline/merge_authz_tests.py
subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
subversion/trunk/subversion/tests/cmdline/merge_tree_conflict_tests.py
Modified: subversion/trunk/subversion/include/svn_mergeinfo.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_mergeinfo.h?rev=961055&r1=961054&r2=961055&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_mergeinfo.h (original)
+++ subversion/trunk/subversion/include/svn_mergeinfo.h Wed Jul 7 01:59:34 2010
@@ -209,6 +209,21 @@ svn_error_t *
svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo, svn_mergeinfo_t changes,
apr_pool_t *pool);
+/** Combine one mergeinfo catalog, @a changes_catalog, into another mergeinfo
+ * catalog @a mergeinfo_catalog. If both catalogs have mergeinfo for the same
+ * key, use svn_mergeinfo_merge() to combine the mergeinfos.
+ *
+ * Additions to @a mergeinfo_catalog are deep copies allocated in
+ * @a result_pool. Temporary allocations are made in @a scratch_pool.
+ *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_mergeinfo_catalog_merge(svn_mergeinfo_catalog_t mergeinfo_catalog,
+ svn_mergeinfo_catalog_t changes_catalog,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/** Like svn_mergeinfo_remove2, but always considers inheritance.
*
* @deprecated Provided for backward compatibility with the 1.5 API.
Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=961055&r1=961054&r2=961055&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Wed Jul 7 01:59:34 2010
@@ -1126,8 +1126,12 @@ merge_props_changed(const char *local_di
int i;
/* If this is a forward merge then don't add new mergeinfo to
- PATH that is already part of PATH's own history. */
- if (merge_b->merge_source.rev1 < merge_b->merge_source.rev2)
+ PATH that is already part of PATH's own history, see
+ http://svn.haxx.se/dev/archive-2008-09/0006.shtml. If the
+ merge sources are not ancestral then there is no concept of a
+ 'forward' or 'reverse' merge and we filter unconditionally. */
+ if (merge_b->merge_source.rev1 < merge_b->merge_source.rev2
+ || !merge_b->sources_ancestral)
SVN_ERR(filter_self_referential_mergeinfo(&props,
local_abspath,
HONOR_MERGEINFO(merge_b),
@@ -4382,12 +4386,21 @@ calculate_merge_inheritance(apr_array_he
return SVN_NO_ERROR;
}
-/* Calculate the new mergeinfo for the target tree based on the merge
- info for TARGET_ABSPATH and MERGES (a mapping of absolute WC paths to
- rangelists), and record it in the WC (at, and possibly below,
- TARGET_ABSPATH). */
+/* Calculate the new mergeinfo for the target tree rooted at TARGET_ABSPATH
+ based on MERGES (a mapping of absolute WC paths to rangelists representing
+ a merge from the source REPOS_REL_PATH).
+
+ If RESULT_CATALOG is NULL, then record the new mergeinfo in the WC (at,
+ and possibly below, TARGET_ABSPATH).
+
+ If RESULT_CATALOG is not NULL, then don't record the new mergeinfo on the
+ WC, but instead record it in RESULT_CATALOG, where the keys are absolute
+ working copy paths and the values are the new mergeinfos for each.
+ Allocate additions to RESULT_CATALOG in pool which RESULT_CATALOG was
+ created in. */
static svn_error_t *
-update_wc_mergeinfo(const char *target_abspath,
+update_wc_mergeinfo(svn_mergeinfo_catalog_t result_catalog,
+ const char *target_abspath,
const char *repos_rel_path,
apr_hash_t *merges,
svn_boolean_t is_rollback,
@@ -4482,25 +4495,42 @@ update_wc_mergeinfo(const char *target_a
svn_mergeinfo__remove_empty_rangelists(mergeinfo, scratch_pool);
- err = svn_client__record_wc_mergeinfo(local_abspath, mergeinfo,
- TRUE, ctx, iterpool);
-
- if (err && err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
+ if (result_catalog)
{
- /* PATH isn't just missing, it's not even versioned as far
- as this working copy knows. But it was included in
- MERGES, which means that the server knows about it.
- Likely we don't have access to the source due to authz
- restrictions. For now just clear the error and
- continue...
-
- ### TODO: Set non-inheritable mergeinfo on PATH's immediate
- ### parent and normal mergeinfo on PATH's siblings which we
- ### do have access to. */
- svn_error_clear(err);
+ svn_mergeinfo_t existing_mergeinfo =
+ apr_hash_get(result_catalog, local_abspath, APR_HASH_KEY_STRING);
+ apr_pool_t *result_catalog_pool = apr_hash_pool_get(result_catalog);
+
+ if (existing_mergeinfo)
+ SVN_ERR(svn_mergeinfo_merge(mergeinfo, existing_mergeinfo,
+ result_catalog_pool));
+ apr_hash_set(result_catalog,
+ apr_pstrdup(result_catalog_pool, local_abspath),
+ APR_HASH_KEY_STRING,
+ svn_mergeinfo_dup(mergeinfo, result_catalog_pool));
}
else
- SVN_ERR(err);
+ {
+ err = svn_client__record_wc_mergeinfo(local_abspath, mergeinfo,
+ TRUE, ctx, iterpool);
+
+ if (err && err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
+ {
+ /* PATH isn't just missing, it's not even versioned as far
+ as this working copy knows. But it was included in
+ MERGES, which means that the server knows about it.
+ Likely we don't have access to the source due to authz
+ restrictions. For now just clear the error and
+ continue...
+
+ ### TODO: Set non-inheritable mergeinfo on PATH's immediate
+ ### parent and normal mergeinfo on PATH's siblings which we
+ ### do have access to. */
+ svn_error_clear(err);
+ }
+ else
+ SVN_ERR(err);
+ }
}
svn_pool_destroy(iterpool);
@@ -4575,7 +4605,7 @@ record_skips(const char *mergeinfo_path,
### skipped? */
;
}
- SVN_ERR(update_wc_mergeinfo(merge_b->target_abspath,
+ SVN_ERR(update_wc_mergeinfo(NULL, merge_b->target_abspath,
mergeinfo_path, merges,
is_rollback, merge_b->ctx, pool));
@@ -6342,11 +6372,18 @@ filter_natural_history_from_mergeinfo(ap
cousins thrice removed, etc...). (This is used to simulate the
history checks that the repository logic does in the directory case.)
+ If mergeinfo is being recorded to describe this merge, and RESULT_CATALOG
+ is not NULL, then don't record the new mergeinfo on the TARGET_ABSPATH,
+ but instead record it in RESULT_CATALOG, where the key is TARGET_ABSPATH
+ and the value is the new mergeinfo for that path. Allocate additions
+ to RESULT_CATALOG in pool which RESULT_CATALOG was created in.
+
Note: MERGE_B->RA_SESSION1 must be associated with URL1 and
MERGE_B->RA_SESSION2 with URL2.
*/
static svn_error_t *
-do_file_merge(const char *url1,
+do_file_merge(svn_mergeinfo_catalog_t result_catalog,
+ const char *url1,
svn_revnum_t revision1,
const char *url2,
svn_revnum_t revision2,
@@ -6681,8 +6718,8 @@ do_file_merge(const char *url1,
notify, subpool);
}
- SVN_ERR(update_wc_mergeinfo(target_abspath, mergeinfo_path,
- merges, is_rollback,
+ SVN_ERR(update_wc_mergeinfo(result_catalog, target_abspath,
+ mergeinfo_path, merges, is_rollback,
ctx, subpool));
}
}
@@ -7045,19 +7082,25 @@ get_inoperative_immediate_children(apr_h
/* Helper for do_directory_merge().
- Record mergeinfo describing a merge of MERGED_RANGE->START:
- MERGED_RANGE->END from the repository relative path MERGEINFO_PATH
- to the merge target (and possibly its subtrees) described by
- NOTIFY_B->CHILDREN_WITH_MERGEINFO -- see the global comment
+ If RESULT_CATALOG is NULL then record mergeinfo describing a merge of
+ MERGED_RANGE->START:MERGED_RANGE->END from the repository relative path
+ MERGEINFO_PATH to the merge target (and possibly its subtrees) described
+ by NOTIFY_B->CHILDREN_WITH_MERGEINFO -- see the global comment
'THE CHILDREN_WITH_MERGEINFO ARRAY'. Obviously this should only
- be called if recording mergeinfo -- see doc string for
- RECORD_MERGEINFO().
+ be called if recording mergeinfo -- see doc string for RECORD_MERGEINFO().
+
+ If RESULT_CATALOG is not NULL, then don't record the new mergeinfo on the
+ WC, but instead record it in RESULT_CATALOG, where the keys are absolute
+ working copy paths and the values are the new mergeinfos for each.
+ Allocate additions to RESULT_CATALOG in pool which RESULT_CATALOG was
+ created in.
DEPTH, NOTIFY_B, MERGE_B, and SQUELCH_MERGEINFO_NOTIFICATIONS are all
cascaded from do_directory_merge's arguments of the same names.
*/
static svn_error_t *
-record_mergeinfo_for_dir_merge(const svn_merge_range_t *merged_range,
+record_mergeinfo_for_dir_merge(svn_mergeinfo_catalog_t result_catalog,
+ const svn_merge_range_t *merged_range,
const char *mergeinfo_path,
svn_depth_t depth,
svn_boolean_t squelch_mergeinfo_notifications,
@@ -7267,7 +7310,8 @@ record_mergeinfo_for_dir_merge(const svn
child_merges = apr_hash_make(iterpool);
apr_hash_set(child_merges, child->abspath, APR_HASH_KEY_STRING,
child_merge_rangelist);
- SVN_ERR(update_wc_mergeinfo(child->abspath,
+ SVN_ERR(update_wc_mergeinfo(result_catalog,
+ child->abspath,
child_merge_src_canon_path,
child_merges, is_rollback,
merge_b->ctx, iterpool));
@@ -7767,6 +7811,12 @@ remove_noop_subtree_ranges(const char *u
svn_wc_notify_merge_record_info_begin notification before any mergeinfo
changes are made to describe the merge performed.
+ If mergeinfo is being recorded to describe this merge, and RESULT_CATALOG
+ is not NULL, then don't record the new mergeinfo on the WC, but instead
+ record it in RESULT_CATALOG, where the keys are absolute working copy
+ paths and the values are the new mergeinfos for each. Allocate additions
+ to RESULT_CATALOG in pool which RESULT_CATALOG was created in.
+
Handle DEPTH as documented for svn_client_merge3().
NOTE: This is a wrapper around drive_merge_report_editor() which
@@ -7775,7 +7825,8 @@ remove_noop_subtree_ranges(const char *u
meet one or more of the criteria described in get_mergeinfo_paths()).
*/
static svn_error_t *
-do_directory_merge(const char *url1,
+do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
+ const char *url1,
svn_revnum_t revision1,
const char *url2,
svn_revnum_t revision2,
@@ -8050,7 +8101,8 @@ do_directory_merge(const char *url1,
/* Record mergeinfo where appropriate.*/
if (record_mergeinfo)
{
- SVN_ERR(record_mergeinfo_for_dir_merge(&range,
+ SVN_ERR(record_mergeinfo_for_dir_merge(result_catalog,
+ &range,
mergeinfo_path,
depth,
squelch_mergeinfo_notifications,
@@ -8149,6 +8201,12 @@ ensure_ra_session_url(svn_ra_session_t *
notification before any mergeinfo changes are made to describe the merge
performed.
+ If mergeinfo is being recorded to describe this merge, and RESULT_CATALOG
+ is not NULL, then don't record the new mergeinfo on the WC, but instead
+ record it in RESULT_CATALOG, where the keys are absolute working copy
+ paths and the values are the new mergeinfos for each. Allocate additions
+ to RESULT_CATALOG in pool which RESULT_CATALOG was created in.
+
FORCE, DRY_RUN, RECORD_ONLY, IGNORE_ANCESTRY, DEPTH, MERGE_OPTIONS,
and CTX are as described in the docstring for svn_client_merge_peg3().
@@ -8166,6 +8224,7 @@ ensure_ra_session_url(svn_ra_session_t *
*/
static svn_error_t *
do_merge(apr_hash_t **modified_subtrees,
+ svn_mergeinfo_catalog_t result_catalog,
const apr_array_header_t *merge_sources,
const char *target_abspath,
svn_boolean_t sources_ancestral,
@@ -8323,7 +8382,8 @@ do_merge(apr_hash_t **modified_subtrees,
/* Call our merge helpers based on TARGET_ABSPATH's kind. */
if (target_kind == svn_node_file)
{
- SVN_ERR(do_file_merge(url1, rev1, url2, rev2, target_abspath,
+ SVN_ERR(do_file_merge(result_catalog,
+ url1, rev1, url2, rev2, target_abspath,
sources_related,
squelch_mergeinfo_notifications,
¬ify_baton,
@@ -8331,7 +8391,8 @@ do_merge(apr_hash_t **modified_subtrees,
}
else if (target_kind == svn_node_dir)
{
- SVN_ERR(do_directory_merge(url1, rev1, url2, rev2, target_abspath,
+ SVN_ERR(do_directory_merge(result_catalog,
+ url1, rev1, url2, rev2, target_abspath,
depth, squelch_mergeinfo_notifications,
¬ify_baton, &merge_cmd_baton,
subpool));
@@ -8478,7 +8539,7 @@ merge_cousins_and_supplement_mergeinfo(c
faux_source->rev1 = rev1;
faux_source->rev2 = rev2;
APR_ARRAY_PUSH(faux_sources, merge_source_t *) = faux_source;
- SVN_ERR(do_merge(&modified_subtrees, faux_sources, target_abspath,
+ SVN_ERR(do_merge(&modified_subtrees, NULL, faux_sources, target_abspath,
FALSE, TRUE, same_repos,
ignore_ancestry, force, dry_run, FALSE, NULL, TRUE,
FALSE, depth, merge_options, use_sleep, ctx,
@@ -8495,22 +8556,66 @@ merge_cousins_and_supplement_mergeinfo(c
pair of record-only merges using the real sources we've
calculated. (We know that each tong in our fork of our merge
source history tree has an ancestral relationship with the common
- ancestral, so we force ancestral=TRUE here.) */
+ ancestral, so we force ancestral=TRUE here.)
+
+ Issue #3648: We don't actually perform these two record-only merges
+ on the WC at first, but rather see what each would do and store that
+ in two mergeinfo catalogs. We then merge the catalogs together and
+ then record the result in the WC. This prevents the second record
+ only merge from removing legitimate mergeinfo history, from the same
+ source, that was made in prior merges. */
if (same_repos && !dry_run)
{
svn_wc_notify_t *notify = svn_wc_create_notify(
target_abspath, svn_wc_notify_merge_record_info_begin, pool);
+ svn_mergeinfo_catalog_t add_result_catalog = apr_hash_make(pool);
+ svn_mergeinfo_catalog_t remove_result_catalog = apr_hash_make(pool);
+
ctx->notify_func2(ctx->notify_baton2, notify, pool);
- SVN_ERR(do_merge(NULL, add_sources, target_abspath,
+ SVN_ERR(do_merge(NULL, add_result_catalog, add_sources, target_abspath,
TRUE, TRUE, same_repos,
ignore_ancestry, force, dry_run, TRUE,
modified_subtrees, TRUE,
TRUE, depth, merge_options, use_sleep, ctx, pool));
- SVN_ERR(do_merge(NULL, remove_sources, target_abspath,
- TRUE, TRUE, same_repos,
+ SVN_ERR(do_merge(NULL, remove_result_catalog, remove_sources,
+ target_abspath, TRUE, TRUE, same_repos,
ignore_ancestry, force, dry_run, TRUE,
modified_subtrees, TRUE,
TRUE, depth, merge_options, use_sleep, ctx, pool));
+ SVN_ERR(svn_mergeinfo_catalog_merge(add_result_catalog,
+ remove_result_catalog,
+ pool, pool));
+
+ if (apr_hash_count(add_result_catalog))
+ {
+ int i;
+ apr_array_header_t *sorted_cat;
+
+ sorted_cat = svn_sort__hash(add_result_catalog,
+ svn_sort_compare_items_as_paths, pool);
+ for (i = 0; i < sorted_cat->nelts; i++)
+ {
+ svn_sort__item_t elt = APR_ARRAY_IDX(sorted_cat, i,
+ svn_sort__item_t);
+ svn_error_t *err = svn_client__record_wc_mergeinfo(elt.key,
+ elt.value,
+ TRUE, ctx,
+ pool);
+
+ if (err && err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
+ {
+ /* PATH isn't just missing, it's not even versioned as far
+ as this working copy knows. But it was included in
+ MERGES, which means that the server knows about it.
+ Likely we don't have access to the source due to authz
+ restrictions. For now just clear the error and
+ continue... */
+ svn_error_clear(err);
+ }
+ else
+ SVN_ERR(err);
+ }
+ }
}
return SVN_NO_ERROR;
@@ -8756,7 +8861,7 @@ merge_locked(const char *source1,
/* Close our temporary RA sessions. */
svn_pool_destroy(sesspool);
- err = do_merge(NULL, merge_sources, target_abspath,
+ err = do_merge(NULL, NULL, merge_sources, target_abspath,
ancestral, related, same_repos,
ignore_ancestry, force, dry_run,
record_only, NULL, FALSE, FALSE, depth, merge_options,
@@ -10121,7 +10226,7 @@ merge_peg_locked(const char *source,
/* Do the real merge! (We say with confidence that our merge
sources are both ancestral and related.) */
- err = do_merge(NULL, merge_sources, target_abspath,
+ err = do_merge(NULL, NULL, merge_sources, target_abspath,
TRUE, TRUE, same_repos, ignore_ancestry, force, dry_run,
record_only, NULL, FALSE, FALSE, depth, merge_options,
&use_sleep, ctx, scratch_pool);
Modified: subversion/trunk/subversion/libsvn_subr/mergeinfo.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/mergeinfo.c?rev=961055&r1=961054&r2=961055&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/mergeinfo.c Wed Jul 7 01:59:34 2010
@@ -1344,6 +1344,69 @@ svn_mergeinfo_merge(svn_mergeinfo_t merg
}
svn_error_t *
+svn_mergeinfo_catalog_merge(svn_mergeinfo_catalog_t mergeinfo_cat,
+ svn_mergeinfo_catalog_t changes_cat,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i = 0;
+ int j = 0;
+ apr_array_header_t *sorted_cat =
+ svn_sort__hash(mergeinfo_cat, svn_sort_compare_items_as_paths,
+ scratch_pool);
+ apr_array_header_t *sorted_changes =
+ svn_sort__hash(changes_cat, svn_sort_compare_items_as_paths,
+ scratch_pool);
+
+ while (i < sorted_cat->nelts && j < sorted_changes->nelts)
+ {
+ svn_sort__item_t cat_elt, change_elt;
+ int res;
+
+ cat_elt = APR_ARRAY_IDX(sorted_cat, i, svn_sort__item_t);
+ change_elt = APR_ARRAY_IDX(sorted_changes, j, svn_sort__item_t);
+ res = svn_sort_compare_items_as_paths(&cat_elt, &change_elt);
+
+ if (res == 0) /* Both catalogs have mergeinfo for a give path. */
+ {
+ svn_mergeinfo_t mergeinfo = cat_elt.value;
+ svn_mergeinfo_t changes_mergeinfo = change_elt.value;
+
+ SVN_ERR(svn_mergeinfo_merge(mergeinfo, changes_mergeinfo,
+ result_pool));
+ apr_hash_set(mergeinfo_cat, cat_elt.key, cat_elt.klen, mergeinfo);
+ i++;
+ j++;
+ }
+ else if (res < 0) /* Only MERGEINFO_CAT has mergeinfo for this path. */
+ {
+ i++;
+ }
+ else /* Only CHANGES_CAT has mergeinfo for this path. */
+ {
+ apr_hash_set(mergeinfo_cat,
+ apr_pstrdup(result_pool, change_elt.key),
+ change_elt.klen,
+ svn_mergeinfo_dup(change_elt.value, result_pool));
+ j++;
+ }
+ }
+
+ /* Copy back any remaining elements from the CHANGES_CAT catalog. */
+ for (; j < sorted_changes->nelts; j++)
+ {
+ svn_sort__item_t elt = APR_ARRAY_IDX(sorted_changes, j,
+ svn_sort__item_t);
+ apr_hash_set(mergeinfo_cat,
+ apr_pstrdup(result_pool, elt.key),
+ elt.klen,
+ svn_mergeinfo_dup(elt.value, result_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_mergeinfo_intersect(svn_mergeinfo_t *mergeinfo,
svn_mergeinfo_t mergeinfo1,
svn_mergeinfo_t mergeinfo2,
Modified: subversion/trunk/subversion/tests/cmdline/merge_authz_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_authz_tests.py?rev=961055&r1=961054&r2=961055&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_authz_tests.py Wed Jul 7
01:59:34 2010
@@ -641,7 +641,7 @@ def reintegrate_fails_if_no_root_access(
'mu' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
})
expected_elision_output = wc.State(A_path, {
})
Modified: subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=961055&r1=961054&r2=961055&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py
(original)
+++ subversion/trunk/subversion/tests/cmdline/merge_reintegrate_tests.py Wed
Jul 7 01:59:34 2010
@@ -171,7 +171,7 @@ def basic_reintegrate(sbox):
'mu' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
})
expected_elision_output = wc.State(A_path, {
})
@@ -229,7 +229,7 @@ def basic_reintegrate(sbox):
'mu' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_MOVED_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
})
expected_elision_output = wc.State(A_MOVED_path, {
})
@@ -452,8 +452,8 @@ def reintegrate_with_rename(sbox):
'D/G/tauprime' : Item(status='A '),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
- 'D/G/tauprime' : Item(status=' G'),
+ '' : Item(status=' U'),
+ 'D/G/tauprime' : Item(status=' U'),
})
expected_elision_output = wc.State(A_path, {
})
@@ -1114,9 +1114,9 @@ def reintegrate_with_subtree_mergeinfo(s
'D' : Item(status=' U'),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
'mu' : Item(status=' G'),
- 'D' : Item(status=' G'),
+ 'D' : Item(status=' U'),
})
expected_elision_output = wc.State(A_path, {
})
@@ -1350,9 +1350,9 @@ def reintegrate_with_subtree_mergeinfo(s
'D/gamma_moved' : Item(status=' U'),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
'mu' : Item(status=' G'),
- 'D' : Item(status=' G'),
+ 'D' : Item(status=' U'),
'D/gamma_moved' : Item(status=' G'),
})
expected_elision_output = wc.State(A_path, {
@@ -1397,8 +1397,21 @@ def reintegrate_with_subtree_mergeinfo(s
'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"),
+ # 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_c...@9 to 'A'. Since %URL%/a...@9
and
+ # %URL%/a_c...@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_c...@2 to %URL%/a_c...@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.
'D/gamma_moved' : Item(
- "Even newer content", props={SVN_PROP_MERGEINFO :
+ "Even newer content", props={SVN_PROP_MERGEINFO :
+ '/A/D/gamma_moved:2-15\n'
'/A_COPY/D/gamma_moved:2-19\n'
'/A_COPY_3/D/gamma:9'}),
'D/H' : Item(),
@@ -1514,7 +1527,7 @@ def multiple_reintegrates_from_the_same_
'B/E/beta' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
})
expected_elision_output = wc.State(A_path, {
})
@@ -1983,7 +1996,7 @@ def added_subtrees_with_mergeinfo_break_
'C/nu' : Item(status=' U'),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
'C/nu' : Item(status=' G'),
})
expected_elision_output = wc.State(A_path, {
@@ -2178,7 +2191,7 @@ def two_URL_merge_removes_valid_mergefin
'B/lambda' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_COPY_2_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
})
expected_elision_output = wc.State(A_COPY_2_path, {
})
@@ -2262,7 +2275,7 @@ test_list = [ None,
server_has_mergeinfo),
reintegrate_with_self_referential_mergeinfo,
added_subtrees_with_mergeinfo_break_reintegrate,
- XFail(two_URL_merge_removes_valid_mergefino_from_target),
+ two_URL_merge_removes_valid_mergefino_from_target,
]
if __name__ == '__main__':
Modified: subversion/trunk/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=961055&r1=961054&r2=961055&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tree_conflict_tests.py
(original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tree_conflict_tests.py Wed
Jul 7 01:59:34 2010
@@ -1703,7 +1703,6 @@ def merge_replace_causes_tree_conflict(s
"--- Recording mergeinfo for merge between repository URLs into '" \
+ A + "':\n",
' U ' + A + '\n',
- ' G ' + A + '\n',
'Summary of conflicts:\n',
' Tree conflicts: 4\n',
])