You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/05/12 01:28:08 UTC
svn commit: r1481454 [2/5] - in /subversion/branches/fsfs-format7: ./
build/ac-macros/ build/generator/ contrib/server-side/fsfsfixer/
contrib/server-side/fsfsfixer/fixer/ subversion/bindings/ctypes-python/
subversion/bindings/swig/ subversion/bindings...
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/log.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/log.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/log.c Sat May 11 23:28:06 2013
@@ -42,6 +42,7 @@
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
+#include <assert.h>
/*** Getting misc. information ***/
@@ -260,57 +261,225 @@ 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 *RELATIVE_TARGETS 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_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"));
+
+ /* Initialize the output array. At a minimum, we need room for one
+ (possibly empty) relpath. Otherwise, we have to hold a relpath
+ for every item in TARGETS except the first. */
+ *relative_targets = apr_array_make(result_pool,
+ MAX(1, targets->nelts - 1),
+ sizeof(const char *));
- if (revision_ranges->nelts == 0)
+ 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;
+}
+
+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))
{
@@ -329,15 +498,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)
{
@@ -354,163 +523,117 @@ 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)
+ /* Does RANGE describe a single svn_opt_revision_t? */
+ if (range->start.kind == range->end.kind)
{
- if (range->start.kind == svn_opt_revision_number &&
- range->end.kind == svn_opt_revision_number)
+ if (range->start.kind == svn_opt_revision_number)
{
- session_opt_rev =
- (range->start.value.number > range->end.value.number ?
- range->start : range->end);
+ if (range->start.value.number == range->end.value.number)
+ start_same_as_end = TRUE;
}
- else if (range->start.kind == svn_opt_revision_head ||
- range->end.kind == svn_opt_revision_head)
+ else if (range->start.kind == svn_opt_revision_date)
{
- session_opt_rev.kind = svn_opt_revision_head;
+ if (range->start.value.date == range->end.value.date)
+ start_same_as_end = TRUE;
}
- else if (range->start.kind == svn_opt_revision_date &&
- range->end.kind == svn_opt_revision_date)
+ else
{
- session_opt_rev =
- (range->start.value.date > range->end.value.date ?
- range->start : range->end);
+ start_same_as_end = TRUE;
}
}
- }
-
- /* 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;
- }
- }
+ 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));
+/* 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
@@ -559,35 +682,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)
{
@@ -617,9 +759,9 @@ svn_client_log5(const apr_array_header_t
}
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,
@@ -642,3 +784,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/fsfs-format7/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/merge.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/merge.c Sat May 11 23:28:06 2013
@@ -436,7 +436,7 @@ check_repos_match(const merge_target_t *
if (!svn_uri__is_ancestor(target->loc.repos_root_url, url))
return svn_error_createf(
SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("Url '%s' of '%s' is not in repository '%s'"),
+ _("URL '%s' of '%s' is not in repository '%s'"),
url, svn_dirent_local_style(local_abspath, scratch_pool),
target->loc.repos_root_url);
@@ -6229,7 +6229,7 @@ get_wc_explicit_mergeinfo_catalog(apr_ha
err = svn_error_createf(
SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
_("Invalid mergeinfo detected on '%s', "
- "mergetracking not possible"),
+ "merge tracking not possible"),
svn_dirent_local_style(wc_path, scratch_pool));
}
return svn_error_trace(err);
@@ -7378,7 +7378,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
err = svn_error_createf(
SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
_("Invalid mergeinfo detected on merge target '%s', "
- "mergetracking not possible"),
+ "merge tracking not possible"),
svn_dirent_local_style(target_abspath, scratch_pool));
}
return svn_error_trace(err);
@@ -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/fsfs-format7/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/mergeinfo.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/mergeinfo.c Sat May 11 23:28:06 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/fsfs-format7/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/ra.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/ra.c Sat May 11 23:28:06 2013
@@ -158,7 +158,7 @@ push_wc_prop(void *baton,
if (! cb->commit_items)
return svn_error_createf
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("Attempt to set wc property '%s' on '%s' in a non-commit operation"),
+ _("Attempt to set wcprop '%s' on '%s' in a non-commit operation"),
name, svn_dirent_local_style(relpath, pool));
for (i = 0; i < cb->commit_items->nelts; i++)
@@ -447,39 +447,14 @@ svn_client_open_ra_session2(svn_ra_sessi
scratch_pool));
}
-
-
-
-/* Given PATH_OR_URL, which contains either a working copy path or an
- absolute URL, a peg revision PEG_REVISION, and a desired revision
- REVISION, find the path at which that object exists in REVISION,
- following copy history if necessary. If REVISION is younger than
- PEG_REVISION, then check that PATH_OR_URL is the same node in both
- PEG_REVISION and REVISION, and return @c
- SVN_ERR_CLIENT_UNRELATED_RESOURCES if it is not the same node.
-
- If PEG_REVISION->kind is 'unspecified', the peg revision is 'head'
- for a URL or 'working' for a WC path. If REVISION->kind is
- 'unspecified', the operative revision is the peg revision.
-
- Store the actual location of the object in *RESOLVED_LOC_P.
-
- RA_SESSION should be an open RA session pointing at the URL of
- PATH_OR_URL, or NULL, in which case this function will open its own
- temporary session.
-
- Use authentication baton cached in CTX to authenticate against the
- repository.
-
- Use POOL for all allocations. */
-static svn_error_t *
-resolve_rev_and_url(svn_client__pathrev_t **resolved_loc_p,
- svn_ra_session_t *ra_session,
- const char *path_or_url,
- const svn_opt_revision_t *peg_revision,
- const svn_opt_revision_t *revision,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+svn_error_t *
+svn_client__resolve_rev_and_url(svn_client__pathrev_t **resolved_loc_p,
+ svn_ra_session_t *ra_session,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
svn_opt_revision_t peg_rev = *peg_revision;
svn_opt_revision_t start_rev = *revision;
@@ -545,9 +520,9 @@ svn_client__ra_session_from_path2(svn_ra
if (corrected_url && svn_path_is_url(path_or_url))
path_or_url = corrected_url;
- SVN_ERR(resolve_rev_and_url(&resolved_loc, ra_session,
- path_or_url, peg_revision, revision,
- ctx, pool));
+ SVN_ERR(svn_client__resolve_rev_and_url(&resolved_loc, ra_session,
+ path_or_url, peg_revision, revision,
+ ctx, pool));
/* Make the session point to the real URL. */
SVN_ERR(svn_ra_reparent(ra_session, resolved_loc->url, pool));
@@ -1009,9 +984,9 @@ svn_client__youngest_common_ancestor(con
path_or_url1, NULL,
revision1, revision1,
ctx, sesspool));
- SVN_ERR(resolve_rev_and_url(&loc2, session,
- path_or_url2, revision2, revision2,
- ctx, scratch_pool));
+ SVN_ERR(svn_client__resolve_rev_and_url(&loc2, session,
+ path_or_url2, revision2, revision2,
+ ctx, scratch_pool));
SVN_ERR(svn_client__get_youngest_common_ancestor(
&ancestor, loc1, loc2, session, ctx, result_pool, scratch_pool));
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/repos_diff.c Sat May 11 23:28:06 2013
@@ -328,7 +328,7 @@ get_file_from_ra(struct file_baton *fb,
fb->pool, scratch_pool));
fstream = svn_stream_checksummed2(fstream, NULL, &fb->start_md5_checksum,
- svn_checksum_md5, TRUE, scratch_pool);
+ svn_checksum_md5, TRUE, fb->pool);
/* Retrieve the file and its properties */
SVN_ERR(svn_ra_get_file(fb->edit_baton->ra_session,
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/switch.c Sat May 11 23:28:06 2013
@@ -340,8 +340,8 @@ switch_internal(svn_revnum_t *result_rev
*timestamp_sleep = TRUE;
/* Drive the reporter structure, describing the revisions within
- PATH. When we call reporter->finish_report, the update_editor
- will be driven by svn_repos_dir_delta2. */
+ LOCAL_ABSPATH. When this calls reporter->finish_report, the
+ reporter will drive the switch_editor. */
SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
report_baton, TRUE,
depth, (! depth_is_sticky),
Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/update.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/update.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/update.c Sat May 11 23:28:06 2013
@@ -454,8 +454,8 @@ update_internal(svn_revnum_t *result_rev
*timestamp_sleep = TRUE;
/* Drive the reporter structure, describing the revisions within
- PATH. When we call reporter->finish_report, the
- update_editor will be driven by svn_repos_dir_delta2. */
+ LOCAL_ABSPATH. When this calls reporter->finish_report, the
+ reporter will drive the update_editor. */
SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
report_baton, TRUE,
depth, (! depth_is_sticky),
Modified: subversion/branches/fsfs-format7/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_ra_serf/serf.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_ra_serf/serf.c Sat May 11 23:28:06 2013
@@ -119,8 +119,9 @@ load_http_auth_types(apr_pool_t *pool, s
*authn_types |= SERF_AUTHN_NEGOTIATE;
else
return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
- _("Invalid config: unknown http auth"
- "type '%s'"), token);
+ _("Invalid config: unknown %s "
+ "'%s'"),
+ SVN_CONFIG_OPTION_HTTP_AUTH_TYPES, token);
}
}
else
Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/delta.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/delta.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/delta.c Sat May 11 23:28:06 2013
@@ -196,17 +196,6 @@ authz_root_check(svn_fs_root_t *root,
}
-static svn_error_t *
-not_a_dir_error(const char *role,
- const char *path)
-{
- return svn_error_createf
- (SVN_ERR_FS_NOT_DIRECTORY, 0,
- "Invalid %s directory '%s'",
- role, path ? path : "(null)");
-}
-
-
/* Public interface to computing directory deltas. */
svn_error_t *
svn_repos_dir_delta2(svn_fs_root_t *src_root,
@@ -237,7 +226,8 @@ svn_repos_dir_delta2(svn_fs_root_t *src_
if (src_parent_dir)
src_parent_dir = svn_relpath_canonicalize(src_parent_dir, pool);
else
- return not_a_dir_error("source parent", src_parent_dir);
+ return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, 0,
+ "Invalid source parent directory '(null)'");
/* TGT_FULLPATH must be valid. */
if (tgt_fullpath)
Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c Sat May 11 23:28:06 2013
@@ -1097,7 +1097,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
{
const svn_delta_editor_t *dump_editor;
void *dump_edit_baton = NULL;
- svn_revnum_t i;
+ svn_revnum_t rev;
svn_fs_t *fs = svn_repos_fs(repos);
apr_pool_t *subpool = svn_pool_create(pool);
svn_revnum_t youngest;
@@ -1129,10 +1129,6 @@ svn_repos_dump_fs3(svn_repos_t *repos,
_("End revision %ld is invalid "
"(youngest revision is %ld)"),
end_rev, youngest);
- if ((start_rev == 0) && incremental)
- incremental = FALSE; /* revision 0 looks the same regardless of
- whether or not this is an incremental
- dump, so just simplify things. */
/* Write out the UUID. */
SVN_ERR(svn_fs_get_uuid(fs, &uuid, pool));
@@ -1156,10 +1152,9 @@ svn_repos_dump_fs3(svn_repos_t *repos,
notify = svn_repos_notify_create(svn_repos_notify_dump_rev_end,
pool);
- /* Main loop: we're going to dump revision i. */
- for (i = start_rev; i <= end_rev; i++)
+ /* Main loop: we're going to dump revision REV. */
+ for (rev = start_rev; rev <= end_rev; rev++)
{
- svn_revnum_t from_rev, to_rev;
svn_fs_root_t *to_root;
svn_boolean_t use_deltas_for_rev;
@@ -1169,56 +1164,35 @@ svn_repos_dump_fs3(svn_repos_t *repos,
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
- /* Special-case the initial revision dump: it needs to contain
- *all* nodes, because it's the foundation of all future
- revisions in the dumpfile. */
- if ((i == start_rev) && (! incremental))
- {
- /* Special-special-case a dump of revision 0. */
- if (i == 0)
- {
- /* Just write out the one revision 0 record and move on.
- The parser might want to use its properties. */
- SVN_ERR(write_revision_record(stream, fs, 0, subpool));
- to_rev = 0;
- goto loop_end;
- }
-
- /* Compare START_REV to revision 0, so that everything
- appears to be added. */
- from_rev = 0;
- to_rev = i;
- }
- else
- {
- /* In the normal case, we want to compare consecutive revs. */
- from_rev = i - 1;
- to_rev = i;
- }
-
/* Write the revision record. */
- SVN_ERR(write_revision_record(stream, fs, to_rev, subpool));
+ SVN_ERR(write_revision_record(stream, fs, rev, subpool));
+
+ /* When dumping revision 0, we just write out the revision record.
+ The parser might want to use its properties. */
+ if (rev == 0)
+ goto loop_end;
/* Fetch the editor which dumps nodes to a file. Regardless of
what we've been told, don't use deltas for the first rev of a
non-incremental dump. */
- use_deltas_for_rev = use_deltas && (incremental || i != start_rev);
- SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton, fs, to_rev,
+ use_deltas_for_rev = use_deltas && (incremental || rev != start_rev);
+ SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton, fs, rev,
"", stream, &found_old_reference,
&found_old_mergeinfo, NULL,
notify_func, notify_baton,
start_rev, use_deltas_for_rev, FALSE, subpool));
/* Drive the editor in one way or another. */
- SVN_ERR(svn_fs_revision_root(&to_root, fs, to_rev, subpool));
+ SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, subpool));
/* If this is the first revision of a non-incremental dump,
we're in for a full tree dump. Otherwise, we want to simply
replay the revision. */
- if ((i == start_rev) && (! incremental))
+ if ((rev == start_rev) && (! incremental))
{
+ /* Compare against revision 0, so everything appears to be added. */
svn_fs_root_t *from_root;
- SVN_ERR(svn_fs_revision_root(&from_root, fs, from_rev, subpool));
+ SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, subpool));
SVN_ERR(svn_repos_dir_delta2(from_root, "", "",
to_root, "",
dump_editor, dump_edit_baton,
@@ -1232,6 +1206,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
}
else
{
+ /* The normal case: compare consecutive revs. */
SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
dump_editor, dump_edit_baton,
NULL, NULL, subpool));
@@ -1244,7 +1219,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
loop_end:
if (notify_func)
{
- notify->revision = to_rev;
+ notify->revision = rev;
notify_func(notify_baton, notify, subpool);
}
}
Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c Sat May 11 23:28:06 2013
@@ -1014,8 +1014,6 @@ find_entry(svn_membuffer_t *cache,
*/
if (group->used == GROUP_SIZE)
{
- static int count = 0;
-
/* every entry gets the same chance of being removed.
* Otherwise, we free the first entry, fill it and remove it
* again on the next occasion without considering the other
@@ -1037,7 +1035,6 @@ find_entry(svn_membuffer_t *cache,
let_entry_age(cache, entry);
drop_entry(cache, entry);
- printf("%d\n", ++count);
}
/* initialize entry for the new key
@@ -1551,7 +1548,7 @@ svn_cache__membuffer_cache_create(svn_me
{
/* We are OOM. There is no need to proceed with "half a cache".
*/
- return svn_error_wrap_apr(APR_ENOMEM, _("OOM"));
+ return svn_error_wrap_apr(APR_ENOMEM, "OOM");
}
#if APR_HAS_THREADS
@@ -2342,9 +2339,9 @@ combine_key(svn_membuffer_cache_t *cache
/* scramble key DATA. All of this must be reversible to prevent key
* collisions. So, we limit ourselves to xor and permutations. */
data[1] = (data[1] << 27) | (data[1] >> 37);
+ data[0] = (data[0] << 43) | (data[0] >> 21);
data[1] ^= data[0] & 0xffff;
data[0] ^= data[1] & 0xffffffffffff0000ull;
- data[0] = (data[0] << 43) | (data[0] >> 21);
/* combine with this cache's namespace */
cache->combined_key[0] = data[0] ^ cache->prefix[0];
Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c Sat May 11 23:28:06 2013
@@ -1152,6 +1152,16 @@ svn_config_ensure(const char *config_dir
"### ra_local (the file:// scheme). The value represents the number" NL
"### of MB used by the cache." NL
"# memory-cache-size = 16" NL
+ "### Set diff-ignore-content-type to 'yes' to cause 'svn diff' to" NL
+ "### attempt to show differences of all modified files regardless" NL
+ "### of their MIME content type. By default, Subversion will only" NL
+ "### attempt to show differences for files believed to have human-" NL
+ "### readable (non-binary) content. This option is especially" NL
+ "### useful when Subversion is configured (via the 'diff-cmd'" NL
+ "### option) to employ an external differencing tool which is able" NL
+ "### to show meaningful differences for binary file formats. [New" NL
+ "### in 1.9]" NL
+ "# diff-ignore-content-type = no" NL
"" NL
"### Section for configuring automatic properties." NL
"[auto-props]" NL
Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c Sat May 11 23:28:06 2013
@@ -679,7 +679,7 @@ svn_strerror(apr_status_t statcode, char
}
#ifdef SVN_DEBUG
-/* Defines svn__errno */
+/* Defines svn__errno and svn__apr_errno */
#include "errorcode.inc"
#endif
@@ -705,6 +705,12 @@ svn_error_symbolic_name(apr_status_t sta
for (i = 0; i < sizeof(svn__errno) / sizeof(svn__errno[0]); i++)
if (svn__errno[i].errcode == (int)statcode)
return svn__errno[i].errname;
+
+ /* Try APR errors. */
+ /* Linear search through a sorted array */
+ for (i = 0; i < sizeof(svn__apr_errno) / sizeof(svn__apr_errno[0]); i++)
+ if (svn__apr_errno[i].errcode == (int)statcode)
+ return svn__apr_errno[i].errname;
#endif /* SVN_DEBUG */
/* ### TODO: do we need APR_* error macros? What about APR_TO_OS_ERROR()? */
Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite.c Sat May 11 23:28:06 2013
@@ -38,6 +38,11 @@
#include "private/svn_skel.h"
#include "private/svn_token.h"
+#ifdef SVN_UNICODE_NORMALIZATION_FIXES
+#include "private/svn_utf_private.h"
+#include "private/svn_string_private.h"
+#endif /* SVN_UNICODE_NORMALIZATION_FIXES */
+
#ifdef SQLITE3_DEBUG
#include "private/svn_debug.h"
#endif
@@ -60,6 +65,13 @@ extern int (*const svn_sqlite3__api_conf
#error SQLite is too old -- version 3.7.12 is the minimum required version
#endif
+#ifdef SVN_UNICODE_NORMALIZATION_FIXES
+/* Limit the length of a GLOB or LIKE pattern. */
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
+#endif
+#endif /* SVN_UNICODE_NORMALIZATION_FIXES */
+
const char *
svn_sqlite__compiled_version(void)
{
@@ -104,6 +116,13 @@ struct svn_sqlite__db_t
int nbr_statements;
svn_sqlite__stmt_t **prepared_stmts;
apr_pool_t *state_pool;
+
+#ifdef SVN_UNICODE_NORMALIZATION_FIXES
+ /* Buffers for SQLite extensoins. */
+ svn_membuf_t sqlext_buf1;
+ svn_membuf_t sqlext_buf2;
+ svn_membuf_t sqlext_buf3;
+#endif /* SVN_UNICODE_NORMALIZATION_FIXES */
};
struct svn_sqlite__stmt_t
@@ -873,6 +892,99 @@ close_apr(void *data)
return APR_SUCCESS;
}
+#ifdef SVN_UNICODE_NORMALIZATION_FIXES
+/* Unicode normalizing collation for WC paths */
+static int
+collate_ucs_nfd(void *baton,
+ int len1, const void *key1,
+ int len2, const void *key2)
+{
+ svn_sqlite__db_t *db = baton;
+ int result;
+
+ if (svn_utf__normcmp(key1, len1, key2, len2,
+ &db->sqlext_buf1, &db->sqlext_buf2, &result))
+ {
+ /* There is really nothing we can do here if an error occurs
+ during Unicode normalizetion, and attempting to recover could
+ result in the wc.db index being corrupted. Presumably this
+ can only happen if the index already contains invalid UTF-8
+ strings, which should never happen in any case ... */
+ SVN_ERR_MALFUNCTION_NO_RETURN();
+ }
+
+ return result;
+}
+
+static void
+glob_like_ucs_nfd_common(sqlite3_context *context,
+ int argc, sqlite3_value **argv,
+ svn_boolean_t sql_like)
+{
+ svn_sqlite__db_t *const db = sqlite3_user_data(context);
+
+ const char *const pattern = (void*)sqlite3_value_text(argv[0]);
+ const apr_size_t pattern_len = sqlite3_value_bytes(argv[0]);
+ const char *const string = (void*)sqlite3_value_text(argv[1]);
+ const apr_size_t string_len = sqlite3_value_bytes(argv[1]);
+
+ const char *escape = NULL;
+ apr_size_t escape_len = 0;
+
+ svn_boolean_t match;
+ svn_error_t *err;
+
+ if (pattern_len > SQLITE_MAX_LIKE_PATTERN_LENGTH)
+ {
+ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
+ return;
+ }
+
+ if (argc == 3 && sql_like)
+ {
+ escape = (void*)sqlite3_value_text(argv[2]);
+ escape_len = sqlite3_value_bytes(argv[2]);
+ }
+
+ if (pattern && string)
+ {
+ err = svn_utf__glob(pattern, pattern_len, string, string_len,
+ escape, escape_len, sql_like,
+ &db->sqlext_buf1, &db->sqlext_buf2, &db->sqlext_buf3,
+ &match);
+
+ if (err)
+ {
+ const char *errmsg;
+ svn_membuf__ensure(&db->sqlext_buf1, 512);
+ errmsg = svn_err_best_message(err,
+ db->sqlext_buf1.data,
+ db->sqlext_buf1.size - 1);
+ svn_error_clear(err);
+ sqlite3_result_error(context, errmsg, -1);
+ return;
+ }
+
+ sqlite3_result_int(context, match);
+ }
+}
+
+/* Unicode normalizing implementation of GLOB */
+static void
+glob_ucs_nfd(sqlite3_context *context,
+ int argc, sqlite3_value **argv)
+{
+ glob_like_ucs_nfd_common(context, argc, argv, FALSE);
+}
+
+/* Unicode normalizing implementation of LIKE */
+static void
+like_ucs_nfd(sqlite3_context *context,
+ int argc, sqlite3_value **argv)
+{
+ glob_like_ucs_nfd_common(context, argc, argv, TRUE);
+}
+#endif /* SVN_UNICODE_NORMALIZATION_FIXES */
svn_error_t *
svn_sqlite__open(svn_sqlite__db_t **db, const char *path,
@@ -887,6 +999,28 @@ svn_sqlite__open(svn_sqlite__db_t **db,
SVN_ERR(internal_open(&(*db)->db3, path, mode, scratch_pool));
+#ifdef SVN_UNICODE_NORMALIZATION_FIXES
+ /* Create extension buffers with space for 200 UCS-4 characters. */
+ svn_membuf__create(&(*db)->sqlext_buf1, 800, result_pool);
+ svn_membuf__create(&(*db)->sqlext_buf2, 800, result_pool);
+ svn_membuf__create(&(*db)->sqlext_buf3, 800, result_pool);
+
+ /* Register collation and LIKE and GLOB operator replacements. */
+ SQLITE_ERR(sqlite3_create_collation((*db)->db3,
+ "svn-ucs-nfd", SQLITE_UTF8,
+ *db, collate_ucs_nfd),
+ *db);
+ SQLITE_ERR(sqlite3_create_function((*db)->db3, "glob", 2, SQLITE_UTF8,
+ *db, glob_ucs_nfd, NULL, NULL),
+ *db);
+ SQLITE_ERR(sqlite3_create_function((*db)->db3, "like", 2, SQLITE_UTF8,
+ *db, like_ucs_nfd, NULL, NULL),
+ *db);
+ SQLITE_ERR(sqlite3_create_function((*db)->db3, "like", 3, SQLITE_UTF8,
+ *db, like_ucs_nfd, NULL, NULL),
+ *db);
+#endif /* SVN_UNICODE_NORMALIZATION_FIXES */
+
#ifdef SQLITE3_DEBUG
sqlite3_trace((*db)->db3, sqlite_tracer, (*db)->db3);
#endif
Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite3wrapper.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite3wrapper.c?rev=1481454&r1=1481453&r2=1481454&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite3wrapper.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/sqlite3wrapper.c Sat May 11 23:28:06 2013
@@ -39,6 +39,17 @@
# pragma GCC diagnostic ignored "-Wshorten-64-to-32"
# endif
# endif
+# ifdef __APPLE__
+# include <Availability.h>
+# if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ /* <libkern/OSAtomic.h> is included on OS X by sqlite3.c, and
+ on old systems (Leopard or older), it cannot be compiled
+ with -std=c89 because it uses inline. This is a work-around. */
+# define inline __inline__
+# include <libkern/OSAtomic.h>
+# undef inline
+# endif
+# endif
# include <sqlite3.c>
# if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6))
# pragma GCC diagnostic pop