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

Re: [PATCH] Single file merge tracking implementation. /merge-tracking/subversion/libsvn_client/diff.c

From: Kamesh Jayachandran <kamesh_at_collab.net>
Date: 2006-07-07 17:35:23 CEST

Thanks Dan for the review and refined patch.
>> + SVN_ERR(svn_fs_fs__change_txn_mergeinfo(txn, canon_path, value, pool));
>>
>> SVN_ERR(svn_fs_fs__change_txn_prop(txn,
>> SVN_FS_PROP_TXN_CONTAINS_MERGEINFO,
>>
>
> Seems like we'll be hitting this code path very often. Is this
> canonicalization redundant in some instances? Can it be avoided, or
> made specific to the "single-file merge" case?
>
>
Originally tried to investigate why nodes under root are not
canonicalized, did not have much success.
> Why are we retrieving the repository UUIDs for the files? To verify
> that both file URLs come from the same repository?
>
>
Yes. I recently found one more issue for which I don't have a clue to
solve(Not sure how to get the WC's uuid)
The issue is, the current patch records 'svn:mergeinfo' on a WC of repo1
when the merge was executed for difference between 2 revisions of
similarly looking file on repo2 and file also gets merged.

>> - /* Discover any svn:mime-type values in the proplists */
>> - pval = apr_hash_get(props1, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE));
>> - mimetype1 = pval ? pval->data : NULL;
>> + /* Establish RA session to URL1. */
>> + SVN_ERR(svn_client__open_ra_session_internal(&ra_session1, URL1, NULL,
>> + NULL, NULL, FALSE, TRUE,
>> + ctx, pool));
>> + SVN_ERR(svn_client__open_ra_session_internal(&ra_session2, URL2, NULL,
>> + NULL, NULL, FALSE, TRUE,
>> + ctx, pool));
>>
>
> The comment is no longer in sync with the code, since we're now
> opening two RA sessions. Do we actually need both sessions here?
>
>
Yes. Attached patch fixes it.
>> + /* Resolve the revision numbers, and store them as a merge range.
>> + Note that the "start" of a merge range is inclusive. */
>> + SVN_ERR(svn_client__get_revision_number
>> + (&range.start, ra_session1, revision1, path1, pool));
>> + SVN_ERR(svn_client__get_revision_number
>> + (&range.end, ra_session2, revision2, path2, pool));
>> + if (range.start == range.end)
>> + /* No merge to perform. */
>> + return SVN_NO_ERROR;
>> + is_revert = (range.start > range.end);
>> + if (is_revert)
>> + range.end += 1;
>> + else
>> + range.start += 1;
>>
>
> This block of code duplicates what's in do_merge(). I wonder whether
> it's worth consolidating, possibly into a route which produces a
> struct containing a svn_merge_range_t and an is_revert flag.
>
>
Fixed in the attached patch.
>> + if (strcmp(uuid1, uuid2) == 0)
>> + {
>> + /* Look at the merge info prop of the WC target to see what's
>> + already been merged into it. */
>> + SVN_ERR(parse_merge_info(&target_mergeinfo, target_wcpath, adm_access, ctx,
>> + pool));
>>
> ...
>
>> + SVN_ERR(svn_client__path_relative_to_root(&rel_path, URL1, NULL,
>> + ra_session1, adm_access, pool));
>> + SVN_ERR(calculate_merge_ranges(&remaining_ranges, rel_path, target_mergeinfo,
>> + &range, is_revert, pool));
>> + }
>> + else
>> + {
>> + remaining_ranges = apr_array_make(pool, 1, sizeof(&range));
>> + APR_ARRAY_PUSH(remaining_ranges, svn_merge_range_t *) = &range;
>> + }
>>
>
> In the "else" case, I take it that we're ignoring any merge info
> because the merge source is supposedly from a different repository?
> AFAIK, this isn't (yet) a supported use case. However, while I was
> expecting to find some validation code which already enforced this, I
> didn't see any. Anyone spare a clue?
>
I could merge from two different repo to a wc of totally another
repo(Atleast for single file merges).
>
>> + for (i = 0; i < remaining_ranges->nelts; i++)
>> + {
>> + /* 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 *);
>>
> ...
>
>> + /* ### heh, funny. we could be fetching two fulltexts from two
>> + *totally* different repositories here. :-) */
>>
>
> Is this comment what made you support the "merge source repos differs
> from WC's repos" use case?
>
>
Yes.
>> + SVN_ERR(single_file_merge_get_file(&tmpfile1, ra_session1, &props1,
>> + is_revert ? r->start : r->start - 1,
>> + URL1, merge_b, pool));
>>
>> - SVN_ERR(merge_file_changed(adm_access,
>> - &text_state, &prop_state,
>> - merge_b->target,
>> - tmpfile1,
>> - tmpfile2,
>> - rev1,
>> - rev2,
>> - mimetype1, mimetype2,
>> - propchanges, props1,
>> - merge_b));
>> + SVN_ERR(single_file_merge_get_file(&tmpfile2, ra_session2, &props2,
>> + is_revert ? r->end - 1 : r->end,
>> + URL2, merge_b, pool));
>>
>> - /* Ignore if temporary file not found. It may have been renamed. */
>> - err = svn_io_remove_file(tmpfile1, pool);
>> - if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
>> - return err;
>> - svn_error_clear(err);
>> - err = svn_io_remove_file(tmpfile2, pool);
>> - if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
>> - return err;
>> - svn_error_clear(err);
>> + /* Discover any svn:mime-type values in the proplists */
>> + pval = apr_hash_get(props1, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE));
>> + mimetype1 = pval ? pval->data : NULL;
>> +
>> + pval = apr_hash_get(props2, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE));
>> + mimetype2 = pval ? pval->data : NULL;
>> +
>> + /* Deduce property diffs. */
>> + SVN_ERR(svn_prop_diffs(&propchanges, props2, props1, pool));
>> +
>> + SVN_ERR(merge_file_changed(adm_access,
>> + &text_state, &prop_state,
>> + merge_b->target,
>> + tmpfile1,
>> + tmpfile2,
>> + is_revert ? r->start : r->start - 1,
>> + is_revert ? r->end - 1 : r->end,
>> + mimetype1, mimetype2,
>> + propchanges, props1,
>> + merge_b));
>> +
>> + /* Ignore if temporary file not found. It may have been renamed. */
>> + err = svn_io_remove_file(tmpfile1, pool);
>> + if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
>> + return err;
>> + svn_error_clear(err);
>> + err = svn_io_remove_file(tmpfile2, pool);
>> + if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
>> + return err;
>> + svn_error_clear(err);
>>
>> - if (merge_b->ctx->notify_func2)
>> - {
>> - svn_wc_notify_t *notify
>> - = svn_wc_create_notify(merge_b->target, svn_wc_notify_update_update,
>> - pool);
>> - notify->kind = svn_node_file;
>> - notify->content_state = text_state;
>> - notify->prop_state = prop_state;
>> - (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
>> - pool);
>> + if (ctx->notify_func2)
>> + {
>> + svn_wc_notify_t *notify
>> + = svn_wc_create_notify(merge_b->target, svn_wc_notify_update_update,
>> + pool);
>> + notify->kind = svn_node_file;
>> + notify->content_state = text_state;
>> + notify->prop_state = prop_state;
>> + (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
>> + }
>>
>
> As with do_merge(), we'll be calling this notification function over
> and over again for each revision range we merge into this file. In
> both cases, not the right behavior. Instead, we need to aggregate the
> notifications, and distill them into some reasonable form. When
> notifications conflict, I think we want to give preference to latter
> notifications.
>
>
Could not understand it much would go through the same later and provide
a fix for it.
>> }
>> + if ((!dry_run) && (strcmp(uuid1, uuid2) == 0) && (remaining_ranges->nelts > 0))
>>
>
> If we end up retaining usage of UUIDs, using a flag to represent this
> condition (which you also use above) would be a lot eaiser to
> understand:
>
> svn_boolean_t from_same_repos = (strcmp(uuid1, uuid2) == 0);
> if (from_same_repos)
> ...
> if (!merge_b->dry_run && from_same_repos && remaining_ranges->nelts > 0)
> ...
>
Could see in your new patch.

Find the attached patch.

Thanks.

With regards
Kamesh Jayachandran

[[[
Patch by: Kamesh Jayachandran <kamesh@collab.net>
Patch by: Daniell L Rall <dlr@collab.net>

Single file merge tracking implementation.

* subversion/libsvn_fs_fs/tree.c
  (fs_change_node_prop):
    For file nodes under '/' we receive path as just the file names
    without a '/' at the begining. This happens for single file merges,
    so canonicalize the path to make sure 'mergeinfo.mergeto' is getting
    recorded as canonicalized path.

* subversion/libsvn_client/diff.c
  (ENSURE_VALID_REVISION_KINDS): New macro to check whether merge revision
   info are specified or not.
  (grok_range_info_from_opt_revisions):
   New function. converts opt_revision_t to svn_revnum_t, adjust the range
   based on 'revert' or 'merge'.
  (do_merge):
   uses ENSURE_VALID_REVISION_KINDS.
   uses grok_range_info_from_opt_revisions.
  (single_file_merge_get_file):
   Caller has to pass ra_session to reuse the ra_session.
   No need to translate 'svn_opt_revision_t' to 'svn_revnum_t', Caller
   has this info already, so no need of 'path' and 'revision' args.
  (do_single_file_merge):
   Implemented merge tracking for single file merges the same way as
   directory merges.
   Remove the FIXME docstring for merge-tracking.
   Calls single_file_merge_get_file with the new signature.
]]]

Index: subversion/libsvn_fs_fs/tree.c
===================================================================
--- subversion/libsvn_fs_fs/tree.c (revision 20465)
+++ subversion/libsvn_fs_fs/tree.c (working copy)
@@ -1458,9 +1458,13 @@
          directly. */
 
       svn_fs_txn_t *txn;
+ /* For file nodes under '/' we receive path as just the file names
+ * without a '/' at the begining. This happens for single file merges,
+ * so canonicalize the path to canon_path */
+ const char *canon_path = svn_fs_fs__canonicalize_abspath(path, pool);
       SVN_ERR(svn_fs_open_txn(&txn, root->fs, txn_id, pool));
 
- SVN_ERR(svn_fs_fs__change_txn_mergeinfo(txn, path, value, pool));
+ SVN_ERR(svn_fs_fs__change_txn_mergeinfo(txn, canon_path, value, pool));
       
       SVN_ERR(svn_fs_fs__change_txn_prop(txn,
                                          SVN_FS_PROP_TXN_CONTAINS_MERGEINFO,
Index: subversion/libsvn_client/diff.c
===================================================================
--- subversion/libsvn_client/diff.c (revision 20465)
+++ subversion/libsvn_client/diff.c (working copy)
@@ -44,6 +44,17 @@
 
 #include "svn_private_config.h"
 
+/* Sanity check -- ensure that we have valid revisions to look at. */
+#define ENSURE_VALID_REVISION_KINDS(rev1_kind, rev2_kind) \
+ if ((rev1_kind == svn_opt_revision_unspecified) \
+ || (rev2_kind == svn_opt_revision_unspecified)) \
+ { \
+ return svn_error_create \
+ (SVN_ERR_CLIENT_BAD_REVISION, NULL, \
+ _("Not all required revisions are specified")); \
+ }
+
+
 /*
  * Constant separator strings
  */
@@ -1763,6 +1774,37 @@
                           adm_access, TRUE /* skip checks */, pool);
 }
 
+static svn_error_t *
+grok_range_info_from_opt_revisions(svn_merge_range_t *range,
+ svn_ra_session_t *ra_session1,
+ svn_ra_session_t *ra_session2,
+ svn_opt_revision_t *revision1,
+ svn_opt_revision_t *revision2,
+ const char *path1,
+ const char *path2,
+ svn_boolean_t *is_revert,
+ apr_pool_t *pool)
+{
+ /* Resolve the revision numbers, and store them as a merge range.
+ Determine whether this merge adds or backs out changes
+ (e.g. merge vs. revert), and handle the fact that a
+ svn_merge_range_t's "start" and "end" are inclusive. */
+ SVN_ERR(svn_client__get_revision_number
+ (&range->start, ra_session1, revision1, path1, pool));
+ SVN_ERR(svn_client__get_revision_number
+ (&range->end, ra_session2, revision2, path2, pool));
+ if (range->start == range->end)
+ /* No merge to perform. */
+ return SVN_NO_ERROR;
+ *is_revert = (range->start > range->end);
+ if (*is_revert)
+ range->end += 1;
+ else
+ range->start += 1;
+
+ return SVN_NO_ERROR;
+}
+
 /* URL1/PATH1, URL2/PATH2, and TARGET_WCPATH all better be
    directories. For the single file case, the caller does the merging
    manually. PATH1 and PATH2 can be NULL.
@@ -1803,14 +1845,8 @@
   svn_opt_revision_t *revision1, *revision2;
   int i;
 
- /* Sanity check -- ensure that we have valid revisions to look at. */
- if ((initial_revision1->kind == svn_opt_revision_unspecified)
- || (initial_revision2->kind == svn_opt_revision_unspecified))
- {
- return svn_error_create
- (SVN_ERR_CLIENT_BAD_REVISION, NULL,
- _("Not all required revisions are specified"));
- }
+ ENSURE_VALID_REVISION_KINDS(initial_revision1->kind,
+ initial_revision2->kind);
 
   /* If we are performing a pegged merge, we need to find out what our
      actual URLs will be. */
@@ -1847,23 +1883,11 @@
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL1, NULL,
                                                NULL, NULL, FALSE, TRUE,
                                                ctx, pool));
- /* Resolve the revision numbers, and store them as a merge range.
- Determine whether this merge adds or backs out changes
- (e.g. merge vs. revert), and handle the fact that a
- svn_merge_range_t's "start" and "end" are inclusive. */
- SVN_ERR(svn_client__get_revision_number
- (&range.start, ra_session, revision1, path1, pool));
- SVN_ERR(svn_client__get_revision_number
- (&range.end, ra_session, revision2, path2, pool));
- if (range.start == range.end)
- /* No merge to perform. */
- return SVN_NO_ERROR;
- is_revert = (range.start > range.end);
- if (is_revert)
- range.end += 1;
- else
- range.start += 1;
 
+ SVN_ERR(grok_range_info_from_opt_revisions(&range, ra_session, ra_session,
+ revision1, revision2, path1,
+ path2, &is_revert, pool));
+
   /* Open a second session used to request individual file
      contents. Although a session can be used for multiple requests, it
      appears that they must be sequential. Since the first request, for
@@ -1947,28 +1971,21 @@
    in POOL. */
 static svn_error_t *
 single_file_merge_get_file(const char **filename,
+ svn_ra_session_t *ra_session,
                            apr_hash_t **props,
- svn_revnum_t *rev,
+ svn_revnum_t rev,
                            const char *url,
- const char *path,
- const svn_opt_revision_t *revision,
                            struct merge_cmd_baton *merge_b,
                            apr_pool_t *pool)
 {
- svn_ra_session_t *ra_session;
   apr_file_t *fp;
   svn_stream_t *stream;
 
- SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url, NULL,
- NULL, NULL, FALSE, TRUE,
- merge_b->ctx, pool));
- SVN_ERR(svn_client__get_revision_number(rev, ra_session, revision,
- path, pool));
   SVN_ERR(svn_io_open_unique_file2(&fp, filename,
                                    merge_b->target, ".tmp",
                                    svn_io_file_del_none, pool));
   stream = svn_stream_from_aprfile2(fp, FALSE, pool);
- SVN_ERR(svn_ra_get_file(ra_session, "", *rev,
+ SVN_ERR(svn_ra_get_file(ra_session, "", rev,
                           stream, NULL, props, pool));
   SVN_ERR(svn_stream_close(stream));
 
@@ -1977,7 +1994,6 @@
                             
 
 /* The single-file, simplified version of do_merge. */
-/* ### FIXME: To handle merge tracking, follow pattern from do_merge(). */
 static svn_error_t *
 do_single_file_merge(const char *initial_URL1,
                      const char *initial_path1,
@@ -1993,16 +2009,26 @@
 {
   apr_hash_t *props1, *props2;
   const char *tmpfile1, *tmpfile2;
- svn_revnum_t rev1, rev2;
   const char *mimetype1, *mimetype2;
   svn_string_t *pval;
   apr_array_header_t *propchanges;
   svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
   svn_wc_notify_state_t text_state = svn_wc_notify_state_unknown;
- const char *URL1, *path1, *URL2, *path2;
+ svn_client_ctx_t *ctx = merge_b->ctx;
+ const char *URL1, *path1, *URL2, *path2, *rel_path;
   svn_opt_revision_t *revision1, *revision2;
   svn_error_t *err;
+ svn_merge_range_t range;
+ svn_ra_session_t *ra_session1, *ra_session2;
+ svn_boolean_t is_revert;
+ apr_hash_t *target_mergeinfo;
+ apr_array_header_t *remaining_ranges;
+ svn_boolean_t from_same_repos;
+ int i;
 
+ ENSURE_VALID_REVISION_KINDS(initial_revision1->kind,
+ initial_revision2->kind);
+
   /* If we are performing a pegged merge, we need to find out what our
      actual URLs will be. */
   if (peg_revision->kind != svn_opt_revision_unspecified)
@@ -2015,7 +2041,7 @@
                                           peg_revision,
                                           initial_revision1,
                                           initial_revision2,
- merge_b->ctx, pool));
+ ctx, pool));
 
       merge_b->url = URL2;
       merge_b->path = NULL;
@@ -2033,60 +2059,115 @@
       revision2 = apr_pcalloc(pool, sizeof(*revision2));
       *revision2 = *initial_revision2;
     }
-
- /* ### heh, funny. we could be fetching two fulltexts from two
- *totally* different repositories here. :-) */
- SVN_ERR(single_file_merge_get_file(&tmpfile1, &props1, &rev1,
- URL1, path1, revision1,
- merge_b, pool));
 
- SVN_ERR(single_file_merge_get_file(&tmpfile2, &props2, &rev2,
- URL2, path2, revision2,
- merge_b, pool));
+ {
+ const char *uuid1, *uuid2;
+ SVN_ERR(svn_client_uuid_from_url(&uuid1, URL1, ctx, pool));
+ SVN_ERR(svn_client_uuid_from_url(&uuid2, URL2, ctx, pool));
+ from_same_repos = (strcmp(uuid1, uuid2) == 0);
+ }
 
- /* Discover any svn:mime-type values in the proplists */
- pval = apr_hash_get(props1, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE));
- mimetype1 = pval ? pval->data : NULL;
+ /* Establish RA session to URL1 and URL2. */
+ SVN_ERR(svn_client__open_ra_session_internal(&ra_session1, URL1, NULL,
+ NULL, NULL, FALSE, TRUE,
+ ctx, pool));
+ SVN_ERR(svn_client__open_ra_session_internal(&ra_session2, URL2, NULL,
+ NULL, NULL, FALSE, TRUE,
+ ctx, pool));
 
- pval = apr_hash_get(props2, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE));
- mimetype2 = pval ? pval->data : NULL;
+ SVN_ERR(grok_range_info_from_opt_revisions(&range, ra_session1, ra_session2,
+ revision1, revision2, path1,
+ path2, &is_revert, pool));
 
- /* Deduce property diffs. */
- SVN_ERR(svn_prop_diffs(&propchanges, props2, props1, pool));
+ if (from_same_repos)
+ {
+ /* Look at the merge info prop of the WC target to see what's
+ already been merged into it. */
+ SVN_ERR(parse_merge_info(&target_mergeinfo, target_wcpath, adm_access, ctx,
+ pool));
 
- SVN_ERR(merge_file_changed(adm_access,
- &text_state, &prop_state,
- merge_b->target,
- tmpfile1,
- tmpfile2,
- rev1,
- rev2,
- mimetype1, mimetype2,
- propchanges, props1,
- merge_b));
+ SVN_ERR(svn_client__path_relative_to_root(&rel_path, URL1, NULL,
+ ra_session1, adm_access, pool));
+ SVN_ERR(calculate_merge_ranges(&remaining_ranges, rel_path, target_mergeinfo,
+ &range, is_revert, pool));
+ }
+ else
+ {
+ /* Files come from different repositories. */
+ remaining_ranges = apr_array_make(pool, 1, sizeof(&range));
+ APR_ARRAY_PUSH(remaining_ranges, svn_merge_range_t *) = &range;
+ }
 
- /* Ignore if temporary file not found. It may have been renamed. */
- err = svn_io_remove_file(tmpfile1, pool);
- if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
- return err;
- svn_error_clear(err);
- err = svn_io_remove_file(tmpfile2, pool);
- if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
- return err;
- svn_error_clear(err);
+ /* ### FIXME: Handle notification callbacks for multiple merges into
+ ### a single versioned resource. */
+ for (i = 0; i < remaining_ranges->nelts; i++)
+ {
+ /* 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 *);
+
+ /* While we currently don't allow it, in theory we could be
+ fetching two fulltexts from two different repositories here. */
+ SVN_ERR(single_file_merge_get_file(&tmpfile1, ra_session1, &props1,
+ is_revert ? r->start : r->start - 1,
+ URL1, merge_b, pool));
+
+ SVN_ERR(single_file_merge_get_file(&tmpfile2, ra_session2, &props2,
+ is_revert ? r->end - 1 : r->end,
+ URL2, merge_b, pool));
+
+ /* Discover any svn:mime-type values in the proplists */
+ pval = apr_hash_get(props1, SVN_PROP_MIME_TYPE,
+ strlen(SVN_PROP_MIME_TYPE));
+ mimetype1 = pval ? pval->data : NULL;
+
+ pval = apr_hash_get(props2, SVN_PROP_MIME_TYPE,
+ strlen(SVN_PROP_MIME_TYPE));
+ mimetype2 = pval ? pval->data : NULL;
+
+ /* Deduce property diffs. */
+ SVN_ERR(svn_prop_diffs(&propchanges, props2, props1, pool));
+
+ SVN_ERR(merge_file_changed(adm_access,
+ &text_state, &prop_state,
+ merge_b->target,
+ tmpfile1,
+ tmpfile2,
+ is_revert ? r->start : r->start - 1,
+ is_revert ? r->end - 1 : r->end,
+ mimetype1, mimetype2,
+ propchanges, props1,
+ merge_b));
+
+ /* Ignore if temporary file not found. It may have been renamed. */
+ err = svn_io_remove_file(tmpfile1, pool);
+ if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
+ return err;
+ svn_error_clear(err);
+ err = svn_io_remove_file(tmpfile2, pool);
+ if (err && ! APR_STATUS_IS_ENOENT(err->apr_err))
+ return err;
+ svn_error_clear(err);
   
- if (merge_b->ctx->notify_func2)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(merge_b->target, svn_wc_notify_update_update,
- pool);
- notify->kind = svn_node_file;
- notify->content_state = text_state;
- notify->prop_state = prop_state;
- (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
- pool);
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify
+ = svn_wc_create_notify(merge_b->target, svn_wc_notify_update_update,
+ pool);
+ notify->kind = svn_node_file;
+ notify->content_state = text_state;
+ notify->prop_state = prop_state;
+ (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+ }
     }
 
+ if (!merge_b->dry_run && from_same_repos && remaining_ranges->nelts > 0)
+ SVN_ERR(update_wc_merge_info(target_wcpath, target_mergeinfo, rel_path,
+ remaining_ranges, is_revert, adm_access,
+ pool));
+
   return SVN_NO_ERROR;
 }
 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Jul 7 17:35:04 2006

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