[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Update on issue-2897 branch(non-reflective file changes getting merged!!!)

From: Kamesh Jayachandran <kamesh_at_collab.net>
Date: 2007-12-14 13:30:17 CET

Hi All,

Tasks are tracked via
http://svn.collab.net/repos/svn/branches/issue-2897/TODO-issue-2897.branch

Now I could extract the *non-reflected* change and apply that alone from
a reflective merge. See the attached patch.

The attached patch is still work in progress, most of the change is
getting the 'reflected_ranges' for a 'reflecive_range'
and make it available at the right place. *Sorry* I did not attach the
log message as I used to write one once completing the work.

For those curious about the extraction logic have a look at
'reflective_merge_file_changed' and the functions it calls.

Logic is very simple than originally thought,
Suppose if r6 is a reflective change of r3-5 from /trunk/test.c to
/fb/test.c + one adhoc change.
When we merge r6 from /fb to /trunk wc, this patch calls
'reflective_merge_file_changed'
with following arguments
older=/fb/test.c@5 (i.e prior to synch up or reflection)
yours=/fb/test.c@6 (i.e after synch up or reflection)
mine=WC/trunk/test.c

Just apply r3-5 from /trunk/test.c to 'older' and call our regular
'merge_file_changed', it will take care of the rest.

We have the 'merge_non_reflective_text_change' testcase, which passes
with this fix.

What is pending,
I need to implement other call backs and the testcase.
* reflective_merge_file_added,
* reflective_merge_file_deleted,
* reflective_merge_dir_added,
* reflective_merge_dir_deleted,
* reflective_merge_props_changed
* issues raised by David Glasser which is tracked in TODO-issue-2897.branch.
* More self review.

Thanks,

With regards
Kamesh Jayachandran

Index: subversion/libsvn_client/repos_diff.c
===================================================================
--- subversion/libsvn_client/repos_diff.c (revision 28477)
+++ subversion/libsvn_client/repos_diff.c (working copy)
@@ -835,11 +835,16 @@
 
       if (!is_replace)
         {
- notify = svn_wc_create_notify(b->wcpath, action, pool);
- notify->kind = svn_node_file;
- notify->content_state = content_state;
- notify->prop_state = prop_state;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
+ if (!(b->added
+ && content_state == svn_wc_notify_state_unchanged
+ && prop_state == svn_wc_notify_state_unchanged))
+ {
+ notify = svn_wc_create_notify(b->wcpath, action, pool);
+ notify->kind = svn_node_file;
+ notify->content_state = content_state;
+ notify->prop_state = prop_state;
+ (*eb->notify_func)(eb->notify_baton, notify, pool);
+ }
         }
     }
 
Index: subversion/libsvn_client/merge.c
===================================================================
--- subversion/libsvn_client/merge.c (revision 28477)
+++ subversion/libsvn_client/merge.c (working copy)
@@ -218,15 +218,27 @@
      as needed. */
   svn_ra_session_t *ra_session1;
   svn_ra_session_t *ra_session2;
+ svn_ra_session_t *target_ra_session;
 
   /* Flag indicating the fact target has everything merged already,
      for the sake of children's merge to work it sets itself a dummy
      merge range of requested_end_rev:requested_end_rev. */
   svn_boolean_t target_has_dummy_merge_range;
 
+ /* reflected_ranges is set for each merge range if the merge is reflective.*/
+ apr_array_header_t *reflected_ranges;
   apr_pool_t *pool;
 } merge_cmd_baton_t;
 
+typedef struct remaining_range_info_t {
+ /* Subset of requested merge range. */
+ svn_merge_range_t *range;
+ /* If reflected_ranges is not NULL then above 'range' is a
+ reflective range of it. */
+ apr_array_header_t *reflected_ranges;
+} remaining_range_info_t;
+
+
 apr_hash_t *
 svn_client__dry_run_deletions(void *merge_cmd_baton)
 {
@@ -366,6 +378,87 @@
   return err;
 }
 
+/* Gets the file at URL_TO_FILE at revision REVISION
+ and stores it in *FILENAME. All allocation occurs in POOL.*/
+static svn_error_t *
+get_file_from_ra(const char **filename, const char *path,
+ svn_revnum_t revision, svn_ra_session_t *ra_session,
+ apr_pool_t *pool)
+{
+ apr_file_t *file;
+ svn_stream_t *fstream;
+ const char *temp_dir;
+
+ SVN_ERR(svn_io_temp_dir(&temp_dir, pool));
+ SVN_ERR(svn_io_open_unique_file2(&file, filename,
+ svn_path_join(temp_dir, "tmp", pool),
+ "", svn_io_file_del_on_pool_cleanup, pool));
+
+ fstream = svn_stream_from_aprfile(file, pool);
+ SVN_ERR(svn_ra_get_file(ra_session, path, revision, fstream,
+ NULL, NULL, pool));
+ SVN_ERR(svn_io_file_close(file, pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* merges MERGE_B->reflected_ranges from MERGE_B->target url to OLDER.*/
+static svn_error_t *
+merge_reflected_ranges_b4_reflecting(const char *older,
+ const char *file_path_relative_to_target,
+ merge_cmd_baton_t *merge_b,
+ apr_pool_t *pool)
+{
+ int i;
+ svn_diff_file_options_t *options;
+ const char *target_marker = "<<<<<<< .working";
+ const char *left_marker = "||||||| .old";
+ const char *right_marker = ">>>>>>> .new";
+ const char *temp_dir;
+ SVN_ERR(svn_io_temp_dir(&temp_dir, pool));
+
+ if (merge_b->merge_options)
+ SVN_ERR(svn_diff_file_options_parse(options,
+ merge_b->merge_options, pool));
+ else
+ options = svn_diff_file_options_create(pool);
+ for (i = 0; i < merge_b->reflected_ranges->nelts; i++)
+ {
+ svn_diff_t *diff;
+ const char *left, *right, *result_target;
+ svn_merge_range_t *range;
+ svn_stream_t *ostream;
+ apr_file_t *result_f;
+ SVN_ERR(svn_io_open_unique_file2(&result_f, &result_target,
+ svn_path_join(temp_dir, "tmp", pool),
+ "", svn_io_file_del_on_pool_cleanup,
+ pool));
+ ostream = svn_stream_from_aprfile(result_f, pool);
+ range = APR_ARRAY_IDX(merge_b->reflected_ranges, i, svn_merge_range_t *);
+ SVN_ERR(get_file_from_ra(&left, file_path_relative_to_target,
+ range->start, merge_b->target_ra_session,
+ pool));
+ SVN_ERR(get_file_from_ra(&right, file_path_relative_to_target,
+ range->end, merge_b->target_ra_session, pool));
+ SVN_ERR(svn_diff_file_diff3_2(&diff, left, older, right,
+ options, pool));
+ SVN_ERR(svn_diff_file_output_merge(ostream, diff,
+ left, older, right,
+ left_marker,
+ target_marker,
+ right_marker,
+ "=======", /* seperator */
+ FALSE, /* display original */
+ FALSE, /* resolve conflicts */
+ pool));
+ SVN_ERR(svn_stream_close(ostream));
+ SVN_ERR(svn_io_file_flush_to_disk(result_f, pool));
+
+ SVN_ERR(svn_io_copy_file(result_target, older, TRUE, pool));
+ }
+ return SVN_NO_ERROR;
+}
+
 /* A svn_wc_diff_callbacks2_t function. */
 static svn_error_t *
 merge_file_changed(svn_wc_adm_access_t *adm_access,
@@ -533,6 +626,142 @@
 
 /* A svn_wc_diff_callbacks2_t function. */
 static svn_error_t *
+reflective_merge_file_changed(svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *content_state,
+ svn_wc_notify_state_t *prop_state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ svn_revnum_t older_rev,
+ svn_revnum_t yours_rev,
+ const char *mimetype1,
+ const char *mimetype2,
+ const apr_array_header_t *prop_changes,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ merge_cmd_baton_t *merge_b = baton;
+ apr_pool_t *subpool = svn_pool_create(merge_b->pool);
+ const char *file_path_relative_to_target;
+
+ file_path_relative_to_target = mine + strlen(merge_b->target) + 1;
+ SVN_ERR(merge_reflected_ranges_b4_reflecting(older,
+ file_path_relative_to_target,
+ merge_b, subpool));
+ svn_pool_destroy(subpool);
+ return merge_file_changed(adm_access, content_state, prop_state,
+ mine, older, yours, older_rev, yours_rev,
+ mimetype1, mimetype2, prop_changes,
+ original_props, baton);
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+reflective_merge_file_added(svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *content_state,
+ svn_wc_notify_state_t *prop_state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ svn_revnum_t rev1,
+ svn_revnum_t rev2,
+ const char *mimetype1,
+ const char *mimetype2,
+ const apr_array_header_t *prop_changes,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ merge_cmd_baton_t *merge_b = baton;
+ svn_node_kind_t kind;
+ const char *copyfrom_url;
+ const char *child;
+ int i;
+ apr_hash_t *new_props;
+
+ *content_state = svn_wc_notify_state_unchanged;
+ *prop_state = svn_wc_notify_state_unchanged;
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+reflective_merge_file_deleted(svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ const char *mimetype1,
+ const char *mimetype2,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ merge_cmd_baton_t *merge_b = baton;
+ svn_node_kind_t kind;
+ svn_wc_adm_access_t *parent_access;
+ const char *parent_path;
+ svn_error_t *err;
+ *state = svn_wc_notify_state_unchanged;
+ return SVN_NO_ERROR;
+}
+
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+reflective_merge_dir_added(svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *path,
+ svn_revnum_t rev,
+ void *baton)
+{
+ merge_cmd_baton_t *merge_b = baton;
+ svn_node_kind_t kind;
+ const svn_wc_entry_t *entry;
+ const char *copyfrom_url, *child;
+
+ *state = svn_wc_notify_state_unchanged;
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+reflective_merge_dir_deleted(svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *path,
+ void *baton)
+{
+ merge_cmd_baton_t *merge_b = baton;
+ svn_node_kind_t kind;
+ svn_wc_adm_access_t *parent_access;
+ const char *parent_path;
+ svn_error_t *err;
+
+ *state = svn_wc_notify_state_unchanged;
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. Used for both file and directory
+ property merges. */
+static svn_error_t *
+reflective_merge_props_changed(svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *path,
+ const apr_array_header_t *propchanges,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ apr_array_header_t *props;
+ merge_cmd_baton_t *merge_b = baton;
+ svn_client_ctx_t *ctx = merge_b->ctx;
+ apr_pool_t *subpool = svn_pool_create(merge_b->pool);
+ svn_error_t *err;
+
+ *state = svn_wc_notify_state_unchanged;
+ return SVN_NO_ERROR;
+}
+
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
 merge_file_added(svn_wc_adm_access_t *adm_access,
                  svn_wc_notify_state_t *content_state,
                  svn_wc_notify_state_t *prop_state,
@@ -970,6 +1199,17 @@
     merge_props_changed
   };
 
+/* The main callback table for 'svn reflective merge'. */
+static const svn_wc_diff_callbacks2_t
+reflective_merge_callbacks =
+ {
+ reflective_merge_file_changed,
+ reflective_merge_file_added,
+ reflective_merge_file_deleted,
+ reflective_merge_dir_added,
+ reflective_merge_dir_deleted,
+ reflective_merge_props_changed
+ };
 
 /*-----------------------------------------------------------------------*/
 
@@ -1091,12 +1331,14 @@
                        && notify_b->merge_b->target_has_dummy_merge_range))
                 {
                   svn_wc_notify_t *notify_merge_begin;
+ remaining_range_info_t *range_info;
                   notify_merge_begin =
                     svn_wc_create_notify(child->path,
                                          svn_wc_notify_merge_begin, pool);
- notify_merge_begin->merge_range =
- APR_ARRAY_IDX(child->remaining_ranges, 0,
- svn_merge_range_t *);
+ range_info = APR_ARRAY_IDX(child->remaining_ranges, 0,
+ remaining_range_info_t *);
+ notify_merge_begin->merge_range = range_info->range;
+
                   if (notify_b->wrapped_func)
                     (*notify_b->wrapped_func)(notify_b->wrapped_baton,
                                               notify_merge_begin, pool);
@@ -1170,6 +1412,12 @@
 
    NOTE: This should only be called when honoring mergeinfo.
 
+ *REFLECTIVE_RANGELIST will be populated with commits post merge from
+ target on source within revision1:revision2.
+
+ *REFLECTED_RANGELIST will be populated with merge ranges that are
+ merged from target to source within revision1:revision2.
+
    ### FIXME: I strongly suspect that these calculations are
    ### rename-ignorant, not accounting for the situation where the
    ### item at TARGET_URL back when merges were from it to our current
@@ -1178,6 +1426,8 @@
 */
 static svn_error_t *
 filter_reflected_revisions(apr_array_header_t **requested_rangelist,
+ apr_array_header_t **reflected_ranges_list,
+ apr_array_header_t **reflective_rangelist,
                            const char *source_root_url,
                            const char *url1,
                            svn_revnum_t revision1,
@@ -1189,8 +1439,6 @@
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
 {
- apr_array_header_t *reflective_rangelist = NULL;
- apr_array_header_t *merge_ranges_list = NULL;
   svn_merge_range_t *range = apr_pcalloc(pool, sizeof(*range));
   svn_revnum_t min_rev = MIN(revision1, revision2);
   svn_revnum_t max_rev = MAX(revision1, revision2);
@@ -1206,8 +1454,8 @@
                                             ra_session, NULL, pool));
 
   SVN_ERR(svn_ra_get_commit_and_merge_ranges(ra_session,
- &merge_ranges_list,
- &reflective_rangelist,
+ reflected_ranges_list,
+ reflective_rangelist,
                                              max_rel_path,
                                              mergeinfo_path,
                                              min_rev, max_rev,
@@ -1220,9 +1468,9 @@
   range->end = revision2;
   range->inheritable = inheritable;
   APR_ARRAY_PUSH(*requested_rangelist, svn_merge_range_t *) = range;
- if (reflective_rangelist)
+ if (*reflective_rangelist)
     SVN_ERR(svn_rangelist_remove(requested_rangelist,
- reflective_rangelist,
+ *reflective_rangelist,
                                  *requested_rangelist, FALSE, pool));
   return SVN_NO_ERROR;
 }
@@ -1231,13 +1479,13 @@
    drive_merge_report_editor()'s application of the editor to the WC
    -- by subtracting revisions which have already been merged from
    MERGEINFO_PATH into the working copy from the requested range(s)
- REQUESTED_MERGE, and storing what's left in REMAINING_RANGES.
+ REQUESTED_MERGE, and storing what's left in RANGES_TO_MERGE.
    TARGET_MERGEINFO may be NULL.
 
    NOTE: This should only be called when honoring mergeinfo.
 */
 static svn_error_t *
-filter_merged_revisions(apr_array_header_t **remaining_ranges,
+filter_merged_revisions(apr_array_header_t **ranges_to_merge,
                         const char *mergeinfo_path,
                         apr_hash_t *target_mergeinfo,
                         apr_hash_t *implicit_mergeinfo,
@@ -1265,20 +1513,20 @@
              revert to work properly. */
           requested_merge = svn_rangelist_dup(requested_merge, pool);
           SVN_ERR(svn_rangelist_reverse(requested_merge, pool));
- SVN_ERR(svn_rangelist_intersect(remaining_ranges,
+ SVN_ERR(svn_rangelist_intersect(ranges_to_merge,
                                           target_rangelist,
                                           requested_merge, pool));
- SVN_ERR(svn_rangelist_reverse(*remaining_ranges, pool));
+ SVN_ERR(svn_rangelist_reverse(*ranges_to_merge, pool));
         }
       else
         {
- *remaining_ranges =
+ *ranges_to_merge =
             apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
         }
     }
   else
     {
- *remaining_ranges = requested_merge;
+ *ranges_to_merge = requested_merge;
 
 /* ### TODO: Which evil shall we choose?
    ###
@@ -1312,7 +1560,7 @@
 #endif
 
       if (target_rangelist)
- SVN_ERR(svn_rangelist_remove(remaining_ranges, target_rangelist,
+ SVN_ERR(svn_rangelist_remove(ranges_to_merge, target_rangelist,
                                      requested_merge, FALSE, pool));
     }
   return SVN_NO_ERROR;
@@ -1345,14 +1593,23 @@
                            apr_pool_t *pool)
 {
   apr_array_header_t *requested_rangelist;
+ apr_array_header_t *reflected_ranges_list = NULL;
+ apr_array_header_t *reflective_rangelist = NULL;
+ apr_array_header_t *ranges_to_merge;
+ svn_merge_range_t *range = NULL, *reflective_range = NULL;
+ apr_array_header_t *reflected_ranges;
   const char *old_url;
   const char *mergeinfo_path;
+ int i = 0, j = 0;
   const char *primary_url = (revision1 < revision2) ? url2 : url1;
 
   /* Determine which of the requested ranges to consider merging... */
   SVN_ERR(svn_ra_get_session_url(ra_session, &old_url, pool));
   SVN_ERR(svn_ra_reparent(ra_session, source_root_url, pool));
- SVN_ERR(filter_reflected_revisions(&requested_rangelist, source_root_url,
+ SVN_ERR(filter_reflected_revisions(&requested_rangelist,
+ &reflected_ranges_list,
+ &reflective_rangelist,
+ source_root_url,
                                      url1, revision1, url2, revision2,
                                      inheritable, entry->url,
                                      ra_session, ctx, pool));
@@ -1363,10 +1620,61 @@
   SVN_ERR(svn_client__path_relative_to_root(&mergeinfo_path, primary_url,
                                             source_root_url, TRUE,
                                             ra_session, NULL, pool));
- SVN_ERR(filter_merged_revisions(remaining_ranges, mergeinfo_path,
+ SVN_ERR(filter_merged_revisions(&ranges_to_merge, mergeinfo_path,
                                   target_mergeinfo, implicit_mergeinfo,
                                   requested_rangelist,
                                   (revision1 > revision2), entry, pool));
+
+ *remaining_ranges = apr_array_make(pool, 0,
+ sizeof(remaining_range_info_t *));
+ /* populate remaining_ranges list. */
+ while (TRUE)
+ {
+ remaining_range_info_t *range_info = apr_pcalloc(pool,
+ sizeof(*range_info));
+ if (ranges_to_merge && i < ranges_to_merge->nelts)
+ range = APR_ARRAY_IDX(ranges_to_merge, i, svn_merge_range_t *);
+ if (reflective_rangelist && j < reflective_rangelist->nelts)
+ {
+ reflective_range = APR_ARRAY_IDX(reflective_rangelist, j,
+ svn_merge_range_t *);
+ reflected_ranges = APR_ARRAY_IDX(reflected_ranges_list, j,
+ apr_array_header_t *);
+ }
+ if (range == NULL && reflective_range == NULL)
+ break;
+
+ if (range && reflective_range)
+ {
+ /* Ranges to merge and reflected ranges won't intersect. */
+ if (range->start < reflective_range->start)
+ {
+ range_info->range = range;
+ ++i;
+ }
+ else
+ {
+ range_info->range = reflective_range;
+ range_info->reflected_ranges = reflected_ranges;
+ ++j;
+ }
+ }
+ else if (range)
+ {
+ range_info->range = range;
+ ++i;
+ }
+ else if (reflective_range)
+ {
+ range_info->range = reflective_range;
+ range_info->reflected_ranges = reflected_ranges;
+ ++j;
+ }
+ APR_ARRAY_PUSH(*remaining_ranges, remaining_range_info_t *) = range_info;
+ range = NULL;
+ reflective_range = NULL;
+ }
+
   return SVN_NO_ERROR;
 }
 
@@ -1516,6 +1824,8 @@
     {
       for (i = 0; i < children_with_mergeinfo->nelts; i++)
         {
+ remaining_range_info_t *range_info =
+ apr_pcalloc(pool, sizeof(*range_info));
           svn_client__merge_path_t *child =
             APR_ARRAY_IDX(children_with_mergeinfo, i,
                           svn_client__merge_path_t *);
@@ -1524,10 +1834,12 @@
           range->start = revision1;
           range->end = revision2;
           range->inheritable = inheritable;
+ range_info->range = range;
 
           child->remaining_ranges =
- apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
- APR_ARRAY_PUSH(child->remaining_ranges, svn_merge_range_t *) = range;
+ apr_array_make(pool, 1, sizeof(remaining_range_info_t *));
+ APR_ARRAY_PUSH(child->remaining_ranges,
+ remaining_range_info_t *) = range_info;
         }
       return SVN_NO_ERROR;
     }
@@ -1586,13 +1898,19 @@
 
       if (child->remaining_ranges->nelts == 0)
         {
+ remaining_range_info_t *range_info =
+ apr_pcalloc(pool, sizeof(*range_info));
           svn_merge_range_t *dummy_range =
             apr_pcalloc(pool, sizeof(*dummy_range));
           dummy_range->start = revision2;
           dummy_range->end = revision2;
           dummy_range->inheritable = inheritable;
+ range_info->range = dummy_range;
           child->remaining_ranges = apr_array_make(pool, 1,
- sizeof(dummy_range));
+ sizeof(*range_info));
+ APR_ARRAY_PUSH(child->remaining_ranges,
+ remaining_range_info_t *) = range_info;
+
           APR_ARRAY_PUSH(child->remaining_ranges, svn_merge_range_t *) =
             dummy_range;
           merge_b->target_has_dummy_merge_range = TRUE;
@@ -2134,7 +2452,6 @@
                           svn_depth_t depth,
                           notification_receiver_baton_t *notify_b,
                           svn_wc_adm_access_t *adm_access,
- const svn_wc_diff_callbacks2_t *callbacks,
                           merge_cmd_baton_t *merge_b,
                           apr_pool_t *pool)
 {
@@ -2144,6 +2461,7 @@
   void *report_baton;
   svn_revnum_t default_start;
   svn_boolean_t honor_mergeinfo;
+ const svn_wc_diff_callbacks2_t *callbacks = &merge_callbacks;
 
   mergeinfo_behavior(&honor_mergeinfo, NULL, merge_b);
 
@@ -2167,10 +2485,20 @@
                           svn_client__merge_path_t *);
           if (child->remaining_ranges->nelts)
             {
- svn_merge_range_t *range =
- APR_ARRAY_IDX(child->remaining_ranges, 0,
- svn_merge_range_t *);
- default_start = range->start;
+ remaining_range_info_t *range_info =
+ APR_ARRAY_IDX(child->remaining_ranges,
+ 0, remaining_range_info_t *);
+ default_start = range_info->range->start;
+ /* ### We handle reflective_merges only if target has such
+ * reflective merges. We should do for childs in
+ * children_with_mergeinfo too, but that would be complex
+ * enough to handle.
+ */
+ if (range_info->reflected_ranges)
+ {
+ merge_b->reflected_ranges = range_info->reflected_ranges;
+ callbacks = &reflective_merge_callbacks;
+ }
             }
         }
     }
@@ -2184,14 +2512,13 @@
   SVN_ERR(svn_client__open_ra_session_internal(&merge_b->ra_session2, url1,
                                                NULL, NULL, NULL, FALSE, TRUE,
                                                merge_b->ctx, pool));
- SVN_ERR(svn_client__get_diff_editor(target_wcpath, adm_access, callbacks,
- merge_b, depth, merge_b->dry_run,
- merge_b->ra_session2, default_start,
- notification_receiver, notify_b,
- merge_b->ctx->cancel_func,
- merge_b->ctx->cancel_baton,
- &diff_editor, &diff_edit_baton,
- pool));
+ SVN_ERR(svn_client__get_diff_editor(target_wcpath, adm_access,
+ callbacks, merge_b, depth,
+ merge_b->dry_run, merge_b->ra_session2,
+ default_start, notification_receiver,
+ notify_b, merge_b->ctx->cancel_func,
+ merge_b->ctx->cancel_baton, &diff_editor,
+ &diff_edit_baton, pool));
 
   SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1,
                           &reporter, &report_baton, revision2,
@@ -2212,6 +2539,7 @@
 
       for (i = 1; i < children_with_mergeinfo->nelts; i++)
         {
+ remaining_range_info_t *range_info;
           svn_merge_range_t *range;
           const char *child_repos_path;
           svn_client__merge_path_t *child =
@@ -2221,8 +2549,9 @@
           if (!child || child->absent || (child->remaining_ranges->nelts == 0))
             continue;
 
- range = APR_ARRAY_IDX(child->remaining_ranges, 0,
- svn_merge_range_t *);
+ range_info = APR_ARRAY_IDX(child->remaining_ranges, 0,
+ remaining_range_info_t *);
+ range = range_info->range;
           if (range->start == default_start)
             continue;
 
@@ -2265,6 +2594,7 @@
 
   for (i = 0; i < children_with_mergeinfo->nelts; i++)
     {
+ remaining_range_info_t *range_info;
       svn_client__merge_path_t *child =
         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
       svn_merge_range_t *range;
@@ -2273,7 +2603,10 @@
         continue;
       if (! child->remaining_ranges->nelts)
         continue;
- range = APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
+ range_info = APR_ARRAY_IDX(child->remaining_ranges, 0,
+ remaining_range_info_t *);
+ range = range_info->range;
+
       if ((i == 0) && (range->start == range->end))
         continue;
       if ((start_rev == SVN_INVALID_REVNUM)
@@ -2302,8 +2635,10 @@
         continue;
       if (child->remaining_ranges->nelts > 0)
         {
- svn_merge_range_t *range = APR_ARRAY_IDX(child->remaining_ranges, 0,
- svn_merge_range_t *);
+ remaining_range_info_t *range_info =
+ APR_ARRAY_IDX(child->remaining_ranges, 0,
+ remaining_range_info_t *);
+ svn_merge_range_t *range = range_info->range;
           if ((end_rev == SVN_INVALID_REVNUM)
               || (is_rollback && (range->end > end_rev))
               || ((! is_rollback) && (range->end < end_rev)))
@@ -2313,7 +2648,7 @@
   return end_rev;
 }
 
-/* If first item in each child of CHILDREN_WITH_MERGEINFO's
+/* If first item's range in each child of CHILDREN_WITH_MERGEINFO's
    remaining_ranges is inclusive of END_REV, Slice the first range in
    to two at END_REV. All the allocations are persistent and allocated
    from POOL. */
@@ -2332,8 +2667,10 @@
         continue;
       if (child->remaining_ranges->nelts > 0)
         {
- svn_merge_range_t *range = APR_ARRAY_IDX(child->remaining_ranges, 0,
- svn_merge_range_t *);
+ remaining_range_info_t *range_info =
+ APR_ARRAY_IDX(child->remaining_ranges, 0,
+ remaining_range_info_t *);
+ svn_merge_range_t *range = range_info->range;
           if ((is_rollback && (range->start > end_rev)
                && (range->end < end_rev))
               || (!is_rollback && (range->start < end_rev)
@@ -2341,6 +2678,10 @@
             {
               int j;
               svn_merge_range_t *split_range1, *split_range2;
+ remaining_range_info_t *range_info1 =
+ apr_pcalloc(pool, sizeof(*range_info1));
+ remaining_range_info_t *range_info2 =
+ apr_pcalloc(pool, sizeof(*range_info2));
               apr_array_header_t *orig_remaining_ranges =
                                                      child->remaining_ranges;
               split_range1 = svn_merge_range_dup(range, pool);
@@ -2349,18 +2690,20 @@
               split_range2->start = end_rev;
               child->remaining_ranges =
                      apr_array_make(pool, (child->remaining_ranges->nelts + 1),
- sizeof(svn_merge_range_t *));
+ sizeof(remaining_range_info_t *));
+ range_info1->range = split_range1;
+ range_info2->range = split_range2;
               APR_ARRAY_PUSH(child->remaining_ranges,
- svn_merge_range_t *) = split_range1;
+ remaining_range_info_t *) = range_info1;
               APR_ARRAY_PUSH(child->remaining_ranges,
- svn_merge_range_t *) = split_range2;
+ remaining_range_info_t *) = range_info2;
               for (j = 1; j < orig_remaining_ranges->nelts; j++)
                 {
- svn_merge_range_t *orig_range =
+ remaining_range_info_t *range_info_orig =
                                      APR_ARRAY_IDX(orig_remaining_ranges, j,
- svn_merge_range_t *);
+ remaining_range_info_t *);
                   APR_ARRAY_PUSH(child->remaining_ranges,
- svn_merge_range_t *) = orig_range;
+ remaining_range_info_t *) = range_info_orig;
                 }
             }
         }
@@ -2391,14 +2734,15 @@
           apr_array_header_t *orig_remaining_ranges = child->remaining_ranges;
           child->remaining_ranges =
             apr_array_make(pool, (child->remaining_ranges->nelts - 1),
- sizeof(svn_merge_range_t *));
+ sizeof(remaining_range_info_t *));
           for (j = 1; j < orig_remaining_ranges->nelts; j++)
             {
- svn_merge_range_t *range = APR_ARRAY_IDX(orig_remaining_ranges,
- j,
- svn_merge_range_t *);
- APR_ARRAY_PUSH(child->remaining_ranges, svn_merge_range_t *)
- = range;
+ remaining_range_info_t *range_info =
+ APR_ARRAY_IDX(orig_remaining_ranges,
+ j,
+ remaining_range_info_t *);
+ APR_ARRAY_PUSH(child->remaining_ranges, remaining_range_info_t *)
+ = range_info;
             }
         }
     }
@@ -3602,8 +3946,12 @@
     }
   else
     {
- remaining_ranges = apr_array_make(pool, 1, sizeof(&range));
- APR_ARRAY_PUSH(remaining_ranges, svn_merge_range_t *) = &range;
+ remaining_range_info_t *range_info = apr_pcalloc(pool,
+ sizeof(*range_info));
+ remaining_ranges = apr_array_make(pool, 1,
+ sizeof(remaining_range_info_t));
+ range_info->range = &range;
+ APR_ARRAY_PUSH(remaining_ranges, remaining_range_info_t *) = range_info;
     }
 
   subpool = svn_pool_create(pool);
@@ -3612,12 +3960,16 @@
     {
       svn_wc_notify_t *n;
 
+ remaining_range_info_t *range_info =
+ APR_ARRAY_IDX(remaining_ranges, i,
+ remaining_range_info_t *);
+
       /* When using this merge range, account for the exclusivity of
          its low value (which is indicated by this operation being a
          merge vs. revert). */
- svn_merge_range_t *r = APR_ARRAY_IDX(remaining_ranges, i,
- svn_merge_range_t *);
 
+ svn_merge_range_t *r = range_info->range;
+
       svn_pool_clear(subpool);
 
       n = svn_wc_create_notify(target_wcpath,
@@ -3832,13 +4184,17 @@
         {
           svn_client__merge_path_t *item = apr_pcalloc(pool, sizeof(*item));
           svn_merge_range_t *itemrange = apr_pcalloc(pool, sizeof(*itemrange));
+ remaining_range_info_t *range_info =
+ apr_pcalloc(pool, sizeof(*range_info));
           apr_array_header_t *remaining_ranges =
- apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
+ apr_array_make(pool, 1, sizeof(remaining_range_info_t));
 
           itemrange->start = revision1;
           itemrange->end = revision2;
           itemrange->inheritable = TRUE;
- APR_ARRAY_PUSH(remaining_ranges, svn_merge_range_t *) = itemrange;
+ range_info->range = itemrange;
+ APR_ARRAY_PUSH(remaining_ranges,
+ remaining_range_info_t *) = range_info;
 
           item->path = apr_pstrdup(pool, target_wcpath);
           item->remaining_ranges = remaining_ranges;
@@ -3847,9 +4203,8 @@
         }
       return drive_merge_report_editor(target_wcpath,
                                        url1, revision1, url2, revision2,
- NULL, is_rollback, depth, notify_b,
- adm_access, &merge_callbacks,
- merge_b, pool);
+ NULL, is_rollback, depth, notify_b,
+ adm_access, merge_b, pool);
     }
 
   /*** If we get here, we're dealing with related sources from the
@@ -3963,10 +4318,8 @@
           SVN_ERR(drive_merge_report_editor(merge_b->target,
                                             real_url1, start_rev, real_url2,
                                             end_rev, children_with_mergeinfo,
- is_rollback,
- depth, notify_b, adm_access,
- &merge_callbacks, merge_b,
- iterpool));
+ is_rollback, depth, notify_b,
+ adm_access, merge_b, iterpool));
 
           remove_first_range_from_remaining_ranges(children_with_mergeinfo,
                                                    pool);
@@ -3995,12 +4348,9 @@
       range.end = revision2;
       range.inheritable = inheritable;
 
- SVN_ERR(drive_merge_report_editor(merge_b->target,
- url1, revision1, url2, revision2,
- NULL, is_rollback,
- depth, notify_b, adm_access,
- &merge_callbacks, merge_b,
- pool));
+ SVN_ERR(drive_merge_report_editor(merge_b->target, url1, revision1, url2,
+ revision2, NULL, is_rollback, depth,
+ notify_b, adm_access, merge_b, pool));
     }
 
   /* Record mergeinfo where appropriate.
@@ -4214,6 +4564,11 @@
   merge_cmd_baton.pool = subpool;
   merge_cmd_baton.merge_options = merge_options;
   merge_cmd_baton.diff3_cmd = diff3_cmd;
+ merge_cmd_baton.reflected_ranges = NULL;
+ SVN_ERR(svn_client__open_ra_session_internal(
+ &merge_cmd_baton.target_ra_session,
+ target_entry->url, NULL, NULL,
+ NULL, FALSE, TRUE, ctx, pool));
 
   /* Build the notification receiver baton. */
   notify_baton.wrapped_func = ctx->notify_func2;
Index: subversion/tests/cmdline/merge_tests.py
===================================================================
--- subversion/tests/cmdline/merge_tests.py (revision 28479)
+++ subversion/tests/cmdline/merge_tests.py (working copy)
@@ -10148,7 +10148,7 @@
               merge_from_renamed_branch_fails_while_avoiding_repeat_merge,
               XFail(merge_source_normalization_and_subtree_merges),
               XFail(merge_non_reflective_changes_from_reflective_rev),
- XFail(merge_non_reflective_text_change),
+ merge_non_reflective_text_change,
              ]
 
 if __name__ == '__main__':

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Dec 14 13:29:49 2007

This is an archived mail posted to the Subversion Dev mailing list.