summaryrefslogtreecommitdiffstats
path: root/subversion/libsvn_client
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2013-07-28 05:04:41 +0000
committerpeter <peter@FreeBSD.org>2013-07-28 05:04:41 +0000
commit3b9f7e96381479fb03ae2c36d490a38718f71083 (patch)
treea851d66ec0c51a7321b30a677a0e55f1655af4d6 /subversion/libsvn_client
parent6879a90da0ad9b5e74fc212c899751fe3821ac7b (diff)
downloadFreeBSD-src-3b9f7e96381479fb03ae2c36d490a38718f71083.zip
FreeBSD-src-3b9f7e96381479fb03ae2c36d490a38718f71083.tar.gz
Import subversion-1.8.1 into vendor staging area.
Diffstat (limited to 'subversion/libsvn_client')
-rw-r--r--subversion/libsvn_client/client.h64
-rw-r--r--subversion/libsvn_client/commit.c7
-rw-r--r--subversion/libsvn_client/copy.c17
-rw-r--r--subversion/libsvn_client/diff.c57
-rw-r--r--subversion/libsvn_client/diff_local.c12
-rw-r--r--subversion/libsvn_client/log.c45
-rw-r--r--subversion/libsvn_client/merge.c65
-rw-r--r--subversion/libsvn_client/mergeinfo.c102
-rw-r--r--subversion/libsvn_client/ra.c104
-rw-r--r--subversion/libsvn_client/switch.c2
10 files changed, 345 insertions, 130 deletions
diff --git a/subversion/libsvn_client/client.h b/subversion/libsvn_client/client.h
index 9ea25f2..f136888 100644
--- a/subversion/libsvn_client/client.h
+++ b/subversion/libsvn_client/client.h
@@ -20,7 +20,8 @@
* under the License.
* ====================================================================
*/
-
+
+
#ifndef SVN_LIBSVN_CLIENT_H
#define SVN_LIBSVN_CLIENT_H
@@ -208,6 +209,9 @@ svn_client__repos_location_segments(apr_array_header_t **segments,
Use the authentication baton cached in CTX to authenticate against
the repository. Use POOL for all allocations.
+ See also svn_client__calc_youngest_common_ancestor() to find youngest
+ common ancestor for already fetched history-as-mergeinfo information.
+
See also svn_client__youngest_common_ancestor().
*/
svn_error_t *
@@ -219,6 +223,34 @@ svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Find the common ancestor of two locations in a repository using already
+ fetched history-as-mergeinfo information.
+
+ Ancestry is determined by the 'copy-from' relationship and the normal
+ successor relationship.
+
+ Set *ANCESTOR_P to the location of the youngest common ancestor of
+ LOC1 and LOC2. If the locations have no common ancestor (including if
+ they don't have the same repository root URL), set *ANCESTOR_P to NULL.
+
+ HISTORY1, HAS_REV_ZERO_HISTORY1, HISTORY2, HAS_REV_ZERO_HISTORY2 are
+ history-as-mergeinfo information as returned by
+ svn_client__get_history_as_mergeinfo() for LOC1 and LOC2 respectively.
+
+ See also svn_client__get_youngest_common_ancestor().
+
+*/
+svn_error_t *
+svn_client__calc_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+ const svn_client__pathrev_t *loc1,
+ apr_hash_t *history1,
+ svn_boolean_t has_rev_zero_history1,
+ const svn_client__pathrev_t *loc2,
+ apr_hash_t *history2,
+ svn_boolean_t has_rev_zero_history2,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Ensure that RA_SESSION's session URL matches SESSION_URL,
reparenting that session if necessary.
Store the previous session URL in *OLD_SESSION_URL (so that if the
@@ -247,7 +279,8 @@ svn_client__ensure_ra_session_url(const char **old_session_url,
apr_pool_t *pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** RA callbacks ***/
@@ -329,7 +362,8 @@ svn_client__ra_make_cb_baton(svn_wc_context_t *wc_ctx,
apr_pool_t *result_pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** Add/delete ***/
/* If AUTOPROPS is not null: Then read automatic properties matching PATH
@@ -442,7 +476,8 @@ svn_client__make_local_parents(const char *path,
apr_pool_t *pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** Checkout, update and switch ***/
/* Update a working copy LOCAL_ABSPATH to REVISION, and (if not NULL) set
@@ -581,7 +616,8 @@ svn_client__switch_internal(svn_revnum_t *result_rev,
apr_pool_t *pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** Inheritable Properties ***/
/* Convert any svn_prop_inherited_item_t elements in INHERITED_PROPS which
@@ -626,7 +662,8 @@ svn_client__get_inheritable_props(apr_hash_t **wcroot_iprops,
apr_pool_t *scratch_pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** Editor for repository diff ***/
/* Create an editor for a pure repository comparison, i.e. comparing one
@@ -666,7 +703,8 @@ svn_client__get_diff_editor2(const svn_delta_editor_t **editor,
apr_pool_t *result_pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** Editor for diff summary ***/
/* Set *CALLBACKS and *CALLBACK_BATON to a set of diff callbacks that will
@@ -689,7 +727,8 @@ svn_client__get_diff_summarize_callbacks(
apr_pool_t *pool);
/* ---------------------------------------------------------------- */
-
+
+
/*** Copy Stuff ***/
/* This structure is used to associate a specific copy or move SRC with a
@@ -730,7 +769,8 @@ typedef struct svn_client__copy_pair_t
} svn_client__copy_pair_t;
/* ---------------------------------------------------------------- */
-
+
+
/*** Commit Stuff ***/
/* WARNING: This is all new, untested, un-peer-reviewed conceptual
@@ -944,7 +984,8 @@ svn_client__do_commit(const char *base_url,
apr_pool_t *scratch_pool);
-
+
+
/*** Externals (Modules) ***/
/* Handle changes to the svn:externals property described by EXTERNALS_NEW,
@@ -1116,7 +1157,8 @@ svn_client__resolve_conflicts(svn_boolean_t *conflicts_remain,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool);
-
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/subversion/libsvn_client/commit.c b/subversion/libsvn_client/commit.c
index 3f6bfef..6b30885 100644
--- a/subversion/libsvn_client/commit.c
+++ b/subversion/libsvn_client/commit.c
@@ -240,6 +240,13 @@ post_process_commit_item(svn_wc_committed_queue_t *queue,
remove_lock = (! keep_locks && (item->state_flags
& SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN));
+ /* When the node was deleted (or replaced), we need to always remove the
+ locks, as they're invalidated on the server. We cannot honor the
+ SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN flag here because it does not tell
+ us whether we have locked children. */
+ if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+ remove_lock = TRUE;
+
return svn_wc_queue_committed3(queue, wc_ctx, item->path,
loop_recurse, item->incoming_prop_changes,
remove_lock, !keep_changelists,
diff --git a/subversion/libsvn_client/copy.c b/subversion/libsvn_client/copy.c
index c0501b9..000ae0c 100644
--- a/subversion/libsvn_client/copy.c
+++ b/subversion/libsvn_client/copy.c
@@ -385,6 +385,7 @@ static svn_error_t *
verify_wc_dsts(const apr_array_header_t *copy_pairs,
svn_boolean_t make_parents,
svn_boolean_t is_move,
+ svn_boolean_t metadata_only,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -435,8 +436,11 @@ verify_wc_dsts(const apr_array_header_t *copy_pairs,
}
/* Check that there is no unversioned obstruction */
- SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind,
- iterpool));
+ if (metadata_only)
+ dst_kind = svn_node_none;
+ else
+ SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind,
+ iterpool));
if (dst_kind != svn_node_none)
{
@@ -527,6 +531,7 @@ static svn_error_t *
verify_wc_srcs_and_dsts(const apr_array_header_t *copy_pairs,
svn_boolean_t make_parents,
svn_boolean_t is_move,
+ svn_boolean_t metadata_only,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -557,7 +562,7 @@ verify_wc_srcs_and_dsts(const apr_array_header_t *copy_pairs,
scratch_pool));
}
- SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, ctx,
+ SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, metadata_only, ctx,
result_pool, iterpool));
svn_pool_destroy(iterpool);
@@ -1727,8 +1732,8 @@ repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep,
/* We've already checked for physical obstruction by a working file.
But there could also be logical obstruction by an entry whose
working file happens to be missing.*/
- SVN_ERR(verify_wc_dsts(copy_pairs, FALSE, FALSE, ctx,
- scratch_pool, iterpool));
+ SVN_ERR(verify_wc_dsts(copy_pairs, FALSE, FALSE, FALSE /* metadata_only */,
+ ctx, scratch_pool, iterpool));
/* Decide whether the two repositories are the same or not. */
{
@@ -2210,7 +2215,7 @@ try_copy(svn_boolean_t *timestamp_sleep,
if ((! srcs_are_urls) && (! dst_is_url))
{
SVN_ERR(verify_wc_srcs_and_dsts(copy_pairs, make_parents, is_move,
- ctx, pool, pool));
+ metadata_only, ctx, pool, pool));
/* Copy or move all targets. */
if (is_move)
diff --git a/subversion/libsvn_client/diff.c b/subversion/libsvn_client/diff.c
index a5a36bd..26890ae 100644
--- a/subversion/libsvn_client/diff.c
+++ b/subversion/libsvn_client/diff.c
@@ -51,6 +51,7 @@
#include "private/svn_wc_private.h"
#include "private/svn_diff_private.h"
#include "private/svn_subr_private.h"
+#include "private/svn_io_private.h"
#include "svn_private_config.h"
@@ -807,14 +808,23 @@ diff_content_changed(svn_boolean_t *wrote_header,
* ### a non-git compatible diff application.*/
/* We deal in streams, but svn_io_run_diff2() deals in file handles,
- unfortunately, so we need to make these temporary files, and then
- copy the contents to our stream. */
- SVN_ERR(svn_io_open_unique_file3(&outfile, &outfilename, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_io_open_unique_file3(&errfile, &errfilename, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
+ so we may need to make temporary files and then copy the contents
+ to our stream. */
+ outfile = svn_stream__aprfile(outstream);
+ if (outfile)
+ outfilename = NULL;
+ else
+ SVN_ERR(svn_io_open_unique_file3(&outfile, &outfilename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ scratch_pool, scratch_pool));
+
+ errfile = svn_stream__aprfile(errstream);
+ if (errfile)
+ errfilename = NULL;
+ else
+ SVN_ERR(svn_io_open_unique_file3(&errfile, &errfilename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ scratch_pool, scratch_pool));
SVN_ERR(svn_io_run_diff2(".",
diff_cmd_baton->options.for_external.argv,
@@ -824,20 +834,25 @@ diff_content_changed(svn_boolean_t *wrote_header,
&exitcode, outfile, errfile,
diff_cmd_baton->diff_cmd, scratch_pool));
- SVN_ERR(svn_io_file_close(outfile, scratch_pool));
- SVN_ERR(svn_io_file_close(errfile, scratch_pool));
-
/* Now, open and copy our files to our output streams. */
- SVN_ERR(svn_stream_open_readonly(&stream, outfilename,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(outstream,
- scratch_pool),
- NULL, NULL, scratch_pool));
- SVN_ERR(svn_stream_open_readonly(&stream, errfilename,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(errstream,
- scratch_pool),
- NULL, NULL, scratch_pool));
+ if (outfilename)
+ {
+ SVN_ERR(svn_io_file_close(outfile, scratch_pool));
+ SVN_ERR(svn_stream_open_readonly(&stream, outfilename,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(outstream,
+ scratch_pool),
+ NULL, NULL, scratch_pool));
+ }
+ if (errfilename)
+ {
+ SVN_ERR(svn_io_file_close(errfile, scratch_pool));
+ SVN_ERR(svn_stream_open_readonly(&stream, errfilename,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(errstream,
+ scratch_pool),
+ NULL, NULL, scratch_pool));
+ }
/* We have a printed a diff for this path, mark it as visited. */
*wrote_header = TRUE;
diff --git a/subversion/libsvn_client/diff_local.c b/subversion/libsvn_client/diff_local.c
index cc7184f..2dd8a1b 100644
--- a/subversion/libsvn_client/diff_local.c
+++ b/subversion/libsvn_client/diff_local.c
@@ -607,7 +607,10 @@ svn_client__arbitrary_nodes_diff(const char *local_abspath1,
if (kind1 != kind2)
return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
_("'%s' is not the same node kind as '%s'"),
- local_abspath1, local_abspath2);
+ svn_dirent_local_style(local_abspath1,
+ scratch_pool),
+ svn_dirent_local_style(local_abspath2,
+ scratch_pool));
if (depth == svn_depth_unknown)
depth = svn_depth_infinity;
@@ -627,7 +630,10 @@ svn_client__arbitrary_nodes_diff(const char *local_abspath1,
else
return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
_("'%s' is not a file or directory"),
- kind1 == svn_node_none ?
- local_abspath1 : local_abspath2);
+ kind1 == svn_node_none
+ ? svn_dirent_local_style(local_abspath1,
+ scratch_pool)
+ : svn_dirent_local_style(local_abspath2,
+ scratch_pool));
return SVN_NO_ERROR;
}
diff --git a/subversion/libsvn_client/log.c b/subversion/libsvn_client/log.c
index ca3edac..73bd612 100644
--- a/subversion/libsvn_client/log.c
+++ b/subversion/libsvn_client/log.c
@@ -712,7 +712,17 @@ run_ra_get_log(apr_array_header_t *revision_ranges,
matching_segment = bsearch(&younger_rev, log_segments->elts,
log_segments->nelts, log_segments->elt_size,
compare_rev_to_segment);
- SVN_ERR_ASSERT(*matching_segment);
+ /* LOG_SEGMENTS is supposed to represent the history of PATHS from
+ the oldest to youngest revs in REVISION_RANGES. This function's
+ current sole caller svn_client_log5 *should* be providing
+ LOG_SEGMENTS that span the oldest to youngest revs in
+ REVISION_RANGES, even if one or more of the svn_location_segment_t's
+ returned have NULL path members indicating a gap in the history. So
+ MATCHING_SEGMENT should never be NULL, but clearly sometimes it is,
+ see http://svn.haxx.se/dev/archive-2013-06/0522.shtml
+ So to be safe we handle that case. */
+ if (matching_segment == NULL)
+ continue;
/* A segment with a NULL path means there is gap in the history.
We'll just proceed and let svn_ra_get_log2 fail with a useful
@@ -850,13 +860,32 @@ svn_client_log5(const apr_array_header_t *targets,
SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
actual_loc->url, pool));
- /* Get the svn_location_segment_t's representing the requested log ranges. */
- SVN_ERR(svn_client__repos_location_segments(&log_segments, ra_session,
- actual_loc->url,
- actual_loc->rev, /* peg */
- actual_loc->rev, /* start */
- oldest_rev, /* end */
- ctx, pool));
+ /* Save us an RA layer round trip if we are on the repository root and
+ know the result in advance. All the revision data has already been
+ validated.
+ */
+ if (strcmp(actual_loc->url, actual_loc->repos_root_url) == 0)
+ {
+ svn_location_segment_t *segment = apr_pcalloc(pool, sizeof(*segment));
+ log_segments = apr_array_make(pool, 1, sizeof(segment));
+
+ segment->range_start = oldest_rev;
+ segment->range_end = actual_loc->rev;
+ segment->path = "";
+ APR_ARRAY_PUSH(log_segments, svn_location_segment_t *) = segment;
+ }
+ else
+ {
+ /* Get the svn_location_segment_t's representing the requested log
+ * ranges. */
+ SVN_ERR(svn_client__repos_location_segments(&log_segments, ra_session,
+ actual_loc->url,
+ actual_loc->rev, /* peg */
+ actual_loc->rev, /* start */
+ oldest_rev, /* end */
+ ctx, pool));
+ }
+
SVN_ERR(run_ra_get_log(revision_ranges, relative_targets, log_segments,
actual_loc, ra_session, targets, limit,
diff --git a/subversion/libsvn_client/merge.c b/subversion/libsvn_client/merge.c
index 884d63d..17a5d23 100644
--- a/subversion/libsvn_client/merge.c
+++ b/subversion/libsvn_client/merge.c
@@ -1307,6 +1307,9 @@ record_tree_conflict(merge_cmd_baton_t *merge_b,
{
svn_wc_context_t *wc_ctx = merge_b->ctx->wc_ctx;
+ if (merge_b->record_only)
+ return SVN_NO_ERROR;
+
if (merge_b->merge_source.ancestral
|| merge_b->reintegrate_merge)
{
@@ -1316,8 +1319,7 @@ record_tree_conflict(merge_cmd_baton_t *merge_b,
alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
merge_b->pool);
-
- if (!merge_b->record_only && !merge_b->dry_run)
+ if (!merge_b->dry_run)
{
svn_wc_conflict_description2_t *conflict;
const svn_wc_conflict_version_t *left;
@@ -12029,16 +12031,17 @@ operative_rev_receiver(void *baton,
return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
}
-/* Wrapper around svn_client_mergeinfo_log2. All arguments are as per
- that API. The discover_changed_paths, depth, and revprops args to
- svn_client_mergeinfo_log2 are always TRUE, svn_depth_infinity_t,
- and NULL respectively.
+/* Wrapper around svn_client__mergeinfo_log. All arguments are as per
+ that private API. The discover_changed_paths, depth, and revprops args to
+ svn_client__mergeinfo_log are always TRUE, svn_depth_infinity_t,
+ and empty array respectively.
If RECEIVER raises a SVN_ERR_CEASE_INVOCATION error, but still sets
*REVISION to a valid revnum, then clear the error. Otherwise return
any error. */
static svn_error_t*
-short_circuit_mergeinfo_log(svn_boolean_t finding_merged,
+short_circuit_mergeinfo_log(svn_mergeinfo_catalog_t *target_mergeinfo_cat,
+ svn_boolean_t finding_merged,
const char *target_path_or_url,
const svn_opt_revision_t *target_peg_revision,
const char *source_path_or_url,
@@ -12048,18 +12051,25 @@ short_circuit_mergeinfo_log(svn_boolean_t finding_merged,
svn_log_entry_receiver_t receiver,
svn_revnum_t *revision,
svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_error_t *err = svn_client_mergeinfo_log2(finding_merged,
- target_path_or_url,
- target_peg_revision,
- source_path_or_url,
- source_peg_revision,
- source_start_revision,
- source_end_revision,
- receiver, revision,
- TRUE, svn_depth_infinity,
- NULL, ctx, scratch_pool);
+ apr_array_header_t *revprops;
+ svn_error_t *err;
+
+ revprops = apr_array_make(scratch_pool, 0, sizeof(const char *));
+ err = svn_client__mergeinfo_log(finding_merged,
+ target_path_or_url,
+ target_peg_revision,
+ target_mergeinfo_cat,
+ source_path_or_url,
+ source_peg_revision,
+ source_start_revision,
+ source_end_revision,
+ receiver, revision,
+ TRUE, svn_depth_infinity,
+ revprops, ctx, result_pool,
+ scratch_pool);
if (err)
{
@@ -12129,6 +12139,7 @@ find_last_merged_location(svn_client__pathrev_t **base_p,
svn_opt_revision_t source_peg_rev, source_start_rev, source_end_rev,
target_opt_rev;
svn_revnum_t youngest_merged_rev = SVN_INVALID_REVNUM;
+ svn_mergeinfo_catalog_t target_mergeinfo_cat = NULL;
source_peg_rev.kind = svn_opt_revision_number;
source_peg_rev.value.number = source_branch->tip->rev;
@@ -12141,14 +12152,15 @@ find_last_merged_location(svn_client__pathrev_t **base_p,
/* Find the youngest revision fully merged from SOURCE_BRANCH to TARGET,
if such a revision exists. */
- SVN_ERR(short_circuit_mergeinfo_log(TRUE, /* Find merged */
+ SVN_ERR(short_circuit_mergeinfo_log(&target_mergeinfo_cat,
+ TRUE, /* Find merged */
target->url, &target_opt_rev,
source_branch->tip->url,
&source_peg_rev,
&source_end_rev, &source_start_rev,
operative_rev_receiver,
&youngest_merged_rev,
- ctx, scratch_pool));
+ ctx, result_pool, scratch_pool));
if (!SVN_IS_VALID_REVNUM(youngest_merged_rev))
{
@@ -12175,14 +12187,15 @@ find_last_merged_location(svn_client__pathrev_t **base_p,
(i.e. finding the youngest revision after the YCA where all revs have
been merged) that doesn't matter. */
source_end_rev.value.number = youngest_merged_rev;
- SVN_ERR(short_circuit_mergeinfo_log(FALSE, /* Find eligible */
+ SVN_ERR(short_circuit_mergeinfo_log(&target_mergeinfo_cat,
+ FALSE, /* Find eligible */
target->url, &target_opt_rev,
source_branch->tip->url,
&source_peg_rev,
&source_start_rev, &source_end_rev,
operative_rev_receiver,
&oldest_eligible_rev,
- ctx, scratch_pool));
+ ctx, scratch_pool, scratch_pool));
/* If there are revisions eligible for merging, use the oldest one
to calculate the base. Otherwise there are no operative revisions
@@ -12298,9 +12311,13 @@ find_automatic_merge(svn_client__pathrev_t **base_p,
&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(
- &s_t->yca, s_t->source, &s_t->target->loc, s_t->source_ra_session,
- ctx, result_pool, result_pool));
+ SVN_ERR(svn_client__calc_youngest_common_ancestor(
+ &s_t->yca, s_t->source, s_t->source_branch.history,
+ s_t->source_branch.has_r0_history,
+ &s_t->target->loc, s_t->target_branch.history,
+ s_t->target_branch.has_r0_history,
+ result_pool, scratch_pool));
+
if (! s_t->yca)
return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
_("'%s@%ld' must be ancestrally related to "
diff --git a/subversion/libsvn_client/mergeinfo.c b/subversion/libsvn_client/mergeinfo.c
index 453cc66..6dd3434 100644
--- a/subversion/libsvn_client/mergeinfo.c
+++ b/subversion/libsvn_client/mergeinfo.c
@@ -1651,11 +1651,11 @@ svn_client_mergeinfo_get_merged(apr_hash_t **mergeinfo_p,
return SVN_NO_ERROR;
}
-
svn_error_t *
-svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
+svn_client__mergeinfo_log(svn_boolean_t finding_merged,
const char *target_path_or_url,
const svn_opt_revision_t *target_peg_revision,
+ svn_mergeinfo_catalog_t *target_mergeinfo_catalog,
const char *source_path_or_url,
const svn_opt_revision_t *source_peg_revision,
const svn_opt_revision_t *source_start_revision,
@@ -1666,12 +1666,15 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
svn_depth_t depth,
const apr_array_header_t *revprops,
svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *log_target = NULL;
const char *repos_root;
const char *target_repos_relpath;
svn_mergeinfo_catalog_t target_mergeinfo_cat;
+ svn_ra_session_t *target_session = NULL;
+ svn_client__pathrev_t *pathrev;
/* A hash of paths, at or under TARGET_PATH_OR_URL, mapped to
rangelists. Not technically mergeinfo, so not using the
@@ -1688,6 +1691,7 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
apr_hash_index_t *hi;
apr_pool_t *iterpool;
svn_boolean_t oldest_revs_first = TRUE;
+ apr_pool_t *subpool;
/* We currently only support depth = empty | infinity. */
if (depth != svn_depth_infinity && depth != svn_depth_empty)
@@ -1713,6 +1717,8 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
&& (source_start_revision->kind != svn_opt_revision_unspecified))
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
+ subpool = svn_pool_create(scratch_pool);
+
/* We need the union of TARGET_PATH_OR_URL@TARGET_PEG_REVISION's mergeinfo
and MERGE_SOURCE_URL's history. It's not enough to do path
matching, because renames in the history of MERGE_SOURCE_URL
@@ -1720,10 +1726,45 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
the target, that vastly simplifies matters (we'll have nothing to
do). */
/* This get_mergeinfo() call doubles as a mergeinfo capabilities check. */
- SVN_ERR(get_mergeinfo(&target_mergeinfo_cat, &repos_root,
- target_path_or_url, target_peg_revision,
- depth == svn_depth_infinity, TRUE,
- ctx, scratch_pool, scratch_pool));
+ if (target_mergeinfo_catalog)
+ {
+ if (*target_mergeinfo_catalog)
+ {
+ /* The caller provided the mergeinfo catalog for
+ TARGET_PATH_OR_URL, so we don't need to accquire
+ it ourselves. We do need to get the repos_root
+ though, because get_mergeinfo() won't do it for us. */
+ target_mergeinfo_cat = *target_mergeinfo_catalog;
+ SVN_ERR(svn_client__ra_session_from_path2(&target_session, &pathrev,
+ target_path_or_url, NULL,
+ target_peg_revision,
+ target_peg_revision,
+ ctx, subpool));
+ SVN_ERR(svn_ra_get_repos_root2(target_session, &repos_root,
+ scratch_pool));
+ }
+ else
+ {
+ /* The caller didn't provide the mergeinfo catalog for
+ TARGET_PATH_OR_URL, but wants us to pass a copy back
+ when we get it, so use RESULT_POOL. */
+ SVN_ERR(get_mergeinfo(target_mergeinfo_catalog, &repos_root,
+ target_path_or_url, target_peg_revision,
+ depth == svn_depth_infinity, TRUE,
+ ctx, result_pool, scratch_pool));
+ target_mergeinfo_cat = *target_mergeinfo_catalog;
+ }
+ }
+ else
+ {
+ /* The caller didn't provide the mergeinfo catalog for
+ TARGET_PATH_OR_URL, nor does it want a copy, so we can use
+ nothing but SCRATCH_POOL. */
+ SVN_ERR(get_mergeinfo(&target_mergeinfo_cat, &repos_root,
+ target_path_or_url, target_peg_revision,
+ depth == svn_depth_infinity, TRUE,
+ ctx, scratch_pool, scratch_pool));
+ }
if (!svn_path_is_url(target_path_or_url))
{
@@ -1755,6 +1796,7 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
history. */
if (finding_merged)
{
+ svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
else
@@ -1772,18 +1814,17 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
* ### TODO: As the source and target must be in the same repository, we
* should share a single session, tracking the two URLs separately. */
{
- apr_pool_t *sesspool = svn_pool_create(scratch_pool);
- svn_ra_session_t *source_session, *target_session;
- svn_client__pathrev_t *pathrev;
+ svn_ra_session_t *source_session;
svn_revnum_t start_rev, end_rev, youngest_rev = SVN_INVALID_REVNUM;
if (! finding_merged)
{
- SVN_ERR(svn_client__ra_session_from_path2(&target_session, &pathrev,
- target_path_or_url, NULL,
- target_peg_revision,
- target_peg_revision,
- ctx, sesspool));
+ if (!target_session)
+ SVN_ERR(svn_client__ra_session_from_path2(&target_session, &pathrev,
+ target_path_or_url, NULL,
+ target_peg_revision,
+ target_peg_revision,
+ ctx, subpool));
SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history, NULL,
pathrev,
SVN_INVALID_REVNUM,
@@ -1796,17 +1837,17 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
source_path_or_url, NULL,
source_peg_revision,
source_peg_revision,
- ctx, sesspool));
+ ctx, subpool));
SVN_ERR(svn_client__get_revision_number(&start_rev, &youngest_rev,
ctx->wc_ctx, source_path_or_url,
source_session,
source_start_revision,
- sesspool));
+ subpool));
SVN_ERR(svn_client__get_revision_number(&end_rev, &youngest_rev,
ctx->wc_ctx, source_path_or_url,
source_session,
source_end_revision,
- sesspool));
+ subpool));
SVN_ERR(svn_client__get_history_as_mergeinfo(&source_history, NULL,
pathrev,
MAX(end_rev, start_rev),
@@ -1817,7 +1858,7 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
oldest_revs_first = FALSE;
/* Close the source and target sessions. */
- svn_pool_destroy(sesspool);
+ svn_pool_destroy(subpool);
}
/* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL,
@@ -2090,6 +2131,31 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
}
svn_error_t *
+svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
+ const char *target_path_or_url,
+ const svn_opt_revision_t *target_peg_revision,
+ const char *source_path_or_url,
+ const svn_opt_revision_t *source_peg_revision,
+ const svn_opt_revision_t *source_start_revision,
+ const svn_opt_revision_t *source_end_revision,
+ svn_log_entry_receiver_t log_receiver,
+ void *log_receiver_baton,
+ svn_boolean_t discover_changed_paths,
+ svn_depth_t depth,
+ const apr_array_header_t *revprops,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ return svn_client__mergeinfo_log(finding_merged, target_path_or_url,
+ target_peg_revision, NULL,
+ source_path_or_url, source_peg_revision,
+ source_start_revision, source_end_revision,
+ log_receiver, log_receiver_baton,
+ discover_changed_paths, depth, revprops,
+ ctx, scratch_pool, scratch_pool);
+}
+
+svn_error_t *
svn_client_suggest_merge_sources(apr_array_header_t **suggestions,
const char *path_or_url,
const svn_opt_revision_t *peg_revision,
diff --git a/subversion/libsvn_client/ra.c b/subversion/libsvn_client/ra.c
index 33d3de5..a0d4cea 100644
--- a/subversion/libsvn_client/ra.c
+++ b/subversion/libsvn_client/ra.c
@@ -862,23 +862,20 @@ svn_client__repos_locations(const char **start_url,
return SVN_NO_ERROR;
}
-
svn_error_t *
-svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
- const svn_client__pathrev_t *loc1,
- const svn_client__pathrev_t *loc2,
- svn_ra_session_t *session,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_client__calc_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+ const svn_client__pathrev_t *loc1,
+ apr_hash_t *history1,
+ svn_boolean_t has_rev_zero_history1,
+ const svn_client__pathrev_t *loc2,
+ apr_hash_t *history2,
+ svn_boolean_t has_rev_zero_history2,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_pool_t *sesspool = NULL;
- apr_hash_t *history1, *history2;
apr_hash_index_t *hi;
svn_revnum_t yc_revision = SVN_INVALID_REVNUM;
const char *yc_relpath = NULL;
- svn_boolean_t has_rev_zero_history1;
- svn_boolean_t has_rev_zero_history2;
if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0)
{
@@ -886,32 +883,6 @@ svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
return SVN_NO_ERROR;
}
- /* Open an RA session for the two locations. */
- if (session == NULL)
- {
- sesspool = svn_pool_create(scratch_pool);
- SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx,
- sesspool, sesspool));
- }
-
- /* We're going to cheat and use history-as-mergeinfo because it
- saves us a bunch of annoying custom data comparisons and such. */
- SVN_ERR(svn_client__get_history_as_mergeinfo(&history1,
- &has_rev_zero_history1,
- loc1,
- SVN_INVALID_REVNUM,
- SVN_INVALID_REVNUM,
- session, ctx, scratch_pool));
- SVN_ERR(svn_client__get_history_as_mergeinfo(&history2,
- &has_rev_zero_history2,
- loc2,
- SVN_INVALID_REVNUM,
- SVN_INVALID_REVNUM,
- session, ctx, scratch_pool));
- /* Close the ra session if we opened one. */
- if (sesspool)
- svn_pool_destroy(sesspool);
-
/* Loop through the first location's history, check for overlapping
paths and ranges in the second location's history, and
remembering the youngest matching location. */
@@ -965,6 +936,63 @@ svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
}
svn_error_t *
+svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+ const svn_client__pathrev_t *loc1,
+ const svn_client__pathrev_t *loc2,
+ svn_ra_session_t *session,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *sesspool = NULL;
+ apr_hash_t *history1, *history2;
+ svn_boolean_t has_rev_zero_history1;
+ svn_boolean_t has_rev_zero_history2;
+
+ if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0)
+ {
+ *ancestor_p = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ /* Open an RA session for the two locations. */
+ if (session == NULL)
+ {
+ sesspool = svn_pool_create(scratch_pool);
+ SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx,
+ sesspool, sesspool));
+ }
+
+ /* We're going to cheat and use history-as-mergeinfo because it
+ saves us a bunch of annoying custom data comparisons and such. */
+ SVN_ERR(svn_client__get_history_as_mergeinfo(&history1,
+ &has_rev_zero_history1,
+ loc1,
+ SVN_INVALID_REVNUM,
+ SVN_INVALID_REVNUM,
+ session, ctx, scratch_pool));
+ SVN_ERR(svn_client__get_history_as_mergeinfo(&history2,
+ &has_rev_zero_history2,
+ loc2,
+ SVN_INVALID_REVNUM,
+ SVN_INVALID_REVNUM,
+ session, ctx, scratch_pool));
+ /* Close the ra session if we opened one. */
+ if (sesspool)
+ svn_pool_destroy(sesspool);
+
+ SVN_ERR(svn_client__calc_youngest_common_ancestor(ancestor_p,
+ loc1, history1,
+ has_rev_zero_history1,
+ loc2, history2,
+ has_rev_zero_history2,
+ result_pool,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_client__youngest_common_ancestor(const char **ancestor_url,
svn_revnum_t *ancestor_rev,
const char *path_or_url1,
diff --git a/subversion/libsvn_client/switch.c b/subversion/libsvn_client/switch.c
index fae03de..cd39cad 100644
--- a/subversion/libsvn_client/switch.c
+++ b/subversion/libsvn_client/switch.c
@@ -241,7 +241,7 @@ switch_internal(svn_revnum_t *result_rev,
return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
_("'%s' shares no common ancestry with '%s'"),
switch_url,
- svn_dirent_dirname(local_abspath, pool));
+ svn_dirent_local_style(local_abspath, pool));
}
wcroot_iprops = apr_hash_make(pool);
OpenPOWER on IntegriCloud