You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/11 02:05:43 UTC
svn commit: r1336974 [2/4] - in /subversion/branches/ev2-export: ./
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/include/ subversion/include/private/ subversion/libsvn_client/
subversion/lib...
Modified: subversion/branches/ev2-export/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/merge.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/merge.c Fri May 11 00:05:41 2012
@@ -866,7 +866,8 @@ filter_self_referential_mergeinfo(apr_ar
apr_array_header_t *adjusted_props;
int i;
apr_pool_t *iterpool;
- svn_boolean_t is_added;
+ svn_boolean_t is_copy;
+ const char *repos_relpath;
svn_client__pathrev_t target_base;
/* Issue #3383: We don't want mergeinfo from a foreign repos.
@@ -891,17 +892,17 @@ filter_self_referential_mergeinfo(apr_ar
/* If this is a merge from the same repository and PATH itself has been
added there is no need to filter. */
- SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, target_abspath, pool));
- if (is_added)
- return SVN_NO_ERROR;
+ SVN_ERR(svn_wc__node_get_origin(&is_copy, &target_base.rev, &repos_relpath,
+ &target_base.repos_root_url,
+ &target_base.repos_uuid, NULL,
+ ctx->wc_ctx, target_abspath, FALSE,
+ pool, pool));
+
+ if (is_copy || !repos_relpath)
+ return SVN_NO_ERROR; /* A copy or a local addition */
- SVN_ERR(svn_wc__node_get_url(&target_base.url, ctx->wc_ctx, target_abspath,
- pool, pool));
- SVN_ERR(svn_wc__node_get_base(&target_base.rev, NULL, NULL, NULL,
- ctx->wc_ctx, target_abspath, pool, pool));
- SVN_ERR(svn_wc__node_get_repos_info(&target_base.repos_root_url,
- &target_base.repos_uuid,
- ctx->wc_ctx, target_abspath, pool, pool));
+ target_base.url = svn_path_url_add_component2(target_base.repos_root_url,
+ repos_relpath, pool);
adjusted_props = apr_array_make(pool, (*props)->nelts, sizeof(svn_prop_t));
iterpool = svn_pool_create(pool);
@@ -1131,31 +1132,33 @@ filter_self_referential_mergeinfo(apr_ar
return SVN_NO_ERROR;
}
-/* Used for both file and directory property merges. */
+/* Prepare a set of property changes PROPCHANGES to be used for a merge
+ operation on LOCAL_ABSPATH. Store the result in *PROP_UPDATES.
+
+ Store information on where mergeinfo is updated in MERGE_B.
+
+ Used for both file and directory property merges. */
static svn_error_t *
-merge_props_changed(svn_wc_notify_state_t *state,
- svn_boolean_t *tree_conflicted,
- const char *local_abspath,
- const apr_array_header_t *propchanges,
- apr_hash_t *original_props,
- void *baton,
- apr_pool_t *scratch_pool)
+prepare_merge_props_changed(const apr_array_header_t **prop_updates,
+ const char *local_abspath,
+ const apr_array_header_t *propchanges,
+ merge_cmd_baton_t *merge_b,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
apr_array_header_t *props;
- merge_cmd_baton_t *merge_b = baton;
- svn_client_ctx_t *ctx = merge_b->ctx;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
SVN_ERR(svn_categorize_props(propchanges, NULL, NULL, &props,
- scratch_pool));
+ result_pool));
/* If we are only applying mergeinfo changes then we need to do
additional filtering of PROPS so it contains only mergeinfo changes. */
if (merge_b->record_only && props->nelts)
{
apr_array_header_t *mergeinfo_props =
- apr_array_make(scratch_pool, 1, sizeof(svn_prop_t));
+ apr_array_make(result_pool, 1, sizeof(svn_prop_t));
int i;
for (i = 0; i < props->nelts; i++)
@@ -1175,8 +1178,6 @@ merge_props_changed(svn_wc_notify_state_
definition, 'svn merge' shouldn't touch any data within .svn/ */
if (props->nelts)
{
- svn_error_t *err;
-
/* If this is a forward merge then don't add new mergeinfo to
PATH that is already part of PATH's own history, see
http://svn.haxx.se/dev/archive-2008-09/0006.shtml. If the
@@ -1191,88 +1192,67 @@ merge_props_changed(svn_wc_notify_state_
merge_b->reintegrate_merge,
merge_b->ra_session2,
merge_b->ctx,
- scratch_pool));
+ result_pool));
+ }
+ *prop_updates = props;
- err = svn_wc_merge_props3(state, ctx->wc_ctx, local_abspath, NULL, NULL,
- original_props, props, merge_b->dry_run,
- ctx->conflict_func2, ctx->conflict_baton2,
- ctx->cancel_func, ctx->cancel_baton,
- scratch_pool);
+ /* If this is not a dry run then make a record in BATON if we find a
+ PATH where mergeinfo is added where none existed previously or PATH
+ is having its existing mergeinfo deleted. */
+ if (!merge_b->dry_run && props->nelts)
+ {
+ int i;
- /* If this is not a dry run then make a record in BATON if we find a
- PATH where mergeinfo is added where none existed previously or PATH
- is having its existing mergeinfo deleted. */
- if (!merge_b->dry_run)
+ for (i = 0; i < props->nelts; ++i)
{
- int i;
+ svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
- for (i = 0; i < props->nelts; ++i)
+ if (strcmp(prop->name, SVN_PROP_MERGEINFO) == 0)
{
- svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
-
- if (strcmp(prop->name, SVN_PROP_MERGEINFO) == 0)
- {
- /* Does LOCAL_ABSPATH have any pristine mergeinfo? */
- svn_boolean_t has_pristine_mergeinfo = FALSE;
- apr_hash_t *pristine_props;
-
- SVN_ERR(svn_wc_get_pristine_props(&pristine_props,
- ctx->wc_ctx,
- local_abspath,
- scratch_pool,
- scratch_pool));
+ /* Does LOCAL_ABSPATH have any pristine mergeinfo? */
+ svn_boolean_t has_pristine_mergeinfo = FALSE;
+ apr_hash_t *pristine_props;
+
+ SVN_ERR(svn_wc_get_pristine_props(&pristine_props,
+ merge_b->ctx->wc_ctx,
+ local_abspath,
+ scratch_pool,
+ scratch_pool));
- if (pristine_props
- && apr_hash_get(pristine_props, SVN_PROP_MERGEINFO,
- APR_HASH_KEY_STRING))
- has_pristine_mergeinfo = TRUE;
+ if (pristine_props
+ && apr_hash_get(pristine_props, SVN_PROP_MERGEINFO,
+ APR_HASH_KEY_STRING))
+ has_pristine_mergeinfo = TRUE;
- if (!has_pristine_mergeinfo && prop->value)
- {
- /* If BATON->PATHS_WITH_NEW_MERGEINFO needs to be
- allocated do so in BATON->POOL so it has a
- sufficient lifetime. */
- if (!merge_b->paths_with_new_mergeinfo)
- merge_b->paths_with_new_mergeinfo =
- apr_hash_make(merge_b->pool);
-
- apr_hash_set(merge_b->paths_with_new_mergeinfo,
- apr_pstrdup(merge_b->pool, local_abspath),
- APR_HASH_KEY_STRING, local_abspath);
- }
- else if (has_pristine_mergeinfo && !prop->value)
- {
- /* If BATON->PATHS_WITH_DELETED_MERGEINFO needs to be
- allocated do so in BATON->POOL so it has a
- sufficient lifetime. */
- if (!merge_b->paths_with_deleted_mergeinfo)
- merge_b->paths_with_deleted_mergeinfo =
- apr_hash_make(merge_b->pool);
-
- apr_hash_set(merge_b->paths_with_deleted_mergeinfo,
- apr_pstrdup(merge_b->pool, local_abspath),
- APR_HASH_KEY_STRING, local_abspath);
- }
+ if (!has_pristine_mergeinfo && prop->value)
+ {
+ /* If BATON->PATHS_WITH_NEW_MERGEINFO needs to be
+ allocated do so in BATON->POOL so it has a
+ sufficient lifetime. */
+ if (!merge_b->paths_with_new_mergeinfo)
+ merge_b->paths_with_new_mergeinfo =
+ apr_hash_make(merge_b->pool);
+
+ apr_hash_set(merge_b->paths_with_new_mergeinfo,
+ apr_pstrdup(merge_b->pool, local_abspath),
+ APR_HASH_KEY_STRING, local_abspath);
+ }
+ else if (has_pristine_mergeinfo && !prop->value)
+ {
+ /* If BATON->PATHS_WITH_DELETED_MERGEINFO needs to be
+ allocated do so in BATON->POOL so it has a
+ sufficient lifetime. */
+ if (!merge_b->paths_with_deleted_mergeinfo)
+ merge_b->paths_with_deleted_mergeinfo =
+ apr_hash_make(merge_b->pool);
+
+ apr_hash_set(merge_b->paths_with_deleted_mergeinfo,
+ apr_pstrdup(merge_b->pool, local_abspath),
+ APR_HASH_KEY_STRING, local_abspath);
}
}
}
-
- if (err && (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND
- || err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS))
- {
- /* If the entry doesn't exist in the wc, this is a tree-conflict. */
- if (state)
- *state = svn_wc_notify_state_missing;
- if (tree_conflicted)
- *tree_conflicted = TRUE;
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
- else if (err)
- return svn_error_trace(err);
}
- else if (state)
- *state = svn_wc_notify_state_unchanged;
return SVN_NO_ERROR;
}
@@ -1289,12 +1269,15 @@ merge_dir_props_changed(svn_wc_notify_st
apr_pool_t *scratch_pool)
{
merge_cmd_baton_t *merge_b = diff_baton;
+ const apr_array_header_t *props;
const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
local_relpath, scratch_pool);
svn_wc_notify_state_t obstr_state;
+ svn_boolean_t is_deleted;
+ svn_node_kind_t kind;
- SVN_ERR(perform_obstruction_check(&obstr_state, NULL, NULL,
- NULL,
+ SVN_ERR(perform_obstruction_check(&obstr_state, NULL, &is_deleted,
+ &kind,
merge_b, local_abspath, svn_node_dir,
scratch_pool));
@@ -1305,6 +1288,26 @@ merge_dir_props_changed(svn_wc_notify_st
return SVN_NO_ERROR;
}
+ if (kind != svn_node_dir || is_deleted)
+ {
+ svn_wc_conflict_reason_t reason;
+
+ if (is_deleted)
+ reason = svn_wc_conflict_reason_deleted;
+ else
+ reason = svn_wc_conflict_reason_missing;
+
+ SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file,
+ svn_wc_conflict_action_edit, reason));
+
+ if (tree_conflicted)
+ *tree_conflicted = TRUE;
+ if (state)
+ *state = svn_wc_notify_state_missing;
+
+ return SVN_NO_ERROR;
+ }
+
if (dir_was_added
&& merge_b->dry_run
&& dry_run_added_p(merge_b, local_abspath))
@@ -1312,13 +1315,26 @@ merge_dir_props_changed(svn_wc_notify_st
return SVN_NO_ERROR; /* We can't do a real prop merge for added dirs */
}
- return svn_error_trace(merge_props_changed(state,
- tree_conflicted,
- local_abspath,
- propchanges,
- original_props,
- diff_baton,
- scratch_pool));
+ SVN_ERR(prepare_merge_props_changed(&props, local_abspath, propchanges,
+ merge_b, scratch_pool, scratch_pool));
+
+ /* We only want to merge "regular" version properties: by
+ definition, 'svn merge' shouldn't touch any pristine data */
+ if (props->nelts)
+ {
+ svn_client_ctx_t *ctx = merge_b->ctx;
+
+ SVN_ERR(svn_wc_merge_props3(state, ctx->wc_ctx, local_abspath,
+ NULL, NULL, original_props, props,
+ merge_b->dry_run,
+ ctx->conflict_func2, ctx->conflict_baton2,
+ ctx->cancel_func, ctx->cancel_baton,
+ scratch_pool));
+ }
+ else if (state)
+ *state = svn_wc_notify_state_unchanged;
+
+ return SVN_NO_ERROR;
}
/* Contains any state collected while resolving conflicts. */
@@ -1472,12 +1488,15 @@ merge_file_changed(svn_wc_notify_state_t
apr_pool_t *scratch_pool)
{
merge_cmd_baton_t *merge_b = baton;
- const char *mine_abspath = svn_dirent_join(merge_b->target->abspath,
- mine_relpath, scratch_pool);
+ svn_client_ctx_t *ctx = merge_b->ctx;
+ const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
+ mine_relpath, scratch_pool);
svn_node_kind_t wc_kind;
svn_boolean_t is_deleted;
+ const svn_wc_conflict_version_t *left;
+ const svn_wc_conflict_version_t *right;
- SVN_ERR_ASSERT(mine_abspath && svn_dirent_is_absolute(mine_abspath));
+ SVN_ERR_ASSERT(local_abspath && svn_dirent_is_absolute(local_abspath));
SVN_ERR_ASSERT(!older_abspath || svn_dirent_is_absolute(older_abspath));
SVN_ERR_ASSERT(!yours_abspath || svn_dirent_is_absolute(yours_abspath));
@@ -1490,7 +1509,7 @@ merge_file_changed(svn_wc_notify_state_t
SVN_ERR(perform_obstruction_check(&obstr_state, NULL,
&is_deleted, &wc_kind,
- merge_b, mine_abspath, svn_node_unknown,
+ merge_b, local_abspath, svn_node_unknown,
scratch_pool));
if (obstr_state != svn_wc_notify_state_inapplicable)
{
@@ -1508,7 +1527,7 @@ merge_file_changed(svn_wc_notify_state_t
/* Other easy outs: if the merge target isn't under version
control, or is just missing from disk, fogettaboutit. There's no
- way svn_wc_merge4() can do the merge. */
+ way svn_wc_merge5() can do the merge. */
if (wc_kind != svn_node_file || is_deleted)
{
const char *moved_to_abspath;
@@ -1524,8 +1543,8 @@ merge_file_changed(svn_wc_notify_state_t
* a conflict. Non-inheritable mergeinfo will be recorded, allowing
* future merges into non-shallow working copies to merge changes
* we missed this time around. */
- SVN_ERR(svn_wc__node_get_depth(&parent_depth, merge_b->ctx->wc_ctx,
- svn_dirent_dirname(mine_abspath,
+ SVN_ERR(svn_wc__node_get_depth(&parent_depth, ctx->wc_ctx,
+ svn_dirent_dirname(local_abspath,
scratch_pool),
scratch_pool));
if (parent_depth < svn_depth_files
@@ -1543,12 +1562,15 @@ merge_file_changed(svn_wc_notify_state_t
* #2282. See also notes/tree-conflicts/detection.txt
*/
err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
- merge_b->ctx->wc_ctx, mine_abspath,
+ ctx->wc_ctx, local_abspath,
scratch_pool, scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- svn_error_clear(err);
+ {
+ svn_error_clear(err);
+ moved_to_abspath = NULL;
+ }
else
return svn_error_trace(err);
}
@@ -1557,7 +1579,7 @@ merge_file_changed(svn_wc_notify_state_t
{
/* File has been moved away locally -- apply incoming
* changes at the new location. */
- mine_abspath = moved_to_abspath;
+ local_abspath = moved_to_abspath;
}
else
{
@@ -1567,7 +1589,7 @@ merge_file_changed(svn_wc_notify_state_t
reason = svn_wc_conflict_reason_deleted;
else
reason = svn_wc_conflict_reason_missing;
- SVN_ERR(tree_conflict(merge_b, mine_abspath, svn_node_file,
+ SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file,
svn_wc_conflict_action_edit, reason));
if (tree_conflicted)
*tree_conflicted = TRUE;
@@ -1593,31 +1615,37 @@ merge_file_changed(svn_wc_notify_state_t
*/
/* This callback is essentially no more than a wrapper around
- svn_wc_merge4(). Thank goodness that all the
+ svn_wc_merge5(). Thank goodness that all the
diff-editor-mechanisms are doing the hard work of getting the
fulltexts! */
- /* Do property merge before text merge so that keyword expansion takes
- into account the new property values. */
+ if (prop_state)
+ *prop_state = svn_wc_notify_state_unchanged;
+
if (prop_changes->nelts > 0)
{
- svn_boolean_t tree_conflicted2 = FALSE;
-
- SVN_ERR(merge_props_changed(prop_state, &tree_conflicted2,
- mine_abspath, prop_changes, original_props,
- baton, scratch_pool));
+ /* Filter entry-props and unneeded properties in case of a record only
+ merge */
+ SVN_ERR(prepare_merge_props_changed(&prop_changes, local_abspath,
+ prop_changes, merge_b,
+ scratch_pool, scratch_pool));
+ }
- /* If the prop change caused a tree-conflict, just bail. */
- if (tree_conflicted2)
- {
- if (tree_conflicted != NULL)
- *tree_conflicted = TRUE;
+ SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
+ svn_node_file, merge_b));
- return SVN_NO_ERROR;
- }
+ /* Do property merge now, if we are not going to perform a text merge */
+ if ((merge_b->record_only || !older_abspath) && prop_changes->nelts)
+ {
+ SVN_ERR(svn_wc_merge_props3(prop_state, ctx->wc_ctx, local_abspath,
+ left, right,
+ original_props, prop_changes,
+ merge_b->dry_run,
+ ctx->conflict_func2,
+ ctx->conflict_baton2,
+ ctx->cancel_func, ctx->cancel_baton,
+ scratch_pool));
}
- else if (prop_state)
- *prop_state = svn_wc_notify_state_unchanged;
/* Easy out: We are only applying mergeinfo differences. */
if (merge_b->record_only)
@@ -1630,7 +1658,7 @@ merge_file_changed(svn_wc_notify_state_t
if (older_abspath)
{
svn_boolean_t has_local_mods;
- enum svn_wc_merge_outcome_t merge_outcome;
+ enum svn_wc_merge_outcome_t content_outcome;
/* xgettext: the '.working', '.merge-left.r%ld' and
'.merge-right.r%ld' strings are used to tag onto a file
@@ -1643,40 +1671,39 @@ merge_file_changed(svn_wc_notify_state_t
_(".merge-right.r%ld"),
yours_rev);
conflict_resolver_baton_t conflict_baton = { 0 };
- const svn_wc_conflict_version_t *left;
- const svn_wc_conflict_version_t *right;
- SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, merge_b->ctx->wc_ctx,
- mine_abspath, FALSE, scratch_pool));
+ SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, ctx->wc_ctx,
+ local_abspath, FALSE, scratch_pool));
- conflict_baton.wrapped_func = merge_b->ctx->conflict_func2;
- conflict_baton.wrapped_baton = merge_b->ctx->conflict_baton2;
+ conflict_baton.wrapped_func = ctx->conflict_func2;
+ conflict_baton.wrapped_baton = ctx->conflict_baton2;
conflict_baton.conflicted_paths = &merge_b->conflicted_paths;
conflict_baton.pool = merge_b->pool;
- SVN_ERR(make_conflict_versions(&left, &right, mine_abspath,
- svn_node_file, merge_b));
- SVN_ERR(svn_wc_merge4(&merge_outcome, merge_b->ctx->wc_ctx,
- older_abspath, yours_abspath, mine_abspath,
+ /* Do property merge and text merge in one step so that keyword expansion
+ takes into account the new property values. */
+ SVN_ERR(svn_wc_merge5(&content_outcome, prop_state, ctx->wc_ctx,
+ older_abspath, yours_abspath, local_abspath,
left_label, right_label, target_label,
left, right,
merge_b->dry_run, merge_b->diff3_cmd,
- merge_b->merge_options, prop_changes,
+ merge_b->merge_options,
+ original_props, prop_changes,
conflict_resolver, &conflict_baton,
- merge_b->ctx->cancel_func,
- merge_b->ctx->cancel_baton,
+ ctx->cancel_func,
+ ctx->cancel_baton,
scratch_pool));
if (content_state)
{
- if (merge_outcome == svn_wc_merge_conflict)
+ if (content_outcome == svn_wc_merge_conflict)
*content_state = svn_wc_notify_state_conflicted;
else if (has_local_mods
- && merge_outcome != svn_wc_merge_unchanged)
+ && content_outcome != svn_wc_merge_unchanged)
*content_state = svn_wc_notify_state_merged;
- else if (merge_outcome == svn_wc_merge_merged)
+ else if (content_outcome == svn_wc_merge_merged)
*content_state = svn_wc_notify_state_changed;
- else if (merge_outcome == svn_wc_merge_no_merge)
+ else if (content_outcome == svn_wc_merge_no_merge)
*content_state = svn_wc_notify_state_missing;
else /* merge_outcome == svn_wc_merge_unchanged */
*content_state = svn_wc_notify_state_unchanged;
@@ -3760,11 +3787,11 @@ ensure_implicit_mergeinfo(svn_client__me
REVISION1 and REVISION2 describe the merge range requested from
MERGEINFO_PATH.
- TARGET_MERGEINFO is the portion of CHILD->ABSPATH's explicit or inherited
+ TARGET_RANGELIST is the portion of CHILD->ABSPATH's explicit or inherited
mergeinfo that intersects with the merge history described by
- MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2. TARGET_MERGEINFO
+ MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2. TARGET_RANGELIST
should be NULL if there is no explicit or inherited mergeinfo on
- CHILD->ABSPATH or an empty hash if CHILD->ABSPATH has empty mergeinfo or
+ CHILD->ABSPATH or an empty list if CHILD->ABSPATH has empty mergeinfo or
explicit mergeinfo that exclusively describes non-intersecting history
with MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2.
@@ -3779,7 +3806,7 @@ static svn_error_t *
filter_merged_revisions(svn_client__merge_path_t *parent,
svn_client__merge_path_t *child,
const char *mergeinfo_path,
- svn_mergeinfo_t target_mergeinfo,
+ apr_array_header_t *target_rangelist,
svn_revnum_t revision1,
svn_revnum_t revision2,
svn_boolean_t child_inherits_implicit,
@@ -3788,7 +3815,7 @@ filter_merged_revisions(svn_client__merg
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- apr_array_header_t *requested_rangelist, *target_rangelist,
+ apr_array_header_t *requested_rangelist,
*target_implicit_rangelist, *explicit_rangelist;
/* Convert REVISION1 and REVISION2 to a rangelist.
@@ -3813,12 +3840,8 @@ filter_merged_revisions(svn_client__merg
our svn_rangelist_* APIs to work properly. */
SVN_ERR(svn_rangelist_reverse(requested_rangelist, scratch_pool));
- if (target_mergeinfo)
- target_rangelist = apr_hash_get(target_mergeinfo,
- mergeinfo_path, APR_HASH_KEY_STRING);
- else
- target_rangelist = NULL;
-
+ /* Set EXPLICIT_RANGELIST to the list of source-range revs that are
+ already recorded as merged to target. */
if (target_rangelist)
{
/* Return the intersection of the revs which are both already
@@ -3902,16 +3925,12 @@ filter_merged_revisions(svn_client__merg
}
else /* This is a forward merge */
{
- if (target_mergeinfo)
- target_rangelist = apr_hash_get(target_mergeinfo, mergeinfo_path,
- APR_HASH_KEY_STRING);
- else
- target_rangelist = NULL;
-
- /* See earlier comment preceding svn_rangelist_intersect() for
- why we don't consider inheritance here. */
+ /* Set EXPLICIT_RANGELIST to the list of source-range revs that are
+ NOT already recorded as merged to target. */
if (target_rangelist)
{
+ /* See earlier comment preceding svn_rangelist_intersect() for
+ why we don't consider inheritance here. */
SVN_ERR(svn_rangelist_remove(&explicit_rangelist,
target_rangelist,
requested_rangelist, FALSE,
@@ -4047,54 +4066,40 @@ calculate_remaining_ranges(svn_client__m
? source->loc2->url : source->loc1->url;
/* Intersection of TARGET_MERGEINFO and the merge history
described by SOURCE. */
- svn_mergeinfo_t adjusted_target_mergeinfo = NULL;
+ apr_array_header_t *target_rangelist;
svn_revnum_t child_base_revision;
/* Determine which of the requested ranges to consider merging... */
SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &mergeinfo_path,
primary_url, result_pool));
- /* Does SOURCE describe a single, unbroken line of history or is there a
- copy as allowed by `MERGEINFO MERGE SOURCE NORMALIZATION'? */
- if (implicit_src_gap && child->pre_merge_mergeinfo)
- {
- /* Handle issue #3242: The presence of IMPLICIT_SRC_GAP implies that
- a single copy of SOURCE->LOC1->URL@SOURCE->LOC1->REV was made
- between SOURCE->LOC1->REV + 1 and SOURCE->LOC2->REV and that
- there exists a single range M:N, where
- SOURCE->LOC1->REV < M < N < SOURCE->LOC2->REV, such that
- SOURCE->LOC2->URL@M:SOURCE->LOC2->URL@N either doesn't exist
- or describes a different line of history than SOURCE. In either
- case we don't want to consider this range as merged so remove it
- from TARGET_MERGEINFO. */
- apr_array_header_t *explicit_mergeinfo_gap_ranges =
- apr_hash_get(child->pre_merge_mergeinfo, mergeinfo_path,
- APR_HASH_KEY_STRING);
-
- if (explicit_mergeinfo_gap_ranges)
- {
- svn_mergeinfo_t gap_mergeinfo = apr_hash_make(scratch_pool);
-
- apr_hash_set(gap_mergeinfo, mergeinfo_path, APR_HASH_KEY_STRING,
- implicit_src_gap);
- SVN_ERR(svn_mergeinfo_remove2(&adjusted_target_mergeinfo,
- gap_mergeinfo, target_mergeinfo,
- FALSE, result_pool, scratch_pool));
- }
- }
+ /* Set TARGET_RANGELIST to the portion of TARGET_MERGEINFO that refers
+ to SOURCE (excluding any gap in SOURCE): first get all ranges from
+ TARGET_MERGEINFO that refer to the path of SOURCE, and then prune
+ any ranges that lie in the gap in SOURCE.
+
+ ### [JAF] In fact, that may still leave some ranges that lie entirely
+ outside the range of SOURCE; it seems we don't care about that. */
+ if (target_mergeinfo)
+ target_rangelist = apr_hash_get(target_mergeinfo, mergeinfo_path,
+ APR_HASH_KEY_STRING);
else
+ target_rangelist = NULL;
+ if (implicit_src_gap && target_rangelist)
{
- /* The simple case: SOURCE->LOC1->URL2@SOURCE->LOC1->REV:
- SOURCE->LOC2->URL2@SOURCE->LOC2->REV describes two locations
- along a single, unbroken line of history, there is nothing to
- filter out. */
- adjusted_target_mergeinfo = target_mergeinfo;
+ /* Remove any mergeinfo referring to the 'gap' in SOURCE, as that
+ mergeinfo doesn't really refer to SOURCE at all but instead
+ refers to locations that are non-existent or on a different
+ line of history. (Issue #3242.) */
+ SVN_ERR(svn_rangelist_remove(&target_rangelist,
+ implicit_src_gap, target_rangelist,
+ FALSE, result_pool));
}
/* Initialize CHILD->REMAINING_RANGES and filter out revisions already
merged (or, in the case of reverse merges, ranges not yet merged). */
SVN_ERR(filter_merged_revisions(parent, child, mergeinfo_path,
- adjusted_target_mergeinfo,
+ target_rangelist,
source->loc1->rev, source->loc2->rev,
child_inherits_implicit,
ra_session, ctx, result_pool,
@@ -8740,6 +8745,7 @@ do_directory_merge(svn_mergeinfo_catalog
{
const char *mergeinfo_path;
+ /* ### Leaks merge_conflict_err */
SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &mergeinfo_path,
primary_url, scratch_pool));
err = record_mergeinfo_for_dir_merge(result_catalog,
@@ -10940,6 +10946,58 @@ svn_client_merge_peg4(const char *source
#ifdef SVN_WITH_SYMMETRIC_MERGE
+/* The location-history of a branch.
+ *
+ * This structure holds the set of path-revisions occupied by a branch,
+ * from an externally chosen 'tip' location back to its origin. The
+ * 'tip' location is the youngest location that we are considering on
+ * the branch. */
+typedef struct branch_history_t
+{
+ /* The tip location of the branch. That is, the youngest location that's
+ * in the repository and that we're considering. If we're considering a
+ * target branch right up to an uncommitted WC, then this is the WC base
+ * (pristine) location. */
+ svn_client__pathrev_t *tip;
+ /* The location-segment history, as mergeinfo. */
+ svn_mergeinfo_t history;
+ /* Whether the location-segment history reached as far as (necessarily
+ the root path in) revision 0 -- a fact that can't be represented as
+ mergeinfo. */
+ svn_boolean_t has_r0_history;
+} branch_history_t;
+
+/* Return the location on BRANCH_HISTORY at revision REV, or NULL if none. */
+static svn_client__pathrev_t *
+location_on_branch_at_rev(const branch_history_t *branch_history,
+ svn_revnum_t rev,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, branch_history->history); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *fspath = svn__apr_hash_index_key(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
+ int i;
+
+ for (i = 0; i < rangelist->nelts; i++)
+ {
+ svn_merge_range_t *r = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+ if (r->start < rev && rev <= r->end)
+ {
+ return svn_client__pathrev_create_with_relpath(
+ branch_history->tip->repos_root_url,
+ branch_history->tip->repos_uuid,
+ rev, fspath + 1, result_pool);
+ }
+ }
+ }
+ return NULL;
+}
+
/* Details of a symmetric merge. */
struct svn_client__symmetric_merge_t
{
@@ -10951,8 +11009,22 @@ typedef struct source_and_target_t
{
svn_client__pathrev_t *source;
svn_ra_session_t *source_ra_session;
+ branch_history_t source_branch;
+
merge_target_t *target;
svn_ra_session_t *target_ra_session;
+ branch_history_t target_branch;
+
+ /* The complete mergeinfo on SOURCE.
+ That is, the explicit or inherited mergeinfo. */
+ svn_mergeinfo_t source_mergeinfo;
+
+ /* The complete mergeinfo on (the current, working version of) TARGET.
+ That is, the explicit or inherited mergeinfo. */
+ svn_mergeinfo_t target_mergeinfo;
+
+ /* Repos location of the youngest common ancestor of SOURCE and TARGET. */
+ svn_client__pathrev_t *yca;
} source_and_target_t;
/* "Open" the source and target branches of a merge. That means:
@@ -11005,18 +11077,214 @@ close_source_and_target(source_and_targe
return SVN_NO_ERROR;
}
+/* Set *INTERSECTION_P to the intersection of BRANCH_HISTORY with the
+ * revision range OLDEST_REV to YOUNGEST_REV (inclusive).
+ *
+ * If the intersection is empty, the result will be a branch history object
+ * containing an empty (not null) history.
+ *
+ * ### The 'tip' of the result is currently unchanged.
+ */
+static svn_error_t *
+branch_history_intersect_range(branch_history_t **intersection_p,
+ const branch_history_t *branch_history,
+ svn_revnum_t oldest_rev,
+ svn_revnum_t youngest_rev,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ branch_history_t *result = apr_palloc(result_pool, sizeof(*result));
+
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(oldest_rev));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+ SVN_ERR_ASSERT(oldest_rev >= 1);
+ /* Allow a just-empty range (oldest = youngest + 1) but not an
+ * arbitrary reverse range (such as oldest = youngest + 2). */
+ SVN_ERR_ASSERT(oldest_rev <= youngest_rev + 1);
+
+ if (oldest_rev <= youngest_rev)
+ {
+ SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
+ &result->history, branch_history->history,
+ youngest_rev, oldest_rev - 1, TRUE /* include_range */,
+ result_pool, scratch_pool));
+ result->history = svn_mergeinfo_dup(result->history, result_pool);
+ }
+ else
+ {
+ result->history = apr_hash_make(result_pool);
+ }
+ result->has_r0_history = FALSE;
+
+ /* ### TODO: Set RESULT->tip to the tip of the intersection. */
+ result->tip = svn_client__pathrev_dup(branch_history->tip, result_pool);
+
+ *intersection_p = result;
+ return SVN_NO_ERROR;
+}
+
+/* Set *OLDEST_P and *YOUNGEST_P to the oldest and youngest locations
+ * (inclusive) along BRANCH. OLDEST_P and/or YOUNGEST_P may be NULL if not
+ * wanted.
+ */
+static svn_error_t *
+branch_history_get_endpoints(svn_client__pathrev_t **oldest_p,
+ svn_client__pathrev_t **youngest_p,
+ const branch_history_t *branch,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_revnum_t youngest_rev, oldest_rev;
+
+ SVN_ERR(svn_mergeinfo__get_range_endpoints(
+ &youngest_rev, &oldest_rev,
+ branch->history, scratch_pool));
+ if (oldest_p)
+ *oldest_p = location_on_branch_at_rev(
+ branch, oldest_rev + 1, result_pool, scratch_pool);
+ if (youngest_p)
+ *youngest_p = location_on_branch_at_rev(
+ branch, youngest_rev, result_pool, scratch_pool);
+ return SVN_NO_ERROR;
+}
+
+/* Set *BASE_P to the last location on SOURCE_BRANCH such that all changes
+ * on SOURCE_BRANCH up to and including *BASE_P have already been merged
+ * into the target branch -- or, specifically, are recorded in
+ * TARGET_MERGEINFO.
+ *
+ * *BASE_P TIP
+ * o-------o-----------o--- SOURCE_BRANCH
+ * / \
+ * -----o prev. \
+ * YCA \ merges \
+ * o-----------o-----------
+ *
+ * In terms of mergeinfo:
+ *
+ * Source a--... o=change, -=no-op revision
+ * branch / \
+ * YCA --> o a---o---o---o---o--- d=delete, a=add-as-a-copy
+ *
+ * Eligible -.eee.eeeeeeeeeeeeeeeeeeee .=not a source branch location
+ *
+ * Tgt-mi -.mmm.mm-mm-------m------- m=merged, -=not merged
+ *
+ * Eligible -.---.--e--eeeeeee-eeeeeee
+ *
+ * Next --------^----------------- BASE is just before here.
+ *
+ * / \
+ * -----o prev. \
+ * YCA \ merges \
+ * o-----------o-------------
+ *
+ * If no locations on SOURCE_BRANCH are recorded in TARGET_MERGEINFO, set
+ * *BASE_P to the YCA.
+ */
+static svn_error_t *
+find_last_merged_location(svn_client__pathrev_t **base_p,
+ svn_client__pathrev_t *yca,
+ const branch_history_t *source_branch,
+ svn_mergeinfo_t target_mergeinfo,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ /*
+ To find the youngest location on BRANCH_A that is fully merged to BRANCH_B:
+
+ Find the longest set of locations in BRANCH_A, starting after YCA,
+ such that each location is (any of):
+ (a) in BRANCH_B's mergeinfo; or
+ (b) a merge onto BRANCH_A of logical changes that are all from the
+ target branch or already in BRANCH_B's mergeinfo; or
+ (c) inoperative on BRANCH_A.
+
+ Report the youngest such location, or the YCA if there are none.
+
+ Part (b) can perhaps, initially, be simplified to something like:
+ a merge onto BRANCH_A of (including? entirely?) revisions from
+ BRANCH_B's history.
+
+ Part (c) is only necessary if we want to allow sparse mergeinfo --
+ that is, if we don't want to do some partially- or completely-
+ inoperative merges to fill in mergeinfo gaps.
+ */
+ branch_history_t *eligible_locations;
+
+ /* Start with a list of all source locations after YCA up to the tip. */
+ SVN_ERR(branch_history_intersect_range(
+ &eligible_locations,
+ source_branch, yca->rev + 1, source_branch->tip->rev,
+ scratch_pool, scratch_pool));
+
+ /* Remove any locations that match (a), (b) or (c). */
+ /* For (a), remove any locations that are in TARGET's mergeinfo. */
+ SVN_ERR(svn_mergeinfo_remove(&eligible_locations->history,
+ target_mergeinfo, eligible_locations->history,
+ scratch_pool));
+ /* For (b) ... */
+
+ /* For (c) ... */
+
+ /* This leaves a list of source locations that are eligible to merge.
+ The location that we want is the source location just before oldest
+ eligible location remaining in this list; or the youngest source
+ location if there are none left in this list. */
+ if (apr_hash_count(eligible_locations->history) > 0)
+ {
+ /* Find the oldest eligible rev.
+ * Eligible -.---.--e--eeeeeee-eeeeeee
+ * ^
+ * BASE is just before here.
+ */
+
+ svn_client__pathrev_t *oldest_eligible;
+ branch_history_t *contiguous_source;
+
+ SVN_ERR(branch_history_get_endpoints(
+ &oldest_eligible, NULL,
+ eligible_locations, scratch_pool, scratch_pool));
+
+ /* Find the branch location just before the oldest eligible rev.
+ * (We can't just subtract 1 from the rev because the branch might
+ * have a gap there.) */
+ SVN_ERR(branch_history_intersect_range(
+ &contiguous_source,
+ source_branch, yca->rev, oldest_eligible->rev - 1,
+ scratch_pool, scratch_pool));
+ SVN_ERR(branch_history_get_endpoints(
+ NULL, base_p,
+ contiguous_source, result_pool, scratch_pool));
+ }
+ else
+ {
+ /* The whole source branch is merged already, so the base for
+ * the next merge is its tip. */
+ *base_p = source_branch->tip;
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Find a merge base location on the target branch, like in a sync
* merge.
*
- * (Source-left) (Source-right = S_T->source)
- * BASE RIGHT
+ * BASE S_T->source
* o-------o-----------o---
* / \ \
* -----o prev. \ \ this
* YCA \ merge \ \ merge
* o-----------o-----------o
- * TARGET
+ * S_T->target
+ *
+ * Set *BASE_P to BASE, the youngest location in the history of S_T->source
+ * (at or after the YCA) at which all revisions up to BASE are recorded as
+ * merged into S_T->target.
*
+ * If no locations on the history of S_T->source are recorded as merged to
+ * S_T->target, set *BASE_P to the YCA.
*/
static svn_error_t *
find_base_on_source(svn_client__pathrev_t **base_p,
@@ -11025,67 +11293,35 @@ find_base_on_source(svn_client__pathrev_
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_mergeinfo_t target_mergeinfo;
- svn_client__merge_path_t *merge_target;
- svn_boolean_t inherited;
- svn_client__pathrev_t loc1;
- merge_source_t source;
- svn_merge_range_t *r;
-
- merge_target = svn_client__merge_path_create(s_t->target->abspath,
- scratch_pool);
-
- /* Fetch target mergeinfo (all the way back to revision 1). */
- SVN_ERR(get_full_mergeinfo(&target_mergeinfo,
- &merge_target->implicit_mergeinfo,
- &inherited, svn_mergeinfo_inherited,
- s_t->target_ra_session, s_t->target->abspath,
- s_t->source->rev, 1,
- ctx, scratch_pool, scratch_pool));
-
- /* In order to find the first unmerged change in the source, set
- * MERGE_TARGET->remaining_ranges to the ranges left to merge,
- * and look at the start revision of the first such range. */
- loc1.repos_root_url = s_t->source->repos_root_url;
- loc1.repos_uuid = s_t->source->repos_uuid;
- loc1.url = s_t->source->url; /* ### WRONG: need historical URL/REV */
- loc1.rev = 1;
- source.loc1 = &loc1;
- source.loc2 = s_t->source;
- SVN_ERR(calculate_remaining_ranges(NULL, merge_target,
- &source,
- target_mergeinfo,
- NULL /*merge_b->implicit_src_gap*/,
- FALSE /*child_inherits_implicit*/,
- s_t->source_ra_session,
- ctx, scratch_pool, scratch_pool));
-
- r = APR_ARRAY_IDX(merge_target->remaining_ranges, 0, svn_merge_range_t *);
-
- /* ### WRONG: need historical URL instead of s_t->source->url. */
- *base_p = svn_client__pathrev_create(s_t->source->repos_root_url,
- s_t->source->repos_uuid,
- r->start, s_t->source->url, result_pool);
+ SVN_ERR(find_last_merged_location(base_p,
+ s_t->yca,
+ &s_t->source_branch,
+ s_t->target_mergeinfo,
+ ctx, result_pool, scratch_pool));
return SVN_NO_ERROR;
}
/* Find a merge base location on the target branch, like in a reintegrate
* merge.
*
- * MID RIGHT
+ * MID S_T->source
* o-----------o-------o---
* / prev. / \
* -----o merge / \ this
* YCA \ / \ merge
* o-------o---------------o
- * BASE TARGET
+ * BASE S_T->target
+ *
+ * Set *BASE_P to BASE, the youngest location in the history of S_T->target
+ * (at or after the YCA) at which all revisions up to BASE are recorded as
+ * merged into S_T->source.
*
- * Set *BASE_P to the latest location on the history of S_T->target at
- * which all revisions up to *BASE_P are recorded as merged into RIGHT
- * (which is S_T->source).
+ * Set *MID_P to the first location on the history of S_T->source at which
+ * all revisions up to BASE are recorded as merged.
+ * ### This is not implemented yet.
*
- * ### TODO: Set *MID_P to the first location on the history of
- * S_T->source at which all revisions up to BASE_P are recorded as merged.
+ * If no locations on the history of S_T->target are recorded as merged to
+ * S_T->source, set both *BASE_P and *MID_P to the YCA.
*/
static svn_error_t *
find_base_on_target(svn_client__pathrev_t **base_p,
@@ -11095,34 +11331,12 @@ find_base_on_target(svn_client__pathrev_
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_mergeinfo_catalog_t unmerged_to_source_mergeinfo_catalog;
- svn_mergeinfo_catalog_t merged_to_source_mergeinfo_catalog;
- apr_hash_t *subtrees_with_mergeinfo;
-
- /* Find all the subtrees in TARGET_WCPATH that have explicit mergeinfo. */
- SVN_ERR(get_wc_explicit_mergeinfo_catalog(&subtrees_with_mergeinfo,
- s_t->target->abspath,
- svn_depth_infinity,
- ctx, scratch_pool, scratch_pool));
-
- SVN_ERR(calculate_left_hand_side(base_p,
- &merged_to_source_mergeinfo_catalog,
- &unmerged_to_source_mergeinfo_catalog,
- s_t->target,
- subtrees_with_mergeinfo,
- s_t->source,
- s_t->source_ra_session,
- s_t->target_ra_session,
- ctx, result_pool, scratch_pool));
-
- if (*base_p)
- {
- *mid_p = s_t->source; /* ### WRONG! This is quite difficult. */
- }
- else
- {
- *mid_p = NULL;
- }
+ SVN_ERR(find_last_merged_location(base_p,
+ s_t->yca,
+ &s_t->target_branch,
+ s_t->source_mergeinfo,
+ ctx, result_pool, scratch_pool));
+ *mid_p = *base_p; /* ### Wrong! */
return SVN_NO_ERROR;
}
@@ -11130,8 +11344,7 @@ find_base_on_target(svn_client__pathrev_
/* The body of svn_client__find_symmetric_merge(), which see.
*/
static svn_error_t *
-find_symmetric_merge(svn_client__pathrev_t **yca_p,
- svn_client__pathrev_t **base_p,
+find_symmetric_merge(svn_client__pathrev_t **base_p,
svn_client__pathrev_t **mid_p,
source_and_target_t *s_t,
svn_client_ctx_t *ctx,
@@ -11140,8 +11353,37 @@ find_symmetric_merge(svn_client__pathrev
{
svn_client__pathrev_t *base_on_source, *base_on_target, *mid;
+ /* Fetch mergeinfo of source branch (tip) and target branch (working). */
+ SVN_ERR(svn_client__get_repos_mergeinfo(&s_t->source_mergeinfo,
+ s_t->source_ra_session,
+ s_t->source->url,
+ s_t->source->rev,
+ svn_mergeinfo_inherited,
+ FALSE /* squelch_incapable */,
+ scratch_pool));
+ SVN_ERR(svn_client__get_wc_or_repos_mergeinfo(&s_t->target_mergeinfo,
+ NULL /* inherited */,
+ NULL /* from_repos */,
+ FALSE /* repos_only */,
+ svn_mergeinfo_inherited,
+ s_t->target_ra_session,
+ s_t->target->abspath,
+ ctx, scratch_pool));
+
+ /* Get the location-history of each branch. */
+ s_t->source_branch.tip = s_t->source;
+ SVN_ERR(svn_client__get_history_as_mergeinfo(
+ &s_t->source_branch.history, &s_t->source_branch.has_r0_history,
+ s_t->source, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+ s_t->source_ra_session, ctx, scratch_pool));
+ s_t->target_branch.tip = &s_t->target->loc;
+ SVN_ERR(svn_client__get_history_as_mergeinfo(
+ &s_t->target_branch.history, &s_t->target_branch.has_r0_history,
+ &s_t->target->loc, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+ s_t->target_ra_session, ctx, scratch_pool));
+
SVN_ERR(svn_client__get_youngest_common_ancestor(
- yca_p, s_t->source, &s_t->target->loc,
+ &s_t->yca, s_t->source, &s_t->target->loc,
ctx, result_pool, result_pool));
/* Find the latest revision of A synced to B and the latest
@@ -11155,32 +11397,20 @@ find_symmetric_merge(svn_client__pathrev
SVN_ERR(find_base_on_target(&base_on_target, &mid, s_t,
ctx, scratch_pool, scratch_pool));
- if (base_on_source)
- SVN_DBG(("base on source: %s@%ld\n", base_on_source->url, base_on_source->rev));
- if (base_on_target)
- SVN_DBG(("base on target: %s@%ld\n", base_on_target->url, base_on_target->rev));
+ SVN_DBG(("base on source: %s@%ld\n", base_on_source->url, base_on_source->rev));
+ SVN_DBG(("base on target: %s@%ld\n", base_on_target->url, base_on_target->rev));
/* Choose a base. */
- if (base_on_source
- && (! base_on_target || (base_on_source->rev > base_on_target->rev)))
+ if (base_on_source->rev >= base_on_target->rev)
{
*base_p = base_on_source;
*mid_p = NULL;
}
- else if (base_on_target)
+ else
{
*base_p = base_on_target;
*mid_p = mid;
}
- else
- {
- /* No previous merge was found, so this is the simple case where
- * the base is the youngest common ancestor of the branches. We'll
- * set MID=NULL; in theory the end result should be the same if we
- * set MID=YCA instead. */
- *base_p = *yca_p;
- *mid_p = NULL;
- }
return SVN_NO_ERROR;
}
@@ -11211,8 +11441,9 @@ svn_client__find_symmetric_merge(svn_cli
&s_t->target->loc, target_wcpath,
TRUE /* strict_urls */, scratch_pool));
- SVN_ERR(find_symmetric_merge(&merge->yca, &merge->base, &merge->mid, s_t,
+ SVN_ERR(find_symmetric_merge(&merge->base, &merge->mid, s_t,
ctx, result_pool, scratch_pool));
+ merge->yca = s_t->yca;
merge->right = s_t->source;
*merge_p = merge;
Modified: subversion/branches/ev2-export/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/resolved.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/resolved.c Fri May 11 00:05:41 2012
@@ -55,12 +55,14 @@ svn_client_resolve(const char *path,
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
- SVN_ERR(svn_wc_resolved_conflict5(ctx->wc_ctx, local_abspath,
+ SVN_ERR(svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
depth,
TRUE /* resolve_text */,
"" /* resolve_prop (ALL props) */,
TRUE /* resolve_tree */,
conflict_choice,
+ ctx->conflict_func2,
+ ctx->conflict_baton2,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func2, ctx->notify_baton2,
pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/blame.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/blame.c Fri May 11 00:05:41 2012
@@ -427,7 +427,7 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_parser_t *parser_ctx;
- const char *relative_url, *basecoll_url, *req_url;
+ const char *req_url;
svn_error_t *err;
blame_ctx = apr_pcalloc(pool, sizeof(*blame_ctx));
@@ -440,10 +440,10 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
blame_ctx->include_merged_revisions = include_merged_revisions;
blame_ctx->done = FALSE;
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
- NULL, session->session_url.path,
- end, NULL, pool));
- req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ NULL /* url */, end,
+ pool, pool));
handler = apr_pcalloc(pool, sizeof(*handler));
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c Fri May 11 00:05:41 2012
@@ -48,17 +48,18 @@
/* Structure associated with a CHECKOUT request. */
typedef struct checkout_context_t {
-
- /* Record information about the checked-out resource. */
- const char *resource_url;
-
- /* These four fields are used during the actual CHECKOUT. They will be
- NULL for resources implicitly checked out (ie. an ancestor was
- checked out). */
+ /* The handler running the CHECKOUT. */
svn_ra_serf__handler_t *handler;
+
+ /* The pool for allocating RESOURCE_URL. */
apr_pool_t *result_pool;
+
+ /* The activity that will hold the checked-out resource. */
const char *activity_url;
+ /* The output: */
+ const char *resource_url;
+
} checkout_context_t;
/* Baton passed back with the commit editor. */
@@ -84,7 +85,7 @@ typedef struct commit_context_t {
/* HTTP v1 stuff (only valid when 'txn_url' is NULL) */
const char *activity_url; /* activity base URL... */
- const checkout_context_t *baseline; /* checkout for the baseline */
+ const char *baseline_url; /* the working-baseline resource */
const char *checked_in_url; /* checked-in root to base CHECKOUTs from */
const char *vcc_url; /* vcc url */
@@ -162,9 +163,9 @@ typedef struct dir_context_t {
apr_hash_t *changed_props;
apr_hash_t *removed_props;
- /* The checked out context for this directory. May be NULL; if so
+ /* The checked-out working resource for this directory. May be NULL; if so
call checkout_dir() first. */
- checkout_context_t *checkout;
+ const char *working_url;
} dir_context_t;
@@ -184,8 +185,8 @@ typedef struct file_context_t {
const char *relpath;
const char *name;
- /* The checked out context for this file. */
- checkout_context_t *checkout;
+ /* The checked-out working resource for this file. */
+ const char *working_url;
/* The base revision of the file. */
svn_revnum_t base_revision;
@@ -325,16 +326,78 @@ handle_checkout(serf_request_t *request,
return err;
}
+
+/* Using the HTTPv1 protocol, perform a CHECKOUT of NODE_URL within the
+ given COMMIT_CTX. The resulting working resource will be returned in
+ *WORKING_URL, allocated from RESULT_POOL. All temporary allocations
+ are performed in SCRATCH_POOL.
+
+ ### are these URLs actually repos relpath values? or fspath? or maybe
+ ### the abspath portion of the full URL.
+
+ This function operates synchronously.
+
+ Strictly speaking, we could perform "all" of the CHECKOUT requests
+ when the commit starts, and only block when we need a specific
+ answer. Or, at a minimum, send off these individual requests async
+ and block when we need the answer (eg PUT or PROPPATCH).
+
+ However: the investment to speed this up is not worthwhile, given
+ that CHECKOUT (and the related round trip) is completely obviated
+ in HTTPv2.
+*/
static svn_error_t *
-checkout_dir(dir_context_t *dir)
+checkout_node(const char **working_url,
+ const commit_context_t *commit_ctx,
+ const char *node_url,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_serf__handler_t handler = { 0 };
+ checkout_context_t checkout_ctx = { 0 };
+
+ /* HANDLER_POOL is the scratch pool since we don't need to remember
+ anything from the handler. We just want the working resource. */
+ handler.handler_pool = scratch_pool;
+ handler.session = commit_ctx->session;
+ handler.conn = commit_ctx->conn;
+
+ checkout_ctx.handler = &handler;
+ checkout_ctx.result_pool = result_pool;
+ checkout_ctx.activity_url = commit_ctx->activity_url;
+
+ handler.body_delegate = create_checkout_body;
+ handler.body_delegate_baton = &checkout_ctx;
+ handler.body_type = "text/xml";
+
+ handler.response_handler = handle_checkout;
+ handler.response_baton = &checkout_ctx;
+
+ handler.method = "CHECKOUT";
+ handler.path = node_url;
+
+ SVN_ERR(svn_ra_serf__context_run_one(&handler, scratch_pool));
+
+ if (handler.sline.code != 201)
+ return svn_error_trace(return_response_err(&handler));
+
+ /* Already in the correct pool. */
+ *working_url = checkout_ctx.resource_url;
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+checkout_dir(dir_context_t *dir,
+ apr_pool_t *scratch_pool)
{
- checkout_context_t *checkout_ctx;
- svn_ra_serf__handler_t *handler;
svn_error_t *err;
dir_context_t *p_dir = dir;
const char *checkout_url;
+ const char **working;
- if (dir->checkout)
+ if (dir->working_url)
{
return SVN_NO_ERROR;
}
@@ -346,67 +409,41 @@ checkout_dir(dir_context_t *dir)
if (p_dir->added)
{
/* Implicitly checkout this dir now. */
- dir->checkout = apr_pcalloc(dir->pool, sizeof(*dir->checkout));
- dir->checkout->resource_url =
- svn_path_url_add_component2(dir->parent_dir->checkout->resource_url,
- dir->name, dir->pool);
-
+ dir->working_url = svn_path_url_add_component2(
+ dir->parent_dir->working_url,
+ dir->name, dir->pool);
return SVN_NO_ERROR;
}
p_dir = p_dir->parent_dir;
}
- /* Checkout our directory into the activity URL now. */
- handler = apr_pcalloc(dir->pool, sizeof(*handler));
- handler->handler_pool = dir->pool;
- handler->session = dir->commit->session;
- handler->conn = dir->commit->conn;
-
- checkout_ctx = apr_pcalloc(dir->pool, sizeof(*checkout_ctx));
- checkout_ctx->handler = handler;
- checkout_ctx->result_pool = dir->pool;
- checkout_ctx->activity_url = dir->commit->activity_url;
-
/* We could be called twice for the root: once to checkout the baseline;
* once to checkout the directory itself if we need to do so.
* Note: CHECKOUT_URL should live longer than HANDLER.
*/
- if (!dir->parent_dir && !dir->commit->baseline)
+ if (!dir->parent_dir && !dir->commit->baseline_url)
{
checkout_url = dir->commit->vcc_url;
- dir->commit->baseline = checkout_ctx;
+ working = &dir->commit->baseline_url;
}
else
{
checkout_url = dir->url;
- dir->checkout = checkout_ctx;
+ working = &dir->working_url;
}
- handler->body_delegate = create_checkout_body;
- handler->body_delegate_baton = checkout_ctx;
- handler->body_type = "text/xml";
-
- handler->response_handler = handle_checkout;
- handler->response_baton = checkout_ctx;
-
- handler->method = "CHECKOUT";
- handler->path = checkout_url;
-
- err = svn_ra_serf__context_run_one(handler, dir->pool);
+ /* Checkout our directory into the activity URL now. */
+ err = checkout_node(working, dir->commit, checkout_url,
+ dir->pool, scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_CONFLICT)
- SVN_ERR_W(err, apr_psprintf(dir->pool,
+ SVN_ERR_W(err, apr_psprintf(scratch_pool,
_("Directory '%s' is out of date; try updating"),
- svn_dirent_local_style(dir->relpath, dir->pool)));
+ svn_dirent_local_style(dir->relpath, scratch_pool)));
return err;
}
- if (handler->sline.code != 201)
- {
- return svn_error_trace(return_response_err(handler));
- }
-
return SVN_NO_ERROR;
}
@@ -424,16 +461,17 @@ checkout_dir(dir_context_t *dir)
* BASE_REVISION, and set *CHECKED_IN_URL to the concatenation of that
* with RELPATH.
*
- * Allocate the result in POOL, and use POOL for temporary allocation.
+ * Allocate the result in RESULT_POOL, and use SCRATCH_POOL for
+ * temporary allocation.
*/
static svn_error_t *
get_version_url(const char **checked_in_url,
svn_ra_serf__session_t *session,
- svn_ra_serf__connection_t *conn,
const char *relpath,
svn_revnum_t base_revision,
const char *parent_vsn_url,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
const char *root_checkout;
@@ -441,15 +479,16 @@ get_version_url(const char **checked_in_
{
const svn_string_t *current_version;
- SVN_ERR(session->wc_callbacks->get_wc_prop(session->wc_callback_baton,
- relpath,
- SVN_RA_SERF__WC_CHECKED_IN_URL,
- ¤t_version, pool));
+ SVN_ERR(session->wc_callbacks->get_wc_prop(
+ session->wc_callback_baton,
+ relpath,
+ SVN_RA_SERF__WC_CHECKED_IN_URL,
+ ¤t_version, scratch_pool));
if (current_version)
{
*checked_in_url =
- svn_urlpath__canonicalize(current_version->data, pool);
+ svn_urlpath__canonicalize(current_version->data, result_pool);
return SVN_NO_ERROR;
}
}
@@ -460,61 +499,50 @@ get_version_url(const char **checked_in_
}
else
{
- svn_ra_serf__propfind_context_t *propfind_ctx;
- apr_hash_t *props;
const char *propfind_url;
-
- props = apr_hash_make(pool);
+ svn_ra_serf__connection_t *conn = session->conns[0];
if (SVN_IS_VALID_REVNUM(base_revision))
{
- const char *bc_url, *bc_relpath;
-
/* mod_dav_svn can't handle the "Label:" header that
svn_ra_serf__deliver_props() is going to try to use for
this lookup, so we'll do things the hard(er) way, by
looking up the version URL from a resource in the
baseline collection. */
- SVN_ERR(svn_ra_serf__get_baseline_info(&bc_url, &bc_relpath,
- session, conn,
- session->session_url.path,
- base_revision, NULL, pool));
- propfind_url = svn_path_url_add_component2(bc_url, bc_relpath, pool);
+ /* ### conn==NULL for session->conns[0]. same as CONN. */
+ SVN_ERR(svn_ra_serf__get_stable_url(&propfind_url,
+ NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ NULL /* url */, base_revision,
+ scratch_pool, scratch_pool));
}
else
{
propfind_url = session->session_url.path;
}
- /* ### switch to svn_ra_serf__retrieve_props */
- SVN_ERR(svn_ra_serf__deliver_props(&propfind_ctx, props, session, conn,
- propfind_url, base_revision, "0",
- checked_in_props, NULL, pool));
- SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, session, pool));
-
- /* We wouldn't get here if the url wasn't found (404), so the checked-in
- property should have been set. */
- root_checkout =
- svn_ra_serf__get_ver_prop(props, propfind_url,
- base_revision, "DAV:", "checked-in");
-
+ SVN_ERR(svn_ra_serf__fetch_dav_prop(&root_checkout,
+ conn, propfind_url, base_revision,
+ "checked-in",
+ scratch_pool, scratch_pool));
if (!root_checkout)
return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("Path '%s' not present"),
session->session_url.path);
- root_checkout = svn_urlpath__canonicalize(root_checkout, pool);
+ root_checkout = svn_urlpath__canonicalize(root_checkout, scratch_pool);
}
- *checked_in_url = svn_path_url_add_component2(root_checkout, relpath, pool);
+ *checked_in_url = svn_path_url_add_component2(root_checkout, relpath,
+ result_pool);
return SVN_NO_ERROR;
}
static svn_error_t *
-checkout_file(file_context_t *file)
+checkout_file(file_context_t *file,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__handler_t *handler;
svn_error_t *err;
dir_context_t *parent_dir = file->parent_dir;
const char *checkout_url;
@@ -527,61 +555,33 @@ checkout_file(file_context_t *file)
if (parent_dir->added)
{
/* Implicitly checkout this file now. */
- file->checkout = apr_pcalloc(file->pool, sizeof(*file->checkout));
- file->checkout->resource_url =
- svn_path_url_add_component2(parent_dir->checkout->resource_url,
- svn_relpath_skip_ancestor(
- parent_dir->relpath, file->relpath),
- file->pool);
+ file->working_url = svn_path_url_add_component2(
+ parent_dir->working_url,
+ svn_relpath_skip_ancestor(
+ parent_dir->relpath, file->relpath),
+ file->pool);
return SVN_NO_ERROR;
}
parent_dir = parent_dir->parent_dir;
}
- /* Checkout our file into the activity URL now. */
- handler = apr_pcalloc(file->pool, sizeof(*handler));
- handler->handler_pool = file->pool;
- handler->session = file->commit->session;
- handler->conn = file->commit->conn;
-
- file->checkout = apr_pcalloc(file->pool, sizeof(*file->checkout));
- file->checkout->handler = handler;
- file->checkout->result_pool = file->pool;
- file->checkout->activity_url = file->commit->activity_url;
-
SVN_ERR(get_version_url(&checkout_url,
- file->commit->session, file->commit->conn,
+ file->commit->session,
file->relpath, file->base_revision,
- NULL, handler->handler_pool));
-
- handler->body_delegate = create_checkout_body;
- handler->body_delegate_baton = file->checkout;
- handler->body_type = "text/xml";
-
- handler->response_handler = handle_checkout;
- handler->response_baton = file->checkout;
-
- handler->method = "CHECKOUT";
- handler->path = checkout_url;
+ NULL, scratch_pool, scratch_pool));
- /* There's no need to wait here as we only need this when we start the
- * PROPPATCH or PUT of the file.
- */
- err = svn_ra_serf__context_run_one(handler, file->pool);
+ /* Checkout our file into the activity URL now. */
+ err = checkout_node(&file->working_url, file->commit, checkout_url,
+ file->pool, scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_CONFLICT)
- SVN_ERR_W(err, apr_psprintf(file->pool,
+ SVN_ERR_W(err, apr_psprintf(scratch_pool,
_("File '%s' is out of date; try updating"),
- svn_dirent_local_style(file->relpath, file->pool)));
+ svn_dirent_local_style(file->relpath, scratch_pool)));
return err;
}
- if (handler->sline.code != 201)
- {
- return svn_error_trace(return_response_err(handler));
- }
-
return SVN_NO_ERROR;
}
@@ -1054,8 +1054,8 @@ setup_copy_file_headers(serf_bucket_t *h
serf_bucket_headers_set(headers, "Destination", absolute_uri);
- serf_bucket_headers_set(headers, "Depth", "0");
- serf_bucket_headers_set(headers, "Overwrite", "T");
+ serf_bucket_headers_setn(headers, "Depth", "0");
+ serf_bucket_headers_setn(headers, "Overwrite", "T");
return SVN_NO_ERROR;
}
@@ -1079,19 +1079,18 @@ setup_copy_dir_headers(serf_bucket_t *he
else
{
uri.path = (char *)svn_path_url_add_component2(
- dir->parent_dir->checkout->resource_url,
+ dir->parent_dir->working_url,
dir->name, pool);
}
absolute_uri = apr_uri_unparse(pool, &uri, 0);
serf_bucket_headers_set(headers, "Destination", absolute_uri);
- serf_bucket_headers_set(headers, "Depth", "infinity");
- serf_bucket_headers_set(headers, "Overwrite", "T");
+ serf_bucket_headers_setn(headers, "Depth", "infinity");
+ serf_bucket_headers_setn(headers, "Overwrite", "T");
/* Implicitly checkout this dir now. */
- dir->checkout = apr_pcalloc(dir->pool, sizeof(*dir->checkout));
- dir->checkout->resource_url = apr_pstrdup(dir->pool, uri.path);
+ dir->working_url = apr_pstrdup(dir->pool, uri.path);
return SVN_NO_ERROR;
}
@@ -1121,8 +1120,8 @@ setup_delete_headers(serf_bucket_t *head
serf_bucket_headers_set(headers, "If", token_header);
if (ctx->keep_locks)
- serf_bucket_headers_set(headers, SVN_DAV_OPTIONS_HEADER,
- SVN_DAV_OPTION_KEEP_LOCKS);
+ serf_bucket_headers_setn(headers, SVN_DAV_OPTIONS_HEADER,
+ SVN_DAV_OPTION_KEEP_LOCKS);
}
}
@@ -1361,19 +1360,12 @@ open_root(void *edit_baton,
}
else
{
- svn_ra_serf__options_context_t *opt_ctx;
const char *activity_str;
- SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, ctx->session,
- ctx->session->conns[0],
- ctx->session->session_url.path,
- ctx->pool));
-
- SVN_ERR(svn_ra_serf__context_run_wait(
- svn_ra_serf__get_options_done_ptr(opt_ctx),
- ctx->session, ctx->pool));
-
- activity_str = svn_ra_serf__options_get_activity_collection(opt_ctx);
+ SVN_ERR(svn_ra_serf__v1_get_activity_collection(&activity_str,
+ ctx->session->conns[0],
+ ctx->pool,
+ ctx->pool));
if (!activity_str)
return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
_("The OPTIONS response did not include the "
@@ -1434,15 +1426,15 @@ open_root(void *edit_baton,
dir->removed_props = apr_hash_make(dir->pool);
SVN_ERR(get_version_url(&dir->url, dir->commit->session,
- dir->commit->conn, dir->relpath,
+ dir->relpath,
dir->base_revision, ctx->checked_in_url,
- dir->pool));
+ dir->pool, dir->pool /* scratch_pool */));
ctx->checked_in_url = dir->url;
/* Checkout our root dir */
- SVN_ERR(checkout_dir(dir));
+ SVN_ERR(checkout_dir(dir, dir->pool /* scratch_pool */));
- proppatch_target = ctx->baseline->resource_url;
+ proppatch_target = ctx->baseline_url;
}
@@ -1509,8 +1501,8 @@ delete_entry(const char *path,
else
{
/* Ensure our directory has been checked out */
- SVN_ERR(checkout_dir(dir));
- delete_target = svn_path_url_add_component2(dir->checkout->resource_url,
+ SVN_ERR(checkout_dir(dir, pool /* scratch_pool */));
+ delete_target = svn_path_url_add_component2(dir->working_url,
svn_relpath_basename(path,
NULL),
pool);
@@ -1612,12 +1604,12 @@ add_directory(const char *path,
else
{
/* Ensure our parent is checked out. */
- SVN_ERR(checkout_dir(parent));
+ SVN_ERR(checkout_dir(parent, dir->pool /* scratch_pool */));
dir->url = svn_path_url_add_component2(parent->commit->checked_in_url,
dir->name, dir->pool);
mkcol_target = svn_path_url_add_component2(
- parent->checkout->resource_url,
+ parent->working_url,
dir->name, dir->pool);
}
@@ -1636,7 +1628,7 @@ add_directory(const char *path,
else
{
apr_uri_t uri;
- const char *rel_copy_path, *basecoll_url, *req_url;
+ const char *req_url;
status = apr_uri_parse(dir->pool, dir->copy_path, &uri);
if (status)
@@ -1646,13 +1638,12 @@ add_directory(const char *path,
dir->copy_path);
}
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &rel_copy_path,
- dir->commit->session,
- dir->commit->conn,
- uri.path, dir->copy_revision,
- NULL, dir_pool));
- req_url = svn_path_url_add_component2(basecoll_url, rel_copy_path,
- dir->pool);
+ /* ### conn==NULL for session->conns[0]. same as commit->conn. */
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ dir->commit->session,
+ NULL /* conn */,
+ uri.path, dir->copy_revision,
+ dir_pool, dir_pool));
handler->method = "COPY";
handler->path = req_url;
@@ -1722,9 +1713,10 @@ open_directory(const char *path,
else
{
SVN_ERR(get_version_url(&dir->url,
- dir->commit->session, dir->commit->conn,
+ dir->commit->session,
dir->relpath, dir->base_revision,
- dir->commit->checked_in_url, dir->pool));
+ dir->commit->checked_in_url,
+ dir->pool, dir->pool /* scratch_pool */));
}
*child_baton = dir;
@@ -1749,9 +1741,9 @@ change_dir_prop(void *dir_baton,
else
{
/* Ensure we have a checked out dir. */
- SVN_ERR(checkout_dir(dir));
+ SVN_ERR(checkout_dir(dir, pool /* scratch_pool */));
- proppatch_target = dir->checkout->resource_url;
+ proppatch_target = dir->working_url;
}
name = apr_pstrdup(dir->pool, name);
@@ -1811,7 +1803,7 @@ close_directory(void *dir_baton,
}
else
{
- proppatch_ctx->path = dir->checkout->resource_url;
+ proppatch_ctx->path = dir->working_url;
}
SVN_ERR(proppatch_resource(proppatch_ctx, dir->commit, dir->pool));
@@ -1859,10 +1851,10 @@ add_file(const char *path,
else
{
/* Ensure our parent directory has been checked out */
- SVN_ERR(checkout_dir(dir));
+ SVN_ERR(checkout_dir(dir, new_file->pool /* scratch_pool */));
new_file->url =
- svn_path_url_add_component2(dir->checkout->resource_url,
+ svn_path_url_add_component2(dir->working_url,
new_file->name, new_file->pool);
}
@@ -1938,9 +1930,9 @@ open_file(const char *path,
else
{
/* CHECKOUT the file into our activity. */
- SVN_ERR(checkout_file(new_file));
+ SVN_ERR(checkout_file(new_file, new_file->pool /* scratch_pool */));
- new_file->url = new_file->checkout->resource_url;
+ new_file->url = new_file->working_url;
}
*file_baton = new_file;
@@ -2026,7 +2018,7 @@ change_file_prop(void *file_baton,
static svn_error_t *
close_file(void *file_baton,
const char *text_checksum,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
file_context_t *ctx = file_baton;
svn_boolean_t put_empty_file = FALSE;
@@ -2038,9 +2030,9 @@ close_file(void *file_baton,
{
svn_ra_serf__handler_t *handler;
apr_uri_t uri;
- const char *rel_copy_path, *basecoll_url, *req_url;
+ const char *req_url;
- status = apr_uri_parse(pool, ctx->copy_path, &uri);
+ status = apr_uri_parse(scratch_pool, ctx->copy_path, &uri);
if (status)
{
return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
@@ -2048,15 +2040,15 @@ close_file(void *file_baton,
ctx->copy_path);
}
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &rel_copy_path,
- ctx->commit->session,
- ctx->commit->conn,
- uri.path, ctx->copy_revision,
- NULL, pool));
- req_url = svn_path_url_add_component2(basecoll_url, rel_copy_path, pool);
+ /* ### conn==NULL for session->conns[0]. same as commit->conn. */
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ ctx->commit->session,
+ NULL /* conn */,
+ uri.path, ctx->copy_revision,
+ scratch_pool, scratch_pool));
- handler = apr_pcalloc(pool, sizeof(*handler));
- handler->handler_pool = pool;
+ handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+ handler->handler_pool = scratch_pool;
handler->method = "COPY";
handler->path = req_url;
handler->conn = ctx->commit->conn;
@@ -2068,7 +2060,7 @@ close_file(void *file_baton,
handler->header_delegate = setup_copy_file_headers;
handler->header_delegate_baton = ctx;
- SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
if (handler->sline.code != 201 && handler->sline.code != 204)
{
@@ -2087,8 +2079,8 @@ close_file(void *file_baton,
{
svn_ra_serf__handler_t *handler;
- handler = apr_pcalloc(pool, sizeof(*handler));
- handler->handler_pool = pool;
+ handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+ handler->handler_pool = scratch_pool;
handler->method = "PUT";
handler->path = ctx->url;
handler->conn = ctx->commit->conn;
@@ -2113,7 +2105,7 @@ close_file(void *file_baton,
handler->header_delegate = setup_put_headers;
handler->header_delegate_baton = ctx;
- SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
if (handler->sline.code != 204 && handler->sline.code != 201)
{
@@ -2122,7 +2114,7 @@ close_file(void *file_baton,
}
if (ctx->svndiff)
- SVN_ERR(svn_io_file_close(ctx->svndiff, pool));
+ SVN_ERR(svn_io_file_close(ctx->svndiff, scratch_pool));
/* If we had any prop changes, push them via PROPPATCH. */
if (apr_hash_count(ctx->changed_props) ||
@@ -2334,8 +2326,8 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
svn_ra_serf__session_t *session = ra_session->priv;
proppatch_context_t *proppatch_ctx;
commit_context_t *commit;
- const char *vcc_url, *proppatch_target, *ns;
- apr_hash_t *props;
+ const char *proppatch_target;
+ const char *ns;
svn_error_t *err;
if (old_value_p)
@@ -2362,21 +2354,15 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
}
else
{
- svn_ra_serf__propfind_context_t *propfind_ctx;
+ const char *vcc_url;
SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, commit->session,
commit->conn, pool));
- props = apr_hash_make(pool);
-
- /* ### switch to svn_ra_serf__retrieve_props */
- SVN_ERR(svn_ra_serf__deliver_props(&propfind_ctx, props, commit->session,
- commit->conn, vcc_url, rev, "0",
- checked_in_props, NULL, pool));
- SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, commit->session, pool));
-
- proppatch_target = svn_ra_serf__get_ver_prop(props, vcc_url, rev,
- "DAV:", "href");
+ SVN_ERR(svn_ra_serf__fetch_dav_prop(&proppatch_target,
+ commit->conn, vcc_url, rev,
+ "href",
+ pool, pool));
}
if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/get_deleted_rev.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/get_deleted_rev.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/get_deleted_rev.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/get_deleted_rev.c Fri May 11 00:05:41 2012
@@ -187,7 +187,7 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
svn_ra_serf__session_t *ras = session->priv;
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_parser_t *parser_ctx;
- const char *relative_url, *basecoll_url, *req_url;
+ const char *req_url;
svn_error_t *err;
drev_ctx = apr_pcalloc(pool, sizeof(*drev_ctx));
@@ -198,11 +198,10 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
drev_ctx->revision_deleted = revision_deleted;
drev_ctx->done = FALSE;
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
- ras, NULL, NULL, peg_revision, NULL,
- pool));
-
- req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ ras, NULL /* conn */,
+ NULL /* url */, peg_revision,
+ pool, pool));
parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
parser_ctx->pool = pool;
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocations.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocations.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocations.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocations.c Fri May 11 00:05:41 2012
@@ -227,7 +227,7 @@ svn_ra_serf__get_locations(svn_ra_sessio
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_parser_t *parser_ctx;
- const char *relative_url, *basecoll_url, *req_url;
+ const char *req_url;
svn_error_t *err;
loc_ctx = apr_pcalloc(pool, sizeof(*loc_ctx));
@@ -240,11 +240,10 @@ svn_ra_serf__get_locations(svn_ra_sessio
*locations = loc_ctx->paths;
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
- NULL, NULL, peg_revision, NULL,
- pool));
-
- req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ NULL /* url */, peg_revision,
+ pool, pool));
handler = apr_pcalloc(pool, sizeof(*handler));
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocationsegments.c?rev=1336974&r1=1336973&r2=1336974&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocationsegments.c Fri May 11 00:05:41 2012
@@ -181,7 +181,7 @@ svn_ra_serf__get_location_segments(svn_r
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_parser_t *parser_ctx;
- const char *relative_url, *basecoll_url, *req_url;
+ const char *req_url;
svn_error_t *err;
gls_ctx = apr_pcalloc(pool, sizeof(*gls_ctx));
@@ -195,10 +195,10 @@ svn_ra_serf__get_location_segments(svn_r
gls_ctx->inside_report = FALSE;
gls_ctx->done = FALSE;
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
- NULL, NULL, peg_revision, NULL, pool));
-
- req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ NULL /* url */, peg_revision,
+ pool, pool));
handler = apr_pcalloc(pool, sizeof(*handler));