You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/05/07 15:26:27 UTC
svn commit: r1479901 [2/7] - in /subversion/branches/wc-collate-path: ./
build/ac-macros/ build/generator/ build/generator/templates/
contrib/server-side/fsfsfixer/ contrib/server-side/fsfsfixer/fixer/
subversion/bindings/ctypes-python/ subversion/bind...
Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/log.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/log.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/log.c Tue May 7 13:26:25 2013
@@ -42,6 +42,7 @@
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
+#include <assert.h>
/*** Getting misc. information ***/
@@ -260,59 +261,223 @@ limit_receiver(void *baton, svn_log_entr
return rb->receiver(rb->baton, log_entry, pool);
}
-
-/*** Public Interface. ***/
+/* Resolve the URLs or WC path in TARGETS as per the svn_client_log5 API.
+ The limitations on TARGETS specified by svn_client_log5 are enforced here.
+ So TARGETS can only contain a single WC path or a URL and zero or more
+ relative paths -- anything else will raise an error.
-svn_error_t *
-svn_client_log5(const apr_array_header_t *targets,
- const svn_opt_revision_t *peg_revision,
- const apr_array_header_t *revision_ranges,
- int limit,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_boolean_t include_merged_revisions,
- const apr_array_header_t *revprops,
- svn_log_entry_receiver_t real_receiver,
- void *real_receiver_baton,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+ PEG_REVISION, TARGETS, and CTX are as per svn_client_log5.
+
+ If TARGETS contains a single WC path then set *RA_TARGET to the absolute
+ path of that single path if PEG_REVISION is dependent on the working copy
+ (e.g. PREV). Otherwise set *RA_TARGET to the corresponding URL for the
+ single WC path. Set *RELATIVE_TARGETS to an array with a single
+ element "".
+
+ If TARGETS contains only a single URL, then set *RA_TARGET to a copy of
+ that URL and *RELATIVE_TARGETS to an array with a single element "".
+
+ If TARGETS contains a single URL and one or more relative paths, then
+ set *RA_TARGET to a copy of that URL and *CONDENSED_PATHS to a copy of
+ each relative path after the URL.
+
+ If *PEG_REVISION is svn_opt_revision_unspecified, then *PEG_REVISION is
+ set to svn_opt_revision_head for URLs or svn_opt_revision_working for a
+ WC path.
+
+ *RA_TARGET and *RELATIVE_TARGETS are allocated in RESULT_POOL. */
+static svn_error_t *
+resolve_log_targets(apr_array_header_t **relative_targets,
+ const char **ra_target,
+ svn_opt_revision_t *peg_revision,
+ const apr_array_header_t *targets,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- svn_ra_session_t *ra_session;
- const char *url_or_path;
- svn_boolean_t has_log_revprops;
- apr_array_header_t *condensed_targets;
- svn_opt_revision_t session_opt_rev;
- const char *ra_target;
- pre_15_receiver_baton_t rb = {0};
- apr_pool_t *iterpool;
int i;
- svn_opt_revision_t peg_rev;
- svn_boolean_t url_targets = FALSE;
- svn_opt_revision_t resolved_peg_rev;
- const char *resolved_target;
+ svn_boolean_t url_targets;
+
+ /* Per svn_client_log5, TARGETS contains either a URL followed by zero or
+ more relative paths, or one working copy path. */
+ const char *url_or_path = APR_ARRAY_IDX(targets, 0, const char *);
+
+ /* svn_client_log5 requires at least one target. */
+ if (targets->nelts == 0)
+ return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("No valid target found"));
- if (revision_ranges->nelts == 0)
+ /* Initialize the output array. */
+ *relative_targets = apr_array_make(result_pool, 1, sizeof(const char *));
+
+ if (svn_path_is_url(url_or_path))
{
- return svn_error_create
- (SVN_ERR_CLIENT_BAD_REVISION, NULL,
- _("Missing required revision specification"));
+ /* An unspecified PEG_REVISION for a URL path defaults
+ to svn_opt_revision_head. */
+ if (peg_revision->kind == svn_opt_revision_unspecified)
+ (*peg_revision).kind = svn_opt_revision_head;
+
+ /* The logic here is this: If we get passed one argument, we assume
+ it is the full URL to a file/dir we want log info for. If we get
+ a URL plus some paths, then we assume that the URL is the base,
+ and that the paths passed are relative to it. */
+ if (targets->nelts > 1)
+ {
+ /* We have some paths, let's use them. Start after the URL. */
+ for (i = 1; i < targets->nelts; i++)
+ {
+ const char *target;
+
+ target = APR_ARRAY_IDX(targets, i, const char *);
+
+ if (svn_path_is_url(target) || svn_dirent_is_absolute(target))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a relative path"),
+ target);
+
+ APR_ARRAY_PUSH(*relative_targets, const char *) =
+ apr_pstrdup(result_pool, target);
+ }
+ }
+ else
+ {
+ /* If we have a single URL, then the session will be rooted at
+ it, so just send an empty string for the paths we are
+ interested in. */
+ APR_ARRAY_PUSH(*relative_targets, const char *) = "";
+ }
+
+ /* Remember that our targets are URLs. */
+ url_targets = TRUE;
}
+ else /* WC path target. */
+ {
+ const char *target;
+ const char *target_abspath;
- /* Make a copy of PEG_REVISION, we may need to change it to a
- default value. */
- peg_rev = *peg_revision;
+ url_targets = FALSE;
+ if (targets->nelts > 1)
+ return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("When specifying working copy paths, only "
+ "one target may be given"));
- /* Use the passed URL, if there is one. */
- url_or_path = APR_ARRAY_IDX(targets, 0, const char *);
- session_opt_rev.kind = svn_opt_revision_unspecified;
+ /* An unspecified PEG_REVISION for a working copy path defaults
+ to svn_opt_revision_working. */
+ if (peg_revision->kind == svn_opt_revision_unspecified)
+ (*peg_revision).kind = svn_opt_revision_working;
- for (i = 0; i < revision_ranges->nelts; i++)
+ /* Get URLs for each target */
+ target = APR_ARRAY_IDX(targets, 0, const char *);
+
+ SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, scratch_pool));
+ SVN_ERR(svn_wc__node_get_url(&url_or_path, ctx->wc_ctx, target_abspath,
+ scratch_pool, scratch_pool));
+ APR_ARRAY_PUSH(*relative_targets, const char *) = "";
+ }
+
+ /* If this is a revision type that requires access to the working copy,
+ * we use our initial target path to figure out where to root the RA
+ * session, otherwise we use our URL. */
+ if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+ {
+ if (url_targets)
+ return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
+ _("PREV, BASE, or COMMITTED revision "
+ "keywords are invalid for URL"));
+
+ else
+ SVN_ERR(svn_dirent_get_absolute(
+ ra_target, APR_ARRAY_IDX(targets, 0, const char *), result_pool));
+ }
+ else
+ {
+ *ra_target = apr_pstrdup(result_pool, url_or_path);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Keep track of oldest and youngest opt revs found.
+
+ If REV is younger than *YOUNGEST_REV, or *YOUNGEST_REV is
+ svn_opt_revision_unspecified, then set *YOUNGEST_REV equal to REV.
+
+ If REV is older than *OLDEST_REV, or *OLDEST_REV is
+ svn_opt_revision_unspecified, then set *OLDEST_REV equal to REV. */
+static void
+find_youngest_and_oldest_revs(svn_revnum_t *youngest_rev,
+ svn_revnum_t *oldest_rev,
+ svn_revnum_t rev)
+{
+ /* Is REV younger than YOUNGEST_REV? */
+ if (! SVN_IS_VALID_REVNUM(*youngest_rev)
+ || rev > *youngest_rev)
+ *youngest_rev = rev;
+
+ if (! SVN_IS_VALID_REVNUM(*oldest_rev)
+ || rev < *oldest_rev)
+ *oldest_rev = rev;
+
+ return;
+}
+
+typedef struct rev_range_t
+{
+ svn_revnum_t range_start;
+ svn_revnum_t range_end;
+} rev_range_t;
+
+/* Convert array of svn_opt_revision_t ranges to an array of svn_revnum_t
+ ranges.
+
+ Given a log target URL_OR_ABSPATH@PEG_REV and an array of
+ svn_opt_revision_range_t's OPT_REV_RANGES, resolve the opt revs in
+ OPT_REV_RANGES to svn_revnum_t's and return these in *REVISION_RANGES, an
+ array of rev_range_t *.
+
+ Set *YOUNGEST_REV and *OLDEST_REV to the youngest and oldest revisions
+ found in *REVISION_RANGES.
+
+ If the repository needs to be contacted to resolve svn_opt_revision_date or
+ svn_opt_revision_head revisions, then the session used to do this is
+ RA_SESSION; it must be an open session to any URL in the right repository.
+*/
+static svn_error_t*
+convert_opt_rev_array_to_rev_range_array(
+ apr_array_header_t **revision_ranges,
+ svn_revnum_t *youngest_rev,
+ svn_revnum_t *oldest_rev,
+ svn_ra_session_t *ra_session,
+ const char *url_or_abspath,
+ const apr_array_header_t *opt_rev_ranges,
+ const svn_opt_revision_t *peg_rev,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+ svn_revnum_t head_rev = SVN_INVALID_REVNUM;
+
+ /* Initialize the input/output parameters. */
+ *youngest_rev = *oldest_rev = SVN_INVALID_REVNUM;
+
+ /* Convert OPT_REV_RANGES to an array of rev_range_t and find the youngest
+ and oldest revision range that spans all of OPT_REV_RANGES. */
+ *revision_ranges = apr_array_make(result_pool, opt_rev_ranges->nelts,
+ sizeof(rev_range_t *));
+
+ for (i = 0; i < opt_rev_ranges->nelts; i++)
{
svn_opt_revision_range_t *range;
+ rev_range_t *rev_range;
+ svn_boolean_t start_same_as_end = FALSE;
- range = APR_ARRAY_IDX(revision_ranges, i, svn_opt_revision_range_t *);
+ range = APR_ARRAY_IDX(opt_rev_ranges, i, svn_opt_revision_range_t *);
+ /* Right now RANGE can be any valid pair of svn_opt_revision_t's. We
+ will now convert all RANGEs in place to the corresponding
+ svn_opt_revision_number kind. */
if ((range->start.kind != svn_opt_revision_unspecified)
&& (range->end.kind == svn_opt_revision_unspecified))
{
@@ -331,15 +496,15 @@ svn_client_log5(const apr_array_header_t
/* Default to any specified peg revision. Otherwise, if the
* first target is a URL, then we default to HEAD:0. Lastly,
* the default is BASE:0 since WC@HEAD may not exist. */
- if (peg_rev.kind == svn_opt_revision_unspecified)
+ if (peg_rev->kind == svn_opt_revision_unspecified)
{
- if (svn_path_is_url(url_or_path))
+ if (svn_path_is_url(url_or_abspath))
range->start.kind = svn_opt_revision_head;
else
range->start.kind = svn_opt_revision_base;
}
else
- range->start = peg_rev;
+ range->start = *peg_rev;
if (range->end.kind == svn_opt_revision_unspecified)
{
@@ -356,179 +521,102 @@ svn_client_log5(const apr_array_header_t
_("Missing required revision specification"));
}
- /* Determine the revision to open the RA session to. */
- if (session_opt_rev.kind == svn_opt_revision_unspecified)
- {
- if (range->start.kind == svn_opt_revision_number &&
- range->end.kind == svn_opt_revision_number)
- {
- session_opt_rev =
- (range->start.value.number > range->end.value.number ?
- range->start : range->end);
- }
- else if (range->start.kind == svn_opt_revision_head ||
- range->end.kind == svn_opt_revision_head)
- {
- session_opt_rev.kind = svn_opt_revision_head;
- }
- else if (range->start.kind == svn_opt_revision_date &&
- range->end.kind == svn_opt_revision_date)
- {
- session_opt_rev =
- (range->start.value.date > range->end.value.date ?
- range->start : range->end);
- }
- }
- }
-
- /* Use the passed URL, if there is one. */
- if (svn_path_is_url(url_or_path))
- {
- /* Initialize this array, since we'll be building it below */
- condensed_targets = apr_array_make(pool, 1, sizeof(const char *));
-
- /* The logic here is this: If we get passed one argument, we assume
- it is the full URL to a file/dir we want log info for. If we get
- a URL plus some paths, then we assume that the URL is the base,
- and that the paths passed are relative to it. */
- if (targets->nelts > 1)
- {
- /* We have some paths, let's use them. Start after the URL. */
- for (i = 1; i < targets->nelts; i++)
- {
- const char *target;
-
- target = APR_ARRAY_IDX(targets, i, const char *);
-
- if (svn_path_is_url(target) || svn_dirent_is_absolute(target))
- return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
- _("'%s' is not a relative path"),
- target);
-
- APR_ARRAY_PUSH(condensed_targets, const char *) = target;
- }
- }
+ if (memcmp(&(range->start), &(range->end),
+ sizeof(svn_opt_revision_t)) == 0)
+ start_same_as_end = TRUE;
+
+ rev_range = apr_palloc(result_pool, sizeof(*rev_range));
+ SVN_ERR(svn_client__get_revision_number(
+ &rev_range->range_start, &head_rev,
+ ctx->wc_ctx, url_or_abspath, ra_session,
+ &range->start, scratch_pool));
+ if (start_same_as_end)
+ rev_range->range_end = rev_range->range_start;
else
- {
- /* If we have a single URL, then the session will be rooted at
- it, so just send an empty string for the paths we are
- interested in. */
- APR_ARRAY_PUSH(condensed_targets, const char *) = "";
- }
-
- /* Remember that our targets are URLs. */
- url_targets = TRUE;
+ SVN_ERR(svn_client__get_revision_number(
+ &rev_range->range_end, &head_rev,
+ ctx->wc_ctx, url_or_abspath, ra_session,
+ &range->end, scratch_pool));
+
+ /* Possibly update the oldest and youngest revisions requested. */
+ find_youngest_and_oldest_revs(youngest_rev,
+ oldest_rev,
+ rev_range->range_start);
+ find_youngest_and_oldest_revs(youngest_rev,
+ oldest_rev,
+ rev_range->range_end);
+ APR_ARRAY_PUSH(*revision_ranges, rev_range_t *) = rev_range;
}
- else
- {
- apr_array_header_t *target_urls;
- apr_array_header_t *real_targets;
- /* See FIXME about multiple wc targets, below. */
- if (targets->nelts > 1)
- return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("When specifying working copy paths, only "
- "one target may be given"));
+ return SVN_NO_ERROR;
+}
- /* An unspecified PEG_REVISION for a working copy path defaults
- to svn_opt_revision_working. */
- if (peg_rev.kind == svn_opt_revision_unspecified)
- peg_rev.kind = svn_opt_revision_working;
+static int
+compare_rev_to_segment(const void *key_p,
+ const void *element_p)
+{
+ svn_revnum_t rev =
+ * (svn_revnum_t *)key_p;
+ const svn_location_segment_t *segment =
+ *((const svn_location_segment_t * const *) element_p);
+
+ if (rev < segment->range_start)
+ return -1;
+ else if (rev > segment->range_end)
+ return 1;
+ else
+ return 0;
+}
- /* Get URLs for each target */
- target_urls = apr_array_make(pool, 1, sizeof(const char *));
- real_targets = apr_array_make(pool, 1, sizeof(const char *));
- iterpool = svn_pool_create(pool);
- for (i = 0; i < targets->nelts; i++)
- {
- const char *url;
- const char *target = APR_ARRAY_IDX(targets, i, const char *);
- const char *target_abspath;
-
- svn_pool_clear(iterpool);
- SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, iterpool));
- SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, target_abspath,
- pool, iterpool));
-
- if (! url)
- return svn_error_createf
- (SVN_ERR_ENTRY_MISSING_URL, NULL,
- _("Entry '%s' has no URL"),
- svn_dirent_local_style(target, pool));
-
- APR_ARRAY_PUSH(target_urls, const char *) = url;
- APR_ARRAY_PUSH(real_targets, const char *) = target;
- }
-
- /* if we have no valid target_urls, just exit. */
- if (target_urls->nelts == 0)
- return SVN_NO_ERROR;
-
- /* Find the base URL and condensed targets relative to it. */
- SVN_ERR(svn_uri_condense_targets(&url_or_path, &condensed_targets,
- target_urls, TRUE, pool, iterpool));
-
- if (condensed_targets->nelts == 0)
- APR_ARRAY_PUSH(condensed_targets, const char *) = "";
-
- /* 'targets' now becomes 'real_targets', which has bogus,
- unversioned things removed from it. */
- targets = real_targets;
- svn_pool_destroy(iterpool);
- }
-
-
- {
- svn_client__pathrev_t *actual_loc;
-
- /* If this is a revision type that requires access to the working copy,
- * we use our initial target path to figure out where to root the RA
- * session, otherwise we use our URL. */
- if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_rev.kind))
- {
- if (url_targets)
- SVN_ERR(svn_uri_condense_targets(&ra_target, NULL, targets,
- TRUE, pool, pool));
- else
- SVN_ERR(svn_dirent_condense_targets(&ra_target, NULL, targets,
- TRUE, pool, pool));
- }
- else
- ra_target = url_or_path;
-
- SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
- ra_target, NULL,
- &peg_rev, &session_opt_rev,
- ctx, pool));
-
- if (svn_path_is_url(ra_target))
- {
- resolved_target = ra_target;
- resolved_peg_rev = peg_rev;
- }
- else
- {
- svn_client__pathrev_t *resolved_target_pathrev;
-
- SVN_ERR(svn_client__wc_node_get_origin(&resolved_target_pathrev,
- ra_target, ctx, pool, pool));
- resolved_target = resolved_target_pathrev->url;
- resolved_peg_rev.kind = svn_opt_revision_number;
- resolved_peg_rev.value.number = resolved_target_pathrev->rev;
- }
+/* Run svn_ra_get_log2 for PATHS, one or more paths relative to RA_SESSION's
+ common parent, for each revision in REVISION_RANGES, an array of
+ rev_range_t.
+
+ RA_SESSION is an open session pointing to ACTUAL_LOC.
+
+ LOG_SEGMENTS is an array of svn_location_segment_t * items representing the
+ history of PATHS from the oldest to youngest revisions found in
+ REVISION_RANGES.
+
+ The TARGETS, LIMIT, DISCOVER_CHANGED_PATHS, STRICT_NODE_HISTORY,
+ INCLUDE_MERGED_REVISIONS, REVPROPS, REAL_RECEIVER, and REAL_RECEIVER_BATON
+ parameters are all as per the svn_client_log5 API. */
+static svn_error_t *
+run_ra_get_log(apr_array_header_t *revision_ranges,
+ apr_array_header_t *paths,
+ apr_array_header_t *log_segments,
+ svn_client__pathrev_t *actual_loc,
+ svn_ra_session_t *ra_session,
+ /* The following are as per svn_client_log5. */
+ const apr_array_header_t *targets,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t real_receiver,
+ void *real_receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+ pre_15_receiver_baton_t rb = {0};
+ apr_pool_t *iterpool;
+ svn_boolean_t has_log_revprops;
- SVN_ERR(svn_ra_has_capability(ra_session, &has_log_revprops,
- SVN_RA_CAPABILITY_LOG_REVPROPS, pool));
+ SVN_ERR(svn_ra_has_capability(ra_session, &has_log_revprops,
+ SVN_RA_CAPABILITY_LOG_REVPROPS,
+ scratch_pool));
- if (!has_log_revprops) {
+ if (!has_log_revprops)
+ {
/* See above pre-1.5 notes. */
rb.ctx = ctx;
/* Create ra session on first use */
- rb.ra_session_pool = pool;
+ rb.ra_session_pool = scratch_pool;
rb.ra_session_url = actual_loc->url;
}
- }
/* It's a bit complex to correctly handle the special revision words
* such as "BASE", "COMMITTED", and "PREV". For example, if the
@@ -577,35 +665,54 @@ svn_client_log5(const apr_array_header_t
* epg wonders if the repository could send a unified stream of log
* entries if the paths and revisions were passed down.
*/
- iterpool = svn_pool_create(pool);
+ iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < revision_ranges->nelts; i++)
{
- svn_revnum_t start_revnum, end_revnum, youngest_rev = SVN_INVALID_REVNUM;
+ const char *old_session_url;
const char *path = APR_ARRAY_IDX(targets, 0, const char *);
const char *local_abspath_or_url;
- svn_opt_revision_range_t *range;
+ rev_range_t *range;
limit_receiver_baton_t lb;
svn_log_entry_receiver_t passed_receiver;
void *passed_receiver_baton;
const apr_array_header_t *passed_receiver_revprops;
+ svn_location_segment_t **matching_segment;
+ svn_revnum_t younger_rev;
svn_pool_clear(iterpool);
if (!svn_path_is_url(path))
- SVN_ERR(svn_dirent_get_absolute(&local_abspath_or_url, path, iterpool));
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath_or_url, path,
+ iterpool));
else
local_abspath_or_url = path;
- range = APR_ARRAY_IDX(revision_ranges, i, svn_opt_revision_range_t *);
+ range = APR_ARRAY_IDX(revision_ranges, i, rev_range_t *);
- SVN_ERR(svn_client__get_revision_number(&start_revnum, &youngest_rev,
- ctx->wc_ctx, local_abspath_or_url,
- ra_session, &range->start,
- iterpool));
- SVN_ERR(svn_client__get_revision_number(&end_revnum, &youngest_rev,
- ctx->wc_ctx, local_abspath_or_url,
- ra_session, &range->end,
- iterpool));
+ /* Issue #4355: Account for renames spanning requested
+ revision ranges. */
+ younger_rev = MAX(range->range_start, range->range_end);
+ matching_segment = bsearch(&younger_rev, log_segments->elts,
+ log_segments->nelts, log_segments->elt_size,
+ compare_rev_to_segment);
+ SVN_ERR_ASSERT(*matching_segment);
+
+ /* 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
+ error...*/
+ if ((*matching_segment)->path != NULL)
+ {
+ /* ...but if there is history, then we must account for issue
+ #4355 and make sure our RA session is pointing at the correct
+ location. */
+ const char *segment_url = svn_path_url_add_component2(
+ actual_loc->repos_root_url, (*matching_segment)->path,
+ scratch_pool);
+ SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
+ ra_session,
+ segment_url,
+ scratch_pool));
+ }
if (has_log_revprops)
{
@@ -634,40 +741,10 @@ svn_client_log5(const apr_array_header_t
passed_receiver_baton = &lb;
}
- /* Issue #4355: If multiple REVISION_RANGES were requested we might
- need to reparent the session to account for renames. */
- if (i > 0)
- {
- const char *old_session_url;
- svn_client__pathrev_t *resolved_loc;
-
- /* Ensure session is pointing to our starting target. */
- SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
- ra_session,
- resolved_target,
- pool));
- /* Find the target's (possibly different) url at the start of
- RANGE and then reparent the session to that if necessary. */
- SVN_ERR(svn_client__resolve_rev_and_url(&resolved_loc, ra_session,
- resolved_target,
- &resolved_peg_rev,
- &(range->start),
- ctx, iterpool));
- SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
- ra_session,
- resolved_loc->url,
- pool));
- if (!has_log_revprops)
- {
- /* See above pre-1.5 notes. */
- rb.ra_session_url = resolved_loc->url;
- }
- }
-
SVN_ERR(svn_ra_get_log2(ra_session,
- condensed_targets,
- start_revnum,
- end_revnum,
+ paths,
+ range->range_start,
+ range->range_end,
limit,
discover_changed_paths,
strict_node_history,
@@ -690,3 +767,85 @@ svn_client_log5(const apr_array_header_t
return SVN_NO_ERROR;
}
+
+/*** Public Interface. ***/
+
+svn_error_t *
+svn_client_log5(const apr_array_header_t *targets,
+ const svn_opt_revision_t *peg_revision,
+ const apr_array_header_t *opt_rev_ranges,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t real_receiver,
+ void *real_receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *ra_session;
+ const char *old_session_url;
+ const char *ra_target;
+ svn_opt_revision_t youngest_opt_rev;
+ svn_revnum_t youngest_rev;
+ svn_revnum_t oldest_rev;
+ svn_opt_revision_t peg_rev;
+ svn_client__pathrev_t *actual_loc;
+ apr_array_header_t *log_segments;
+ apr_array_header_t *revision_ranges;
+ apr_array_header_t *relative_targets;
+
+ if (opt_rev_ranges->nelts == 0)
+ {
+ return svn_error_create
+ (SVN_ERR_CLIENT_BAD_REVISION, NULL,
+ _("Missing required revision specification"));
+ }
+
+ /* Make a copy of PEG_REVISION, we may need to change it to a
+ default value. */
+ peg_rev = *peg_revision;
+
+ SVN_ERR(resolve_log_targets(&relative_targets, &ra_target, &peg_rev,
+ targets, ctx, pool, pool));
+
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
+ ra_target, NULL, &peg_rev, &peg_rev,
+ ctx, pool));
+
+ /* Convert OPT_REV_RANGES to an array of rev_range_t and find the youngest
+ and oldest revision range that spans all of OPT_REV_RANGES. */
+ SVN_ERR(convert_opt_rev_array_to_rev_range_array(&revision_ranges,
+ &youngest_rev,
+ &oldest_rev,
+ ra_session,
+ ra_target,
+ opt_rev_ranges, &peg_rev,
+ ctx, pool, pool));
+
+ /* Make ACTUAL_LOC and RA_SESSION point to the youngest operative rev. */
+ youngest_opt_rev.kind = svn_opt_revision_number;
+ youngest_opt_rev.value.number = youngest_rev;
+ SVN_ERR(svn_client__resolve_rev_and_url(&actual_loc, ra_session,
+ ra_target, &peg_rev,
+ &youngest_opt_rev, ctx, pool));
+ 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));
+
+ SVN_ERR(run_ra_get_log(revision_ranges, relative_targets, log_segments,
+ actual_loc, ra_session, targets, limit,
+ discover_changed_paths, strict_node_history,
+ include_merged_revisions, revprops, real_receiver,
+ real_receiver_baton, ctx, pool));
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c Tue May 7 13:26:25 2013
@@ -12028,16 +12028,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,
+/* 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 NULL 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,
@@ -12047,18 +12048,21 @@ short_circuit_mergeinfo_log(svn_boolean_
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,
+ svn_error_t *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,
- NULL, ctx, scratch_pool);
+ NULL, ctx, result_pool,
+ scratch_pool);
if (err)
{
@@ -12128,6 +12132,7 @@ find_last_merged_location(svn_client__pa
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;
@@ -12140,14 +12145,15 @@ find_last_merged_location(svn_client__pa
/* 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))
{
@@ -12174,14 +12180,15 @@ find_last_merged_location(svn_client__pa
(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
Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c Tue May 7 13:26:25 2013
@@ -1647,11 +1647,11 @@ svn_client_mergeinfo_get_merged(apr_hash
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,
@@ -1662,12 +1662,15 @@ svn_client_mergeinfo_log2(svn_boolean_t
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
@@ -1684,6 +1687,7 @@ svn_client_mergeinfo_log2(svn_boolean_t
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)
@@ -1709,6 +1713,8 @@ svn_client_mergeinfo_log2(svn_boolean_t
&& (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
@@ -1716,10 +1722,45 @@ svn_client_mergeinfo_log2(svn_boolean_t
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))
{
@@ -1751,6 +1792,7 @@ svn_client_mergeinfo_log2(svn_boolean_t
history. */
if (finding_merged)
{
+ svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
else
@@ -1768,18 +1810,17 @@ svn_client_mergeinfo_log2(svn_boolean_t
* ### 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,
@@ -1792,17 +1833,17 @@ svn_client_mergeinfo_log2(svn_boolean_t
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),
@@ -1813,7 +1854,7 @@ svn_client_mergeinfo_log2(svn_boolean_t
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,
@@ -2086,6 +2127,31 @@ svn_client_mergeinfo_log2(svn_boolean_t
}
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,
Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c Tue May 7 13:26:25 2013
@@ -447,9 +447,6 @@ svn_client_open_ra_session2(svn_ra_sessi
scratch_pool));
}
-
-
-
svn_error_t *
svn_client__resolve_rev_and_url(svn_client__pathrev_t **resolved_loc_p,
svn_ra_session_t *ra_session,
Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/repos_diff.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/repos_diff.c Tue May 7 13:26:25 2013
@@ -843,6 +843,37 @@ window_handler(svn_txdelta_window_t *win
return SVN_NO_ERROR;
}
+/* Implements svn_stream_lazyopen_func_t. */
+static svn_error_t *
+lazy_open_source(svn_stream_t **stream,
+ void *baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct file_baton *fb = baton;
+
+ SVN_ERR(svn_stream_open_readonly(stream, fb->path_start_revision,
+ result_pool, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_stream_lazyopen_func_t. */
+static svn_error_t *
+lazy_open_result(svn_stream_t **stream,
+ void *baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct file_baton *fb = baton;
+
+ SVN_ERR(svn_stream_open_unique(stream, &fb->path_end_revision, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* An svn_delta_editor_t function. */
static svn_error_t *
apply_textdelta(void *file_baton,
@@ -902,14 +933,13 @@ apply_textdelta(void *file_baton,
}
/* Open the file to be used as the base for second revision */
- SVN_ERR(svn_stream_open_readonly(&src_stream, fb->path_start_revision,
- scratch_pool, scratch_pool));
+ src_stream = svn_stream_lazyopen_create(lazy_open_source, fb, FALSE,
+ scratch_pool);
/* Open the file that will become the second revision after applying the
text delta, it starts empty */
- SVN_ERR(svn_stream_open_unique(&result_stream, &fb->path_end_revision, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
+ result_stream = svn_stream_lazyopen_create(lazy_open_result, fb, FALSE,
+ scratch_pool);
svn_txdelta_apply(src_stream,
result_stream,
Modified: subversion/branches/wc-collate-path/subversion/libsvn_delta/compose_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_delta/compose_delta.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_delta/compose_delta.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_delta/compose_delta.c Tue May 7 13:26:25 2013
@@ -648,15 +648,17 @@ copy_source_ops(apr_size_t offset, apr_s
{
const svn_txdelta_op_t *const op = &window->ops[op_ndx];
const apr_size_t *const off = &ndx->offs[op_ndx];
- apr_size_t fix_offset;
- apr_size_t fix_limit;
+ const apr_size_t fix_offset = (offset > off[0] ? offset - off[0] : 0);
+ const apr_size_t fix_limit = (off[1] > limit ? off[1] - limit : 0);
+ /* Ideally, we'd do this check before assigning fix_offset and
+ fix_limit; but then we couldn't make them const whilst still
+ adhering to C90 rules. Instead, we're going to assume that a
+ smart optimizing compiler will reorder this check before the
+ local variable initialization. */
if (off[0] >= limit)
break;
- fix_offset = (offset > off[0] ? offset - off[0] : 0);
- fix_limit = (off[1] > limit ? off[1] - limit : 0);
-
/* It would be extremely weird if the fixed-up op had zero length. */
assert(fix_offset + fix_limit < op->length);
@@ -701,23 +703,22 @@ copy_source_ops(apr_size_t offset, apr_s
apr_size_t tgt_off = target_offset;
assert(ptn_length > ptn_overlap);
- /* ### FIXME: ptn_overlap is unsigned, so the if() condition
- below is always true! Either it should be '> 0', or the
- code block should be unconditional. See also r842362. */
- if (ptn_overlap >= 0)
- {
- /* Issue second subrange in the pattern. */
- const apr_size_t length =
- MIN(op->length - fix_off - fix_limit,
- ptn_length - ptn_overlap);
- copy_source_ops(op->offset + ptn_overlap,
- op->offset + ptn_overlap + length,
- tgt_off,
- op_ndx,
- build_baton, window, ndx, pool);
- fix_off += length;
- tgt_off += length;
- }
+ /* Unconditionally issue the second subrange of the
+ pattern. This is always correct, since the outer
+ condition already verifies that there is an overlap
+ in the target copy. */
+ {
+ const apr_size_t length =
+ MIN(op->length - fix_off - fix_limit,
+ ptn_length - ptn_overlap);
+ copy_source_ops(op->offset + ptn_overlap,
+ op->offset + ptn_overlap + length,
+ tgt_off,
+ op_ndx,
+ build_baton, window, ndx, pool);
+ fix_off += length;
+ tgt_off += length;
+ }
assert(fix_off + fix_limit <= op->length);
if (ptn_overlap > 0
Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.c Tue May 7 13:26:25 2013
@@ -487,6 +487,7 @@ svn_fs_upgrade(const char *path, apr_poo
svn_error_t *
svn_fs_verify(const char *path,
+ apr_hash_t *fs_config,
svn_revnum_t start,
svn_revnum_t end,
svn_fs_progress_notify_func_t notify_func,
@@ -499,7 +500,7 @@ svn_fs_verify(const char *path,
svn_fs_t *fs;
SVN_ERR(fs_library_vtable(&vtable, path, pool));
- fs = fs_new(NULL, pool);
+ fs = fs_new(fs_config, pool);
SVN_MUTEX__WITH_LOCK(common_pool_lock,
vtable->verify_fs(fs, path, start, end,
@@ -515,6 +516,15 @@ svn_fs_path(svn_fs_t *fs, apr_pool_t *po
return apr_pstrdup(pool, fs->path);
}
+apr_hash_t *
+svn_fs_config(svn_fs_t *fs, apr_pool_t *pool)
+{
+ if (fs->config)
+ return apr_hash_copy(pool, fs->config);
+
+ return NULL;
+}
+
svn_error_t *
svn_fs_delete_fs(const char *path, apr_pool_t *pool)
{
@@ -1306,7 +1316,6 @@ svn_fs_youngest_rev(svn_revnum_t *younge
return svn_error_trace(fs->vtable->youngest_rev(youngest_p, fs, pool));
}
-#ifdef SVN_FS_INFO
svn_error_t *
svn_fs_info_format(int *fs_format,
svn_version_t **supports_version,
@@ -1329,7 +1338,6 @@ svn_fs_info_config_files(apr_array_heade
result_pool,
scratch_pool));
}
-#endif
svn_error_t *
svn_fs_deltify_revision(svn_fs_t *fs, svn_revnum_t revision, apr_pool_t *pool)
@@ -1617,24 +1625,41 @@ svn_fs_version(void)
}
-#ifdef SVN_FS_INFO
/** info **/
svn_error_t *
-svn_fs_info(const svn_fs_info_t **info,
+svn_fs_info(const svn_fs_info_placeholder_t **info_p,
svn_fs_t *fs,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- SVN__NOT_IMPLEMENTED();
+ if (fs->vtable->info_fsap)
+ {
+ SVN_ERR(fs->vtable->info_fsap((const void **)info_p, fs,
+ result_pool, scratch_pool));
+ }
+ else
+ {
+ svn_fs_info_placeholder_t *info = apr_palloc(result_pool, sizeof(*info));
+ /* ### Ask the disk(!), since svn_fs_t doesn't cache the answer. */
+ SVN_ERR(svn_fs_type(&info->fs_type, fs->path, result_pool));
+ *info_p = info;
+ }
+ return SVN_NO_ERROR;
}
-svn_fs_info_t *
-svn_fs_info_dup(const svn_fs_info_t *info,
- apr_pool_t *result_pool)
+void *
+svn_fs_info_dup(const void *info_void,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- /* Not implemented. */
- SVN_ERR_MALFUNCTION_NO_RETURN();
- return NULL;
+ const svn_fs_info_placeholder_t *info = info_void;
+ fs_library_vtable_t *vtable;
+
+ SVN_ERR(get_library_vtable(&vtable, info->fs_type, scratch_pool));
+
+ if (vtable->info_fsap_dup)
+ return vtable->info_fsap_dup(info_void, result_pool);
+ else
+ return apr_pmemdup(result_pool, info, sizeof(*info));
}
-#endif
Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.h?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs/fs-loader.h Tue May 7 13:26:25 2013
@@ -131,7 +131,9 @@ typedef struct fs_library_vtable_t
const char *,
apr_hash_t *,
apr_pool_t *));
-
+ /* For svn_fs_info_fsfs_dup(). */
+ void *(*info_fsap_dup)(const void *fsap_info,
+ apr_pool_t *result_pool);
} fs_library_vtable_t;
/* This is the type of symbol an FS module defines to fetch the
@@ -221,6 +223,11 @@ typedef struct fs_vtable_t
svn_fs_t *fs,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+ svn_error_t *(*info_fsap)(const void **fsap_info,
+ svn_fs_t *fs,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+ /* info_fsap_dup is in the library vtable. */
svn_error_t *(*verify_root)(svn_fs_root_t *root,
apr_pool_t *pool);
svn_error_t *(*freeze)(svn_fs_t *fs,
Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_base/fs.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_base/fs.c Tue May 7 13:26:25 2013
@@ -562,6 +562,7 @@ static fs_vtable_t fs_vtable = {
svn_fs_base__get_locks,
base_bdb_info_format,
base_bdb_info_config_files,
+ NULL /* info_fsap */,
base_bdb_verify_root,
base_bdb_freeze,
base_bdb_set_errcall,
@@ -1462,7 +1463,8 @@ static fs_library_vtable_t library_vtabl
base_bdb_pack,
base_bdb_logfiles,
svn_fs_base__id_parse,
- base_set_svn_fs_open
+ base_set_svn_fs_open,
+ NULL /* info_fsap_dup */
};
svn_error_t *
Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.c Tue May 7 13:26:25 2013
@@ -164,6 +164,21 @@ fs_freeze(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+static svn_error_t *
+fs_info(const void **fsfs_info,
+ svn_fs_t *fs,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+ svn_fs_fsfs_info_t *info = apr_palloc(result_pool, sizeof(*info));
+ info->fs_type = SVN_FS_TYPE_FSFS;
+ info->shard_size = ffd->max_files_per_dir;
+ info->min_unpacked_rev = ffd->min_unpacked_rev;
+ *fsfs_info = info;
+ return SVN_NO_ERROR;
+}
+
/* The vtable associated with a specific open filesystem. */
@@ -186,6 +201,7 @@ static fs_vtable_t fs_vtable = {
svn_fs_fs__get_locks,
svn_fs_fs__info_format,
svn_fs_fs__info_config_files,
+ fs_info,
svn_fs_fs__verify_root,
fs_freeze,
fs_set_errcall
@@ -414,6 +430,15 @@ fs_set_svn_fs_open(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+static void *
+fs_info_dup(const void *fsfs_info_void,
+ apr_pool_t *result_pool)
+{
+ /* All fields are either ints or static strings. */
+ const svn_fs_fsfs_info_t *fsfs_info = fsfs_info_void;
+ return apr_pmemdup(result_pool, fsfs_info, sizeof(*fsfs_info));
+}
+
/* Base FS library vtable, used by the FS loader library. */
@@ -431,7 +456,8 @@ static fs_library_vtable_t library_vtabl
fs_pack,
fs_logfiles,
NULL /* parse_id */,
- fs_set_svn_fs_open
+ fs_set_svn_fs_open,
+ fs_info_dup
};
svn_error_t *
Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c Tue May 7 13:26:25 2013
@@ -1157,9 +1157,9 @@ read_config(fs_fs_data_t *ffd,
const char *fs_path,
apr_pool_t *pool)
{
- SVN_ERR(svn_config_read2(&ffd->config,
+ SVN_ERR(svn_config_read3(&ffd->config,
svn_dirent_join(fs_path, PATH_CONFIG, pool),
- FALSE, FALSE, pool));
+ FALSE, FALSE, FALSE, pool));
/* Initialize ffd->rep_sharing_allowed. */
if (ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT)
Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/commit.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/commit.c Tue May 7 13:26:25 2013
@@ -989,7 +989,7 @@ create_put_body(serf_bucket_t **body_bkt
apr_file_buffer_set(ctx->svndiff, NULL, 0);
#endif
offset = 0;
- apr_file_seek(ctx->svndiff, APR_SET, &offset);
+ SVN_ERR(svn_io_file_seek(ctx->svndiff, APR_SET, &offset, pool));
*body_bkt = serf_bucket_file_create(ctx->svndiff, alloc);
return SVN_NO_ERROR;
Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c Tue May 7 13:26:25 2013
@@ -94,8 +94,8 @@ typedef enum report_state_e {
We measure outstanding requests as the sum of NUM_ACTIVE_FETCHES and
NUM_ACTIVE_PROPFINDS in the report_context_t structure. */
-#define REQUEST_COUNT_TO_PAUSE 1000
-#define REQUEST_COUNT_TO_RESUME 100
+#define REQUEST_COUNT_TO_PAUSE 50
+#define REQUEST_COUNT_TO_RESUME 40
/* Forward-declare our report context. */
@@ -2721,7 +2721,7 @@ create_update_report_body(serf_bucket_t
apr_off_t offset;
offset = 0;
- apr_file_seek(report->body_file, APR_SET, &offset);
+ SVN_ERR(svn_io_file_seek(report->body_file, APR_SET, &offset, pool));
*body_bkt = serf_bucket_file_create(report->body_file, alloc);
Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/marshal.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/marshal.c Tue May 7 13:26:25 2013
@@ -1230,6 +1230,15 @@ static svn_error_t *vparse_tuple(const a
else
break;
}
+ else if (**fmt == '3' && elt->kind == SVN_RA_SVN_WORD)
+ {
+ if (strcmp(elt->u.word, "true") == 0)
+ *va_arg(*ap, svn_tristate_t *) = svn_tristate_true;
+ else if (strcmp(elt->u.word, "false") == 0)
+ *va_arg(*ap, svn_tristate_t *) = svn_tristate_false;
+ else
+ break;
+ }
else if (**fmt == 'l' && elt->kind == SVN_RA_SVN_LIST)
*va_arg(*ap, apr_array_header_t **) = elt->u.list;
else if (**fmt == '(' && elt->kind == SVN_RA_SVN_LIST)
@@ -1268,6 +1277,9 @@ static svn_error_t *vparse_tuple(const a
case 'n':
*va_arg(*ap, apr_uint64_t *) = SVN_RA_SVN_UNSPECIFIED_NUMBER;
break;
+ case '3':
+ *va_arg(*ap, svn_tristate_t *) = svn_tristate_unknown;
+ break;
case '(':
nesting_level++;
break;
Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/authz.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/authz.c Tue May 7 13:26:25 2013
@@ -824,7 +824,7 @@ authz_retrieve_config_repo(svn_config_t
{
if (!must_exist)
{
- SVN_ERR(svn_config_create(cfg_p, TRUE, result_pool));
+ SVN_ERR(svn_config_create2(cfg_p, TRUE, TRUE, result_pool));
return SVN_NO_ERROR;
}
else
@@ -842,7 +842,7 @@ authz_retrieve_config_repo(svn_config_t
}
SVN_ERR(svn_fs_file_contents(&contents, root, fs_path, scratch_pool));
- err = svn_config_parse(cfg_p, contents, TRUE, result_pool);
+ err = svn_config_parse(cfg_p, contents, TRUE, TRUE, result_pool);
/* Add the URL to the error stack since the parser doesn't have it. */
if (err != SVN_NO_ERROR)
@@ -891,7 +891,7 @@ authz_retrieve_config(svn_config_t **cfg
else
{
/* Outside of repo file or Windows registry*/
- SVN_ERR(svn_config_read2(cfg_p, path, must_exist, TRUE, pool));
+ SVN_ERR(svn_config_read3(cfg_p, path, must_exist, TRUE, TRUE, pool));
}
return SVN_NO_ERROR;
@@ -944,7 +944,7 @@ svn_repos__authz_read(svn_authz_t **auth
if (accept_urls)
SVN_ERR(authz_retrieve_config(&authz->cfg, path, must_exist, pool));
else
- SVN_ERR(svn_config_read2(&authz->cfg, path, must_exist, TRUE, pool));
+ SVN_ERR(svn_config_read3(&authz->cfg, path, must_exist, TRUE, TRUE, pool));
if (groups_path)
{
@@ -956,8 +956,8 @@ svn_repos__authz_read(svn_authz_t **auth
SVN_ERR(authz_retrieve_config(&groups_cfg, groups_path, must_exist,
pool));
else
- SVN_ERR(svn_config_read2(&groups_cfg, groups_path, must_exist,
- TRUE, pool));
+ SVN_ERR(svn_config_read3(&groups_cfg, groups_path, must_exist,
+ TRUE, TRUE, pool));
/* Copy the groups from groups_cfg into authz. */
err = authz_copy_groups(authz, groups_cfg, pool);
@@ -998,14 +998,14 @@ svn_repos_authz_parse(svn_authz_t **auth
svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
/* Parse the authz stream */
- SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, pool));
+ SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, TRUE, pool));
if (groups_stream)
{
svn_config_t *groups_cfg;
/* Parse the groups stream */
- SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, pool));
+ SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, TRUE, pool));
SVN_ERR(authz_copy_groups(authz, groups_cfg, pool));
}
Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/dump.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/dump.c Tue May 7 13:26:25 2013
@@ -1438,7 +1438,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
}
/* Verify global metadata and backend-specific data first. */
- SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), start_rev, end_rev,
+ SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), svn_fs_config(fs, pool),
+ start_rev, end_rev,
verify_notify, verify_notify_baton,
cancel_func, cancel_baton, pool));
Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c Tue May 7 13:26:25 2013
@@ -740,7 +740,14 @@ pack_notify_func(void *baton,
struct pack_notify_baton *pnb = baton;
svn_repos_notify_t *notify;
- notify = svn_repos_notify_create(pack_action + 3, pool);
+ /* Simple conversion works for these values. */
+ SVN_ERR_ASSERT(pack_action >= svn_fs_pack_notify_start
+ && pack_action <= svn_fs_pack_notify_end_revprop);
+
+ notify = svn_repos_notify_create(pack_action
+ + svn_repos_notify_pack_shard_start
+ - svn_fs_pack_notify_start,
+ pool);
notify->shard = shard;
pnb->notify_func(pnb->notify_baton, notify, pool);
Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/hooks.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/hooks.c Tue May 7 13:26:25 2013
@@ -421,7 +421,8 @@ svn_repos__parse_hooks_env(apr_hash_t **
if (local_abspath)
{
- SVN_ERR(svn_config_read2(&cfg, local_abspath, FALSE, TRUE, scratch_pool));
+ SVN_ERR(svn_config_read3(&cfg, local_abspath, FALSE,
+ TRUE, TRUE, scratch_pool));
b.cfg = cfg;
b.hooks_env = apr_hash_make(result_pool);
(void)svn_config_enumerate_sections2(cfg, parse_hooks_env_section, &b,
Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/repos.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/repos.c Tue May 7 13:26:25 2013
@@ -1677,7 +1677,6 @@ svn_repos_has_capability(svn_repos_t *re
return SVN_NO_ERROR;
}
-#ifdef SVN_FS_INFO
svn_error_t *
svn_repos_capabilities(apr_hash_t **capabilities,
svn_repos_t *repos,
@@ -1734,7 +1733,6 @@ svn_repos_info_format(int *repos_format,
return SVN_NO_ERROR;
}
-#endif
svn_fs_t *
svn_repos_fs(svn_repos_t *repos)
Modified: subversion/branches/wc-collate-path/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_subr/cache-inprocess.c?rev=1479901&r1=1479900&r2=1479901&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_subr/cache-inprocess.c Tue May 7 13:26:25 2013
@@ -642,6 +642,7 @@ svn_cache__create_inprocess(svn_cache__t
wrapper->vtable = &inprocess_cache_vtable;
wrapper->cache_internal = cache;
+ wrapper->pretend_empty = !!getenv("SVN_X_DOES_NOT_MARK_THE_SPOT");
*cache_p = wrapper;
return SVN_NO_ERROR;