Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D7474102A0 for ; Tue, 15 Oct 2013 08:54:01 +0000 (UTC) Received: (qmail 82779 invoked by uid 500); 15 Oct 2013 08:53:54 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 82668 invoked by uid 500); 15 Oct 2013 08:53:51 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 82549 invoked by uid 99); 15 Oct 2013 08:53:50 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Oct 2013 08:53:50 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Oct 2013 08:53:38 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id CA9742388C32; Tue, 15 Oct 2013 08:52:43 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1532250 [12/37] - in /subversion/branches/cache-server: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/emacs/ contrib/hook-scripts/ contrib/server-side/fsfsfixer/ contrib/se... Date: Tue, 15 Oct 2013 08:52:18 -0000 To: commits@subversion.apache.org From: stefan2@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131015085243.CA9742388C32@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/cache-server/subversion/libsvn_client/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/mergeinfo.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/mergeinfo.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/mergeinfo.c Tue Oct 15 08:52:06 2013 @@ -24,6 +24,7 @@ #include #include +#include "svn_private_config.h" #include "svn_pools.h" #include "svn_dirent_uri.h" #include "svn_path.h" @@ -46,7 +47,6 @@ #include "private/svn_client_private.h" #include "client.h" #include "mergeinfo.h" -#include "svn_private_config.h" @@ -1021,6 +1021,11 @@ svn_client__elide_mergeinfo(const char * Set *REPOS_ROOT to the root URL of the repository associated with PATH_OR_URL. + If RA_SESSION is NOT NULL and PATH_OR_URL refers to a URL, RA_SESSION + (which must be of the repository containing PATH_OR_URL) will be used + instead of a temporary RA session. Caller is responsible for reparenting + the session if it wants to use it after the call. + Allocate *MERGEINFO_CATALOG and all its contents in RESULT_POOL. Use SCRATCH_POOL for all temporary allocations. @@ -1034,17 +1039,30 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m svn_boolean_t include_descendants, svn_boolean_t ignore_invalid_mergeinfo, svn_client_ctx_t *ctx, + svn_ra_session_t *ra_session, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_ra_session_t *ra_session; const char *local_abspath; svn_boolean_t use_url = svn_path_is_url(path_or_url); svn_client__pathrev_t *peg_loc; - SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc, - path_or_url, NULL, peg_revision, - peg_revision, ctx, scratch_pool)); + if (ra_session && svn_path_is_url(path_or_url)) + { + SVN_ERR(svn_ra_reparent(ra_session, path_or_url, scratch_pool)); + SVN_ERR(svn_client__resolve_rev_and_url(&peg_loc, ra_session, + path_or_url, + peg_revision, + peg_revision, + ctx, scratch_pool)); + } + else + { + SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc, + path_or_url, NULL, + peg_revision, + peg_revision, ctx, scratch_pool)); + } /* If PATH_OR_URL is as working copy path determine if we will need to contact the repository for the requested PEG_REVISION. */ @@ -1064,10 +1082,6 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m } } - /* Check server Merge Tracking capability. */ - SVN_ERR(svn_ra__assert_mergeinfo_capable_server(ra_session, path_or_url, - scratch_pool)); - SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool)); if (use_url) @@ -1391,17 +1405,21 @@ filter_log_entry_with_rangelist(void *ba obviously back. If it was added or replaced it's still around possibly it was replaced one or more times, but it's back now. Regardless, LOG_ENTRY->REVISION is *not* an eligible revision! */ - if (ancestor_is_self /* Explicit mergeinfo on TARGET_PATH_AFFECTED */ + if (nearest_ancestor_mergeinfo && + ancestor_is_self /* Explicit mergeinfo on TARGET_PATH_AFFECTED */ && (change->action != 'M')) { svn_rangelist_t *rangelist = svn_hash_gets(nearest_ancestor_mergeinfo, path); - svn_merge_range_t *youngest_range = APR_ARRAY_IDX( - rangelist, rangelist->nelts - 1, svn_merge_range_t *); + if (rangelist) + { + svn_merge_range_t *youngest_range = APR_ARRAY_IDX( + rangelist, rangelist->nelts - 1, svn_merge_range_t *); - if (youngest_range - && (youngest_range->end > log_entry->revision)) - continue; + if (youngest_range + && (youngest_range->end > log_entry->revision)) + continue; + } } if (nearest_ancestor_mergeinfo) @@ -1496,29 +1514,22 @@ logs_for_mergeinfo_rangelist(const char svn_log_entry_receiver_t log_receiver, void *log_receiver_baton, svn_client_ctx_t *ctx, + svn_ra_session_t *ra_session, apr_pool_t *scratch_pool) { - apr_array_header_t *target; svn_merge_range_t *oldest_range, *youngest_range; - apr_array_header_t *revision_ranges; - svn_opt_revision_t oldest_rev, youngest_rev; + svn_revnum_t oldest_rev, youngest_rev; struct filter_log_entry_baton_t fleb; if (! rangelist->nelts) return SVN_NO_ERROR; - /* Build a single-member log target list using SOURCE_URL. */ - target = apr_array_make(scratch_pool, 1, sizeof(const char *)); - APR_ARRAY_PUSH(target, const char *) = source_url; - /* Calculate and construct the bounds of our log request. */ youngest_range = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1, svn_merge_range_t *); - youngest_rev.kind = svn_opt_revision_number; - youngest_rev.value.number = youngest_range->end; + youngest_rev = youngest_range->end; oldest_range = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *); - oldest_rev.kind = svn_opt_revision_number; - oldest_rev.value.number = oldest_range->start; + oldest_rev = oldest_range->start; if (! target_mergeinfo_catalog) target_mergeinfo_catalog = apr_hash_make(scratch_pool); @@ -1543,19 +1554,29 @@ logs_for_mergeinfo_rangelist(const char fleb.log_receiver_baton = log_receiver_baton; fleb.ctx = ctx; - /* Drive the log. */ - revision_ranges = apr_array_make(scratch_pool, 1, - sizeof(svn_opt_revision_range_t *)); - if (oldest_revs_first) - APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) - = svn_opt__revision_range_create(&oldest_rev, &youngest_rev, scratch_pool); + if (!ra_session) + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, source_url, + NULL, NULL, FALSE, FALSE, ctx, + scratch_pool, scratch_pool)); else - APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) - = svn_opt__revision_range_create(&youngest_rev, &oldest_rev, scratch_pool); - SVN_ERR(svn_client_log5(target, &youngest_rev, revision_ranges, - 0, discover_changed_paths, FALSE, FALSE, revprops, - filter_log_entry_with_rangelist, &fleb, ctx, - scratch_pool)); + SVN_ERR(svn_ra_reparent(ra_session, source_url, scratch_pool)); + + { + apr_array_header_t *target; + target = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(target, const char *) = ""; + + SVN_ERR(svn_ra_get_log2(ra_session, target, + oldest_revs_first ? oldest_rev : youngest_rev, + oldest_revs_first ? youngest_rev : oldest_rev, + 0 /* limit */, + discover_changed_paths, + FALSE /* strict_node_history */, + FALSE /* include_merged_revisions */, + revprops, + filter_log_entry_with_rangelist, &fleb, + scratch_pool)); + } /* Check for cancellation. */ if (ctx->cancel_func) @@ -1616,7 +1637,7 @@ svn_client_mergeinfo_get_merged(apr_hash svn_mergeinfo_t mergeinfo; SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url, - peg_revision, FALSE, FALSE, ctx, pool, pool)); + peg_revision, FALSE, FALSE, ctx, NULL, pool, pool)); if (mergeinfo_cat) { const char *repos_relpath; @@ -1647,11 +1668,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 +1683,16 @@ svn_client_mergeinfo_log2(svn_boolean_t svn_depth_t depth, const apr_array_header_t *revprops, svn_client_ctx_t *ctx, + svn_ra_session_t *ra_session, + 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 +1709,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 +1735,11 @@ 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); + + if (ra_session) + target_session = ra_session; + /* 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 +1747,61 @@ 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; + + if (ra_session && svn_path_is_url(target_path_or_url)) + { + SVN_ERR(svn_ra_reparent(ra_session, target_path_or_url, subpool)); + SVN_ERR(svn_client__resolve_rev_and_url(&pathrev, ra_session, + target_path_or_url, + target_peg_revision, + target_peg_revision, + ctx, subpool)); + target_session = ra_session; + } + else + { + 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, ra_session, 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, ra_session, scratch_pool, scratch_pool)); + } if (!svn_path_is_url(target_path_or_url)) { @@ -1751,6 +1833,7 @@ svn_client_mergeinfo_log2(svn_boolean_t history. */ if (finding_merged) { + svn_pool_destroy(subpool); return SVN_NO_ERROR; } else @@ -1768,18 +1851,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, @@ -1788,21 +1870,38 @@ svn_client_mergeinfo_log2(svn_boolean_t scratch_pool)); } - SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev, - source_path_or_url, NULL, - source_peg_revision, - source_peg_revision, - ctx, sesspool)); + if (target_session + && svn_path_is_url(source_path_or_url) + && repos_root + && svn_uri_skip_ancestor(repos_root, source_path_or_url, subpool)) + { + /* We can re-use the existing session */ + source_session = target_session; + SVN_ERR(svn_ra_reparent(source_session, source_path_or_url, subpool)); + SVN_ERR(svn_client__resolve_rev_and_url(&pathrev, source_session, + source_path_or_url, + source_peg_revision, + source_peg_revision, + ctx, subpool)); + } + else + { + SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev, + source_path_or_url, NULL, + source_peg_revision, + source_peg_revision, + 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), @@ -1811,9 +1910,6 @@ svn_client_mergeinfo_log2(svn_boolean_t scratch_pool)); if (start_rev > end_rev) oldest_revs_first = FALSE; - - /* Close the source and target sessions. */ - svn_pool_destroy(sesspool); } /* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL, @@ -2070,7 +2166,10 @@ svn_client_mergeinfo_log2(svn_boolean_t log_target = svn_path_url_add_component2(repos_root, log_target + 1, scratch_pool); - SVN_ERR(logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths, + { + svn_error_t *err; + + err = logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths, finding_merged, master_inheritable_rangelist, oldest_revs_first, @@ -2081,8 +2180,40 @@ svn_client_mergeinfo_log2(svn_boolean_t discover_changed_paths, revprops, log_receiver, log_receiver_baton, - ctx, scratch_pool)); - return SVN_NO_ERROR; + ctx, target_session, scratch_pool); + + /* Close the source and target sessions. */ + svn_pool_destroy(subpool); /* For SVN_ERR_CEASE_INVOCATION */ + + return svn_error_trace(err); + } +} + +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_error_trace( + 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, NULL, + scratch_pool, scratch_pool)); } svn_error_t * @@ -2120,7 +2251,7 @@ svn_client_suggest_merge_sources(apr_arr /* ### TODO: Share ra_session batons to improve efficiency? */ SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url, - peg_revision, FALSE, FALSE, ctx, pool, pool)); + peg_revision, FALSE, FALSE, ctx, NULL, pool, pool)); if (mergeinfo_cat && apr_hash_count(mergeinfo_cat)) { Modified: subversion/branches/cache-server/subversion/libsvn_client/patch.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/patch.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/patch.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/patch.c Tue Oct 15 08:52:06 2013 @@ -29,6 +29,8 @@ #include #include + +#include "svn_private_config.h" #include "svn_client.h" #include "svn_dirent_uri.h" #include "svn_diff.h" @@ -42,7 +44,6 @@ #include "svn_wc.h" #include "client.h" -#include "svn_private_config.h" #include "private/svn_eol_private.h" #include "private/svn_wc_private.h" #include "private/svn_dep_compat.h" @@ -2676,8 +2677,8 @@ install_patched_prop_targets(patch_targe { if (! dry_run) { - SVN_ERR(svn_io_file_create(target->local_abspath, "", - scratch_pool)); + SVN_ERR(svn_io_file_create_empty(target->local_abspath, + scratch_pool)); SVN_ERR(svn_wc_add_from_disk2(ctx->wc_ctx, target->local_abspath, NULL /*props*/, /* suppress notification */ @@ -2815,10 +2816,13 @@ check_ancestor_delete(const char *delete { struct can_delete_baton_t cb; svn_error_t *err; + apr_array_header_t *ignores; apr_pool_t *iterpool = svn_pool_create(scratch_pool); const char *dir_abspath = svn_dirent_dirname(deleted_target, scratch_pool); + SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, scratch_pool)); + while (svn_dirent_is_child(apply_root, dir_abspath, iterpool)) { svn_pool_clear(iterpool); @@ -2828,7 +2832,7 @@ check_ancestor_delete(const char *delete cb.targets_info = targets_info; err = svn_wc_walk_status(ctx->wc_ctx, dir_abspath, svn_depth_infinity, - TRUE, FALSE, FALSE, NULL, + TRUE, FALSE, FALSE, ignores, can_delete_callback, &cb, ctx->cancel_func, ctx->cancel_baton, iterpool); Modified: subversion/branches/cache-server/subversion/libsvn_client/prop_commands.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/prop_commands.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/prop_commands.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/prop_commands.c Tue Oct 15 08:52:06 2013 @@ -30,6 +30,7 @@ #define APR_WANT_STRFUNC #include +#include "svn_private_config.h" #include "svn_error.h" #include "svn_client.h" #include "client.h" @@ -40,7 +41,6 @@ #include "svn_hash.h" #include "svn_sorts.h" -#include "svn_private_config.h" #include "private/svn_wc_private.h" #include "private/svn_ra_private.h" #include "private/svn_client_private.h" Modified: subversion/branches/cache-server/subversion/libsvn_client/ra.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/ra.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/ra.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/ra.c Tue Oct 15 08:52:06 2013 @@ -25,6 +25,7 @@ #include +#include "svn_private_config.h" #include "svn_error.h" #include "svn_hash.h" #include "svn_pools.h" @@ -39,7 +40,6 @@ #include "client.h" #include "mergeinfo.h" -#include "svn_private_config.h" #include "private/svn_wc_private.h" #include "private/svn_client_private.h" @@ -70,6 +70,8 @@ typedef struct callback_baton_t /* A client context. */ svn_client_ctx_t *ctx; + /* Last progress reported by progress callback. */ + apr_off_t last_progress; } callback_baton_t; @@ -158,7 +160,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++) @@ -287,6 +289,28 @@ get_client_string(void *baton, return SVN_NO_ERROR; } +/* Implements svn_ra_progress_notify_func_t. Accumulates progress information + * for different RA sessions and reports total progress to caller. */ +static void +progress_func(apr_off_t progress, + apr_off_t total, + void *baton, + apr_pool_t *pool) +{ + callback_baton_t *b = baton; + svn_client_ctx_t *ctx = b->ctx; + + ctx->progress += (progress - b->last_progress); + b->last_progress = progress; + + if (ctx->progress_func) + { + /* All RA implementations currently provide -1 for total. So it doesn't + make sense to develop some complex logic to combine total across all + RA sessions. */ + ctx->progress_func(ctx->progress, -1, ctx->progress_baton, pool); + } +} #define SVN_CLIENT__MAX_REDIRECT_ATTEMPTS 3 /* ### TODO: Make configurable. */ @@ -320,12 +344,16 @@ svn_client__open_ra_session_internal(svn cbtable->invalidate_wc_props = (write_dav_props && read_dav_props) ? invalidate_wc_props : NULL; cbtable->auth_baton = ctx->auth_baton; /* new-style */ - cbtable->progress_func = ctx->progress_func; - cbtable->progress_baton = ctx->progress_baton; + cbtable->progress_func = progress_func; + cbtable->progress_baton = cb; cbtable->cancel_func = ctx->cancel_func ? cancel_callback : NULL; cbtable->get_client_string = get_client_string; if (base_dir_abspath) cbtable->get_wc_contents = get_wc_contents; + cbtable->check_tunnel_func = ctx->check_tunnel_func; + cbtable->open_tunnel_func = ctx->open_tunnel_func; + cbtable->close_tunnel_func = ctx->close_tunnel_func; + cbtable->tunnel_baton = ctx->tunnel_baton; cb->commit_items = commit_items; cb->ctx = ctx; @@ -447,39 +475,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 +548,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)); @@ -652,6 +655,9 @@ svn_client__repos_location_segments(apr_ * END_REVNUM must be valid revision numbers except that END_REVNUM may * be SVN_INVALID_REVNUM if END_URL is NULL. * + * YOUNGEST_REV is the already retrieved youngest revision of the ra session, + * but can be SVN_INVALID_REVNUM if the value is not already retrieved. + * * RA_SESSION is an open RA session parented at URL. */ static svn_error_t * @@ -662,6 +668,7 @@ repos_locations(const char **start_url, svn_revnum_t peg_revnum, svn_revnum_t start_revnum, svn_revnum_t end_revnum, + svn_revnum_t youngest_rev, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -669,9 +676,9 @@ repos_locations(const char **start_url, apr_array_header_t *revs; apr_hash_t *rev_locs; - SVN_ERR_ASSERT(peg_revnum != SVN_INVALID_REVNUM); - SVN_ERR_ASSERT(start_revnum != SVN_INVALID_REVNUM); - SVN_ERR_ASSERT(end_revnum != SVN_INVALID_REVNUM || end_url == NULL); + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(peg_revnum)); + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start_revnum)); + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(end_revnum) || end_url == NULL); /* Avoid a network request in the common easy case. */ if (start_revnum == peg_revnum @@ -686,6 +693,27 @@ repos_locations(const char **start_url, SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, scratch_pool)); + /* Handle another common case: The repository root can't move */ + if (! strcmp(repos_url, url)) + { + if (! SVN_IS_VALID_REVNUM(youngest_rev)) + SVN_ERR(svn_ra_get_latest_revnum(ra_session, &youngest_rev, + scratch_pool)); + + if (start_revnum > youngest_rev + || (SVN_IS_VALID_REVNUM(end_revnum) && (end_revnum > youngest_rev))) + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), + (start_revnum > youngest_rev) + ? start_revnum : end_revnum); + + if (start_url) + *start_url = apr_pstrdup(result_pool, repos_url); + if (end_url) + *end_url = apr_pstrdup(result_pool, repos_url); + return SVN_NO_ERROR; + } + revs = apr_array_make(scratch_pool, 2, sizeof(svn_revnum_t)); APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum; if (end_revnum != start_revnum && end_revnum != SVN_INVALID_REVNUM) @@ -741,7 +769,7 @@ svn_client__repos_location(svn_client__p peg_loc->url, scratch_pool)); err = repos_locations(&op_url, NULL, ra_session, peg_loc->url, peg_loc->rev, - op_revnum, SVN_INVALID_REVNUM, + op_revnum, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, result_pool, scratch_pool); SVN_ERR(svn_error_compose_create( err, svn_ra_reparent(ra_session, old_session_url, scratch_pool))); @@ -881,29 +909,26 @@ svn_client__repos_locations(const char * SVN_ERR(repos_locations(start_url, end_url, ra_session, url, peg_revnum, - start_revnum, end_revnum, + start_revnum, end_revnum, youngest_rev, pool, subpool)); svn_pool_destroy(subpool); return SVN_NO_ERROR; } - svn_error_t * -svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p, - const svn_client__pathrev_t *loc1, - const svn_client__pathrev_t *loc2, - svn_ra_session_t *session, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_client__calc_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p, + const svn_client__pathrev_t *loc1, + apr_hash_t *history1, + svn_boolean_t has_rev_zero_history1, + const svn_client__pathrev_t *loc2, + apr_hash_t *history2, + svn_boolean_t has_rev_zero_history2, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_pool_t *sesspool = NULL; - apr_hash_t *history1, *history2; apr_hash_index_t *hi; svn_revnum_t yc_revision = SVN_INVALID_REVNUM; const char *yc_relpath = NULL; - svn_boolean_t has_rev_zero_history1; - svn_boolean_t has_rev_zero_history2; if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0) { @@ -911,32 +936,6 @@ svn_client__get_youngest_common_ancestor return SVN_NO_ERROR; } - /* Open an RA session for the two locations. */ - if (session == NULL) - { - sesspool = svn_pool_create(scratch_pool); - SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx, - sesspool, sesspool)); - } - - /* We're going to cheat and use history-as-mergeinfo because it - saves us a bunch of annoying custom data comparisons and such. */ - SVN_ERR(svn_client__get_history_as_mergeinfo(&history1, - &has_rev_zero_history1, - loc1, - SVN_INVALID_REVNUM, - SVN_INVALID_REVNUM, - session, ctx, scratch_pool)); - SVN_ERR(svn_client__get_history_as_mergeinfo(&history2, - &has_rev_zero_history2, - loc2, - SVN_INVALID_REVNUM, - SVN_INVALID_REVNUM, - session, ctx, scratch_pool)); - /* Close the ra session if we opened one. */ - if (sesspool) - svn_pool_destroy(sesspool); - /* Loop through the first location's history, check for overlapping paths and ranges in the second location's history, and remembering the youngest matching location. */ @@ -990,47 +989,62 @@ svn_client__get_youngest_common_ancestor } svn_error_t * -svn_client__youngest_common_ancestor(const char **ancestor_url, - svn_revnum_t *ancestor_rev, - const char *path_or_url1, - const svn_opt_revision_t *revision1, - const char *path_or_url2, - const svn_opt_revision_t *revision2, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p, + const svn_client__pathrev_t *loc1, + const svn_client__pathrev_t *loc2, + svn_ra_session_t *session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_pool_t *sesspool = svn_pool_create(scratch_pool); - svn_ra_session_t *session; - svn_client__pathrev_t *loc1, *loc2, *ancestor; - - /* Resolve the two locations */ - SVN_ERR(svn_client__ra_session_from_path2(&session, &loc1, - 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__get_youngest_common_ancestor( - &ancestor, loc1, loc2, session, ctx, result_pool, scratch_pool)); + apr_pool_t *sesspool = NULL; + apr_hash_t *history1, *history2; + svn_boolean_t has_rev_zero_history1; + svn_boolean_t has_rev_zero_history2; - if (ancestor) + if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0) { - *ancestor_url = ancestor->url; - *ancestor_rev = ancestor->rev; + *ancestor_p = NULL; + return SVN_NO_ERROR; } - else + + /* Open an RA session for the two locations. */ + if (session == NULL) { - *ancestor_url = NULL; - *ancestor_rev = SVN_INVALID_REVNUM; + sesspool = svn_pool_create(scratch_pool); + SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx, + sesspool, sesspool)); } - svn_pool_destroy(sesspool); + + /* We're going to cheat and use history-as-mergeinfo because it + saves us a bunch of annoying custom data comparisons and such. */ + SVN_ERR(svn_client__get_history_as_mergeinfo(&history1, + &has_rev_zero_history1, + loc1, + SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, + session, ctx, scratch_pool)); + SVN_ERR(svn_client__get_history_as_mergeinfo(&history2, + &has_rev_zero_history2, + loc2, + SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, + session, ctx, scratch_pool)); + /* Close the ra session if we opened one. */ + if (sesspool) + svn_pool_destroy(sesspool); + + SVN_ERR(svn_client__calc_youngest_common_ancestor(ancestor_p, + loc1, history1, + has_rev_zero_history1, + loc2, history2, + has_rev_zero_history2, + result_pool, + scratch_pool)); + return SVN_NO_ERROR; } - struct ra_ev2_baton { /* The working copy context, from the client context. */ svn_wc_context_t *wc_ctx; Modified: subversion/branches/cache-server/subversion/libsvn_client/repos_diff.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/repos_diff.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/repos_diff.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/repos_diff.c Tue Oct 15 08:52:06 2013 @@ -36,6 +36,7 @@ #include #include +#include "svn_private_config.h" #include "svn_checksum.h" #include "svn_hash.h" #include "svn_wc.h" @@ -44,7 +45,6 @@ #include "svn_path.h" #include "svn_io.h" #include "svn_props.h" -#include "svn_private_config.h" #include "client.h" @@ -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, @@ -933,12 +933,12 @@ apply_textdelta(void *file_baton, } /* Open the file to be used as the base for second revision */ - src_stream = svn_stream_lazyopen_create(lazy_open_source, fb, FALSE, + src_stream = svn_stream_lazyopen_create(lazy_open_source, fb, TRUE, scratch_pool); /* Open the file that will become the second revision after applying the text delta, it starts empty */ - result_stream = svn_stream_lazyopen_create(lazy_open_result, fb, FALSE, + result_stream = svn_stream_lazyopen_create(lazy_open_result, fb, TRUE, scratch_pool); svn_txdelta_apply(src_stream, Modified: subversion/branches/cache-server/subversion/libsvn_client/resolved.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/resolved.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/resolved.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/resolved.c Tue Oct 15 08:52:06 2013 @@ -29,6 +29,7 @@ #include +#include "svn_private_config.h" #include "svn_types.h" #include "svn_wc.h" #include "svn_client.h" @@ -40,8 +41,6 @@ #include "svn_sorts.h" #include "client.h" #include "private/svn_wc_private.h" - -#include "svn_private_config.h" /*** Code. ***/ Modified: subversion/branches/cache-server/subversion/libsvn_client/revert.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/revert.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/revert.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/revert.c Tue Oct 15 08:52:06 2013 @@ -27,6 +27,7 @@ /*** Includes. ***/ +#include "svn_private_config.h" #include "svn_path.h" #include "svn_wc.h" #include "svn_client.h" @@ -39,8 +40,6 @@ #include "client.h" #include "private/svn_wc_private.h" -#include "svn_private_config.h" - /*** Code. ***/ Modified: subversion/branches/cache-server/subversion/libsvn_client/status.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/status.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/status.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/status.c Tue Oct 15 08:52:06 2013 @@ -29,6 +29,7 @@ #include #include +#include "svn_private_config.h" #include "svn_pools.h" #include "client.h" @@ -39,7 +40,6 @@ #include "svn_error.h" #include "svn_hash.h" -#include "svn_private_config.h" #include "private/svn_wc_private.h" #include "private/svn_client_private.h" Modified: subversion/branches/cache-server/subversion/libsvn_client/switch.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/switch.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/switch.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/switch.c Tue Oct 15 08:52:06 2013 @@ -27,6 +27,7 @@ /*** Includes. ***/ +#include "svn_private_config.h" #include "svn_client.h" #include "svn_error.h" #include "svn_hash.h" @@ -37,7 +38,6 @@ #include "svn_pools.h" #include "client.h" -#include "svn_private_config.h" #include "private/svn_wc_private.h" @@ -231,8 +231,6 @@ switch_internal(svn_revnum_t *result_rev yca = NULL; /* Not versioned */ else { - /* ### It would be nice if this function could reuse the existing - ra session instead of opening two for its own use. */ SVN_ERR(svn_client__get_youngest_common_ancestor( &yca, switch_loc, target_base_loc, ra_session, ctx, pool, pool)); @@ -241,7 +239,7 @@ switch_internal(svn_revnum_t *result_rev return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, _("'%s' shares no common ancestry with '%s'"), switch_url, - svn_dirent_dirname(local_abspath, pool)); + svn_dirent_local_style(local_abspath, pool)); } wcroot_iprops = apr_hash_make(pool); @@ -340,8 +338,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/cache-server/subversion/libsvn_client/update.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/update.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/update.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/update.c Tue Oct 15 08:52:06 2013 @@ -27,6 +27,7 @@ /*** Includes. ***/ +#include "svn_private_config.h" #include "svn_hash.h" #include "svn_wc.h" #include "svn_client.h" @@ -39,7 +40,6 @@ #include "svn_io.h" #include "client.h" -#include "svn_private_config.h" #include "private/svn_wc_private.h" /* Implements svn_wc_dirents_func_t for update and switch handling. Assumes @@ -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), @@ -701,7 +701,23 @@ svn_client_update4(apr_array_header_t ** cleanup: if (sleep) - svn_io_sleep_for_timestamps((paths->nelts == 1) ? path : NULL, pool); + { + const char *wcroot_abspath; + + if (paths->nelts == 1) + { + const char *abspath; + + /* PATH iteslf may have been removed by the update. */ + SVN_ERR(svn_dirent_get_absolute(&abspath, path, pool)); + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, abspath, + pool, pool)); + } + else + wcroot_abspath = NULL; + + svn_io_sleep_for_timestamps(wcroot_abspath, pool); + } return svn_error_trace(err); } Modified: subversion/branches/cache-server/subversion/libsvn_client/util.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_client/util.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_client/util.c (original) +++ subversion/branches/cache-server/subversion/libsvn_client/util.c Tue Oct 15 08:52:06 2013 @@ -24,6 +24,7 @@ #include #include +#include "svn_private_config.h" #include "svn_hash.h" #include "svn_pools.h" #include "svn_error.h" @@ -40,8 +41,6 @@ #include "client.h" -#include "svn_private_config.h" - svn_client__pathrev_t * svn_client__pathrev_create(const char *repos_root_url, const char *repos_uuid, Modified: subversion/branches/cache-server/subversion/libsvn_delta/compat.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_delta/compat.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_delta/compat.c (original) +++ subversion/branches/cache-server/subversion/libsvn_delta/compat.c Tue Oct 15 08:52:06 2013 @@ -23,6 +23,7 @@ #include +#include "svn_private_config.h" #include "svn_types.h" #include "svn_error.h" #include "svn_delta.h" @@ -33,8 +34,6 @@ #include "svn_props.h" #include "svn_pools.h" -#include "svn_private_config.h" - #include "private/svn_delta_private.h" @@ -218,6 +217,7 @@ locate_change(struct ev2_edit_baton *eb, change = apr_pcalloc(eb->edit_pool, sizeof(*change)); change->changing = SVN_INVALID_REVNUM; change->deleting = SVN_INVALID_REVNUM; + change->kind = svn_node_unknown; svn_hash_sets(eb->changes, relpath, change); @@ -439,8 +439,8 @@ process_actions(struct ev2_edit_baton *e change->changing, NULL, props)); else SVN_ERR(svn_editor_alter_file(eb->editor, repos_relpath, - change->changing, props, - checksum, contents)); + change->changing, + checksum, contents, props)); } return SVN_NO_ERROR; @@ -1182,9 +1182,9 @@ static svn_error_t * alter_file_cb(void *baton, const char *relpath, svn_revnum_t revision, - apr_hash_t *props, const svn_checksum_t *checksum, svn_stream_t *contents, + apr_hash_t *props, apr_pool_t *scratch_pool) { struct editor_baton *eb = baton; @@ -1234,8 +1234,8 @@ static svn_error_t * alter_symlink_cb(void *baton, const char *relpath, svn_revnum_t revision, - apr_hash_t *props, const char *target, + apr_hash_t *props, apr_pool_t *scratch_pool) { /* ### should we verify the kind is truly a symlink? */ @@ -1330,17 +1330,6 @@ move_cb(void *baton, return SVN_NO_ERROR; } -/* This implements svn_editor_cb_rotate_t */ -static svn_error_t * -rotate_cb(void *baton, - const apr_array_header_t *relpaths, - const apr_array_header_t *revisions, - apr_pool_t *scratch_pool) -{ - SVN__NOT_IMPLEMENTED(); -} - - static int count_components(const char *relpath) { @@ -1633,11 +1622,14 @@ apply_change(void **dir_baton, change->copyfrom_path, scratch_pool); else - copyfrom_url = change->copyfrom_path; + { + copyfrom_url = change->copyfrom_path; - /* Make this an FS path by prepending "/" */ - if (copyfrom_url[0] != '/') - copyfrom_url = apr_pstrcat(scratch_pool, "/", copyfrom_url, NULL); + /* Make this an FS path by prepending "/" */ + if (copyfrom_url[0] != '/') + copyfrom_url = apr_pstrcat(scratch_pool, "/", + copyfrom_url, NULL); + } copyfrom_rev = change->copyfrom_rev; } @@ -1885,7 +1877,6 @@ svn_delta__editor_from_delta(svn_editor_ delete_cb, copy_cb, move_cb, - rotate_cb, complete_cb, abort_cb }; Modified: subversion/branches/cache-server/subversion/libsvn_delta/compose_delta.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_delta/compose_delta.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_delta/compose_delta.c (original) +++ subversion/branches/cache-server/subversion/libsvn_delta/compose_delta.c Tue Oct 15 08:52:06 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/cache-server/subversion/libsvn_delta/editor.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_delta/editor.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_delta/editor.c (original) +++ subversion/branches/cache-server/subversion/libsvn_delta/editor.c Tue Oct 15 08:52:06 2013 @@ -391,16 +391,6 @@ svn_editor_setcb_move(svn_editor_t *edit svn_error_t * -svn_editor_setcb_rotate(svn_editor_t *editor, - svn_editor_cb_rotate_t callback, - apr_pool_t *scratch_pool) -{ - editor->funcs.cb_rotate = callback; - return SVN_NO_ERROR; -} - - -svn_error_t * svn_editor_setcb_complete(svn_editor_t *editor, svn_editor_cb_complete_t callback, apr_pool_t *scratch_pool) @@ -437,7 +427,6 @@ svn_editor_setcb_many(svn_editor_t *edit COPY_CALLBACK(cb_delete); COPY_CALLBACK(cb_copy); COPY_CALLBACK(cb_move); - COPY_CALLBACK(cb_rotate); COPY_CALLBACK(cb_complete); COPY_CALLBACK(cb_abort); @@ -683,9 +672,9 @@ svn_error_t * svn_editor_alter_file(svn_editor_t *editor, const char *relpath, svn_revnum_t revision, - apr_hash_t *props, const svn_checksum_t *checksum, - svn_stream_t *contents) + svn_stream_t *contents, + apr_hash_t *props) { svn_error_t *err = SVN_NO_ERROR; @@ -705,8 +694,8 @@ svn_editor_alter_file(svn_editor_t *edit { START_CALLBACK(editor); err = editor->funcs.cb_alter_file(editor->baton, - relpath, revision, props, - checksum, contents, + relpath, revision, + checksum, contents, props, editor->scratch_pool); END_CALLBACK(editor); } @@ -723,8 +712,8 @@ svn_error_t * svn_editor_alter_symlink(svn_editor_t *editor, const char *relpath, svn_revnum_t revision, - apr_hash_t *props, - const char *target) + const char *target, + apr_hash_t *props) { svn_error_t *err = SVN_NO_ERROR; @@ -740,8 +729,8 @@ svn_editor_alter_symlink(svn_editor_t *e { START_CALLBACK(editor); err = editor->funcs.cb_alter_symlink(editor->baton, - relpath, revision, props, - target, + relpath, revision, + target, props, editor->scratch_pool); END_CALLBACK(editor); } @@ -862,56 +851,6 @@ svn_editor_move(svn_editor_t *editor, svn_error_t * -svn_editor_rotate(svn_editor_t *editor, - const apr_array_header_t *relpaths, - const apr_array_header_t *revisions) -{ - svn_error_t *err = SVN_NO_ERROR; - - SHOULD_NOT_BE_FINISHED(editor); -#ifdef ENABLE_ORDERING_CHECK - { - int i; - for (i = 0; i < relpaths->nelts; i++) - { - const char *relpath = APR_ARRAY_IDX(relpaths, i, const char *); - - SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath)); - SHOULD_NOT_BE_COMPLETED(editor, relpath); - VERIFY_PARENT_MAY_EXIST(editor, relpath); - CHILD_DELETIONS_ALLOWED(editor, relpath); - } - } -#endif - - SVN_ERR(check_cancel(editor)); - - if (editor->funcs.cb_rotate) - { - START_CALLBACK(editor); - err = editor->funcs.cb_rotate(editor->baton, relpaths, revisions, - editor->scratch_pool); - END_CALLBACK(editor); - } - -#ifdef ENABLE_ORDERING_CHECK - { - int i; - for (i = 0; i < relpaths->nelts; i++) - { - const char *relpath = APR_ARRAY_IDX(relpaths, i, const char *); - MARK_ALLOW_ALTER(editor, relpath); - MARK_PARENT_STABLE(editor, relpath); - } - } -#endif - - svn_pool_clear(editor->scratch_pool); - return svn_error_trace(err); -} - - -svn_error_t * svn_editor_complete(svn_editor_t *editor) { svn_error_t *err = SVN_NO_ERROR; Modified: subversion/branches/cache-server/subversion/libsvn_delta/svndiff.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_delta/svndiff.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_delta/svndiff.c (original) +++ subversion/branches/cache-server/subversion/libsvn_delta/svndiff.c Tue Oct 15 08:52:06 2013 @@ -29,21 +29,12 @@ #include "delta.h" #include "svn_pools.h" #include "svn_private_config.h" -#include #include "private/svn_error_private.h" #include "private/svn_delta_private.h" - -/* The zlib compressBound function was not exported until 1.2.0. */ -#if ZLIB_VERNUM >= 0x1200 -#define svnCompressBound(LEN) compressBound(LEN) -#else -#define svnCompressBound(LEN) ((LEN) + ((LEN) >> 12) + ((LEN) >> 14) + 11) -#endif - -/* For svndiff1, address/instruction/new data under this size will not - be compressed using zlib as a secondary compressor. */ -#define MIN_COMPRESS_SIZE 512 +#include "private/svn_subr_private.h" +#include "private/svn_string_private.h" +#include "private/svn_dep_compat.h" /* ----- Text delta to svndiff ----- */ @@ -58,139 +49,31 @@ struct encoder_baton { apr_pool_t *pool; }; -/* This is at least as big as the largest size of an integer that - encode_int can generate; it is sufficient for creating buffers for - it to write into. This assumes that integers are at most 64 bits, - and so 10 bytes (with 7 bits of information each) are sufficient to - represent them. */ -#define MAX_ENCODED_INT_LEN 10 /* This is at least as big as the largest size for a single instruction. */ -#define MAX_INSTRUCTION_LEN (2*MAX_ENCODED_INT_LEN+1) +#define MAX_INSTRUCTION_LEN (2*SVN__MAX_ENCODED_UINT_LEN+1) /* This is at least as big as the largest possible instructions section: in theory, the instructions could be SVN_DELTA_WINDOW_SIZE 1-byte copy-from-source instructions (though this is very unlikely). */ #define MAX_INSTRUCTION_SECTION_LEN (SVN_DELTA_WINDOW_SIZE*MAX_INSTRUCTION_LEN) -/* Encode VAL into the buffer P using the variable-length svndiff - integer format. Return the incremented value of P after the - encoded bytes have been written. P must point to a buffer of size - at least MAX_ENCODED_INT_LEN. - - This encoding uses the high bit of each byte as a continuation bit - and the other seven bits as data bits. High-order data bits are - encoded first, followed by lower-order bits, so the value can be - reconstructed by concatenating the data bits from left to right and - interpreting the result as a binary number. Examples (brackets - denote byte boundaries, spaces are for clarity only): - - 1 encodes as [0 0000001] - 33 encodes as [0 0100001] - 129 encodes as [1 0000001] [0 0000001] - 2000 encodes as [1 0001111] [0 1010000] -*/ -static unsigned char * -encode_int(unsigned char *p, svn_filesize_t val) -{ - int n; - svn_filesize_t v; - unsigned char cont; - - SVN_ERR_ASSERT_NO_RETURN(val >= 0); - - /* Figure out how many bytes we'll need. */ - v = val >> 7; - n = 1; - while (v > 0) - { - v = v >> 7; - n++; - } - - SVN_ERR_ASSERT_NO_RETURN(n <= MAX_ENCODED_INT_LEN); - - /* Encode the remaining bytes; n is always the number of bytes - coming after the one we're encoding. */ - while (--n >= 0) - { - cont = ((n > 0) ? 0x1 : 0x0) << 7; - *p++ = (unsigned char)(((val >> (n * 7)) & 0x7f) | cont); - } - - return p; -} - /* Append an encoded integer to a string. */ static void append_encoded_int(svn_stringbuf_t *header, svn_filesize_t val) { - unsigned char buf[MAX_ENCODED_INT_LEN], *p; + unsigned char buf[SVN__MAX_ENCODED_UINT_LEN], *p; - p = encode_int(buf, val); + SVN_ERR_ASSERT_NO_RETURN(val >= 0); + p = svn__encode_uint(buf, (apr_uint64_t)val); svn_stringbuf_appendbytes(header, (const char *)buf, p - buf); } -/* If IN is a string that is >= MIN_COMPRESS_SIZE and the COMPRESSION_LEVEL - is not SVN_DELTA_COMPRESSION_LEVEL_NONE, zlib compress it and places the - result in OUT, with an integer prepended specifying the original size. - If IN is < MIN_COMPRESS_SIZE, or if the compressed version of IN was no - smaller than the original IN, OUT will be a copy of IN with the size - prepended as an integer. */ -static svn_error_t * -zlib_encode(const char *data, - apr_size_t len, - svn_stringbuf_t *out, - int compression_level) -{ - unsigned long endlen; - apr_size_t intlen; - - svn_stringbuf_setempty(out); - append_encoded_int(out, len); - intlen = out->len; - - /* Compression initialization overhead is considered to large for - short buffers. Also, if we don't actually want to compress data, - ZLIB will produce an output no shorter than the input. Hence, - the DATA would directly appended to OUT, so we can do that directly - without calling ZLIB before. */ - if ( (len < MIN_COMPRESS_SIZE) - || (compression_level == SVN_DELTA_COMPRESSION_LEVEL_NONE)) - { - svn_stringbuf_appendbytes(out, data, len); - } - else - { - int zerr; - - svn_stringbuf_ensure(out, svnCompressBound(len) + intlen); - endlen = out->blocksize; - - zerr = compress2((unsigned char *)out->data + intlen, &endlen, - (const unsigned char *)data, len, - compression_level); - if (zerr != Z_OK) - return svn_error_trace(svn_error__wrap_zlib( - zerr, "compress2", - _("Compression of svndiff data failed"))); - - /* Compression didn't help :(, just append the original text */ - if (endlen >= len) - { - svn_stringbuf_appendbytes(out, data, len); - return SVN_NO_ERROR; - } - out->len = endlen + intlen; - out->data[out->len] = 0; - } - return SVN_NO_ERROR; -} - static svn_error_t * send_simple_insertion_window(svn_txdelta_window_t *window, struct encoder_baton *eb) { - unsigned char headers[4 + 5 * MAX_ENCODED_INT_LEN + MAX_INSTRUCTION_LEN]; + unsigned char headers[4 + 5 * SVN__MAX_ENCODED_UINT_LEN + + MAX_INSTRUCTION_LEN]; unsigned char ibuf[MAX_INSTRUCTION_LEN]; unsigned char *header_current; apr_size_t header_len; @@ -226,16 +109,17 @@ send_simple_insertion_window(svn_txdelta else { ibuf[0] = (0x2 << 6); - ip_len = encode_int(ibuf + 1, window->tview_len) - ibuf; + ip_len = svn__encode_uint(ibuf + 1, window->tview_len) - ibuf; } /* encode the window header. Please note that the source window may * have content despite not being used for deltification. */ - header_current = encode_int(header_current, window->sview_offset); - header_current = encode_int(header_current, window->sview_len); - header_current = encode_int(header_current, window->tview_len); + header_current = svn__encode_uint(header_current, + (apr_uint64_t)window->sview_offset); + header_current = svn__encode_uint(header_current, window->sview_len); + header_current = svn__encode_uint(header_current, window->tview_len); header_current[0] = (unsigned char)ip_len; /* 1 instruction */ - header_current = encode_int(&header_current[1], len); + header_current = svn__encode_uint(&header_current[1], len); /* append instructions (1 to a handful of bytes) */ for (i = 0; i < ip_len; ++i) @@ -319,9 +203,9 @@ window_handler(svn_txdelta_window_t *win if (op->length >> 6 == 0) *ip++ |= (unsigned char)op->length; else - ip = encode_int(ip + 1, op->length); + ip = svn__encode_uint(ip + 1, op->length); if (op->action_code != svn_txdelta_new) - ip = encode_int(ip, op->offset); + ip = svn__encode_uint(ip, op->offset); svn_stringbuf_appendbytes(instructions, (const char *)ibuf, ip - ibuf); } @@ -331,20 +215,20 @@ window_handler(svn_txdelta_window_t *win append_encoded_int(header, window->tview_len); if (eb->version == 1) { - SVN_ERR(zlib_encode(instructions->data, instructions->len, - i1, eb->compression_level)); + SVN_ERR(svn__compress(instructions, i1, eb->compression_level)); instructions = i1; } append_encoded_int(header, instructions->len); if (eb->version == 1) { - svn_stringbuf_t *temp = svn_stringbuf_create_empty(pool); - svn_string_t *tempstr = svn_string_create_empty(pool); - SVN_ERR(zlib_encode(window->new_data->data, window->new_data->len, - temp, eb->compression_level)); - tempstr->data = temp->data; - tempstr->len = temp->len; - newdata = tempstr; + svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool); + svn_stringbuf_t *original = svn_stringbuf_create_empty(pool); + original->data = (char *)window->new_data->data; /* won't be modified */ + original->len = window->new_data->len; + original->blocksize = window->new_data->len + 1; + + SVN_ERR(svn__compress(original, compressed, eb->compression_level)); + newdata = svn_stringbuf__morph_into_string(compressed); } else newdata = window->new_data; @@ -453,128 +337,32 @@ struct decode_baton }; -/* Decode an svndiff-encoded integer into *VAL and return a pointer to - the byte after the integer. The bytes to be decoded live in the - range [P..END-1]. If these bytes do not contain a whole encoded - integer, return NULL; in this case *VAL is undefined. - - See the comment for encode_int() earlier in this file for more detail on - the encoding format. */ +/* Wrapper aroung svn__deencode_uint taking a file size as *VAL. */ static const unsigned char * decode_file_offset(svn_filesize_t *val, const unsigned char *p, const unsigned char *end) { - svn_filesize_t temp = 0; - - if (p + MAX_ENCODED_INT_LEN < end) - end = p + MAX_ENCODED_INT_LEN; - /* Decode bytes until we're done. */ - while (p < end) - { - /* Don't use svn_filesize_t here, because this might be 64 bits - * on 32 bit targets. Optimizing compilers may or may not be - * able to reduce that to the effective code below. */ - unsigned int c = *p++; - - temp = (temp << 7) | (c & 0x7f); - if (c < 0x80) - { - *val = temp; - return p; - } - } + apr_uint64_t temp = 0; + const unsigned char *result = svn__decode_uint(&temp, p, end); + *val = (svn_filesize_t)temp; - return NULL; + return result; } - /* Same as above, only decode into a size variable. */ static const unsigned char * decode_size(apr_size_t *val, const unsigned char *p, const unsigned char *end) { - apr_size_t temp = 0; - - if (p + MAX_ENCODED_INT_LEN < end) - end = p + MAX_ENCODED_INT_LEN; - /* Decode bytes until we're done. */ - while (p < end) - { - apr_size_t c = *p++; - - temp = (temp << 7) | (c & 0x7f); - if (c < 0x80) - { - *val = temp; - return p; - } - } - - return NULL; -} - -/* Decode the possibly-zlib compressed string of length INLEN that is in - IN, into OUT. We expect an integer is prepended to IN that specifies - the original size, and that if encoded size == original size, that the - remaining data is not compressed. - In that case, we will simply return pointer into IN as data pointer for - OUT, COPYLESS_ALLOWED has been set. The, the caller is expected not to - modify the contents of OUT. - An error is returned if the decoded length exceeds the given LIMIT. - */ -static svn_error_t * -zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out, - apr_size_t limit) -{ - apr_size_t len; - const unsigned char *oldplace = in; - - /* First thing in the string is the original length. */ - in = decode_size(&len, in, in + inLen); - if (in == NULL) - return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL, - _("Decompression of svndiff data failed: no size")); - if (len > limit) - return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL, - _("Decompression of svndiff data failed: " - "size too large")); - /* We need to subtract the size of the encoded original length off the - * still remaining input length. */ - inLen -= (in - oldplace); - if (inLen == len) - { - svn_stringbuf_ensure(out, len); - memcpy(out->data, in, len); - out->data[len] = 0; - out->len = len; - - return SVN_NO_ERROR; - } - else - { - unsigned long zlen = len; - int zerr; - - svn_stringbuf_ensure(out, len); - zerr = uncompress((unsigned char *)out->data, &zlen, in, inLen); - if (zerr != Z_OK) - return svn_error_trace(svn_error__wrap_zlib( - zerr, "uncompress", - _("Decompression of svndiff data failed"))); - - /* Zlib should not produce something that has a different size than the - original length we stored. */ - if (zlen != len) - return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, - NULL, - _("Size of uncompressed data " - "does not match stored original length")); - out->data[zlen] = 0; - out->len = zlen; - } - return SVN_NO_ERROR; + apr_uint64_t temp = 0; + const unsigned char *result = svn__decode_uint(&temp, p, end); + if (temp > APR_SIZE_MAX) + return NULL; + + *val = (apr_size_t)temp; + return result; } /* Decode an instruction into OP, returning a pointer to the text @@ -695,6 +483,21 @@ count_and_verify_instructions(int *ninst return SVN_NO_ERROR; } +static svn_error_t * +zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out, + apr_size_t limit) +{ + /* construct a fake string buffer as parameter to svn__decompress. + This is fine as that function never writes to it. */ + svn_stringbuf_t compressed; + compressed.pool = NULL; + compressed.data = (char *)in; + compressed.len = inLen; + compressed.blocksize = inLen + 1; + + return svn__decompress(&compressed, out, limit); +} + /* Given the five integer fields of a window header and a pointer to the remainder of the window contents, fill in a delta window structure *WINDOW. New allocations will be performed in POOL; @@ -847,7 +650,7 @@ write_handler(void *baton, if (tview_len > SVN_DELTA_WINDOW_SIZE || sview_len > SVN_DELTA_WINDOW_SIZE || /* for svndiff1, newlen includes the original length */ - newlen > SVN_DELTA_WINDOW_SIZE + MAX_ENCODED_INT_LEN || + newlen > SVN_DELTA_WINDOW_SIZE + SVN__MAX_ENCODED_UINT_LEN || inslen > MAX_INSTRUCTION_SECTION_LEN) return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, _("Svndiff contains a too-large window")); @@ -1029,7 +832,7 @@ read_window_header(svn_stream_t *stream, if (*tview_len > SVN_DELTA_WINDOW_SIZE || *sview_len > SVN_DELTA_WINDOW_SIZE || /* for svndiff1, newlen includes the original length */ - *newlen > SVN_DELTA_WINDOW_SIZE + MAX_ENCODED_INT_LEN || + *newlen > SVN_DELTA_WINDOW_SIZE + SVN__MAX_ENCODED_UINT_LEN || *inslen > MAX_INSTRUCTION_SECTION_LEN) return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, _("Svndiff contains a too-large window")); @@ -1086,18 +889,3 @@ svn_txdelta_skip_svndiff_window(apr_file } -svn_error_t * -svn__compress(svn_string_t *in, - svn_stringbuf_t *out, - int compression_level) -{ - return zlib_encode(in->data, in->len, out, compression_level); -} - -svn_error_t * -svn__decompress(svn_string_t *in, - svn_stringbuf_t *out, - apr_size_t limit) -{ - return zlib_decode((const unsigned char*)in->data, in->len, out, limit); -} Modified: subversion/branches/cache-server/subversion/libsvn_delta/text_delta.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_delta/text_delta.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_delta/text_delta.c (original) +++ subversion/branches/cache-server/subversion/libsvn_delta/text_delta.c Tue Oct 15 08:52:06 2013 @@ -669,7 +669,7 @@ patterning_copy(char *target, const char #if SVN_UNALIGNED_ACCESS_IS_OK - if (end + sizeof(apr_uint32_t) <= target) + if (source + sizeof(apr_uint32_t) <= target) { /* Source and target are at least 4 bytes apart, so we can copy in * 4-byte chunks. */ Modified: subversion/branches/cache-server/subversion/libsvn_delta/xdelta.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_delta/xdelta.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_delta/xdelta.c (original) +++ subversion/branches/cache-server/subversion/libsvn_delta/xdelta.c Tue Oct 15 08:52:06 2013 @@ -27,8 +27,10 @@ #include /* for APR_INLINE */ #include +#include "svn_private_config.h" #include "svn_hash.h" #include "svn_delta.h" +#include "private/svn_string_private.h" #include "delta.h" /* This is pseudo-adler32. It is adler32 without the prime modulus. @@ -223,73 +225,6 @@ init_blocks_table(const char *data, add_block(blocks, init_adler32(data + i), i); } -/* Return the lowest position at which A and B differ. If no difference - * can be found in the first MAX_LEN characters, MAX_LEN will be returned. - */ -static apr_size_t -match_length(const char *a, const char *b, apr_size_t max_len) -{ - apr_size_t pos = 0; - -#if SVN_UNALIGNED_ACCESS_IS_OK - - /* Chunky processing is so much faster ... - * - * We can't make this work on architectures that require aligned access - * because A and B will probably have different alignment. So, skipping - * the first few chars until alignment is reached is not an option. - */ - for (; pos + sizeof(apr_size_t) <= max_len; pos += sizeof(apr_size_t)) - if (*(const apr_size_t*)(a + pos) != *(const apr_size_t*)(b + pos)) - break; - -#endif - - for (; pos < max_len; ++pos) - if (a[pos] != b[pos]) - break; - - return pos; -} - -/* Return the number of bytes before A and B that don't differ. If no - * difference can be found in the first MAX_LEN characters, MAX_LEN will - * be returned. Please note that A-MAX_LEN and B-MAX_LEN must both be - * valid addresses. - */ -static apr_size_t -reverse_match_length(const char *a, const char *b, apr_size_t max_len) -{ - apr_size_t pos = 0; - -#if SVN_UNALIGNED_ACCESS_IS_OK - - /* Chunky processing is so much faster ... - * - * We can't make this work on architectures that require aligned access - * because A and B will probably have different alignment. So, skipping - * the first few chars until alignment is reached is not an option. - */ - for (pos = sizeof(apr_size_t); pos <= max_len; pos += sizeof(apr_size_t)) - if (*(const apr_size_t*)(a - pos) != *(const apr_size_t*)(b - pos)) - break; - - pos -= sizeof(apr_size_t); - -#endif - - /* If we find a mismatch at -pos, pos-1 characters matched. - */ - while (++pos <= max_len) - if (a[0-pos] != b[0-pos]) - return pos - 1; - - /* No mismatch found -> at least MAX_LEN matching chars. - */ - return max_len; -} - - /* Try to find a match for the target data B in BLOCKS, and then extend the match as long as data in A and B at the match position continues to match. We set the position in A we ended up in (in @@ -323,9 +258,9 @@ find_match(const struct blocks *blocks, max_delta = asize - apos - MATCH_BLOCKSIZE < bsize - bpos - MATCH_BLOCKSIZE ? asize - apos - MATCH_BLOCKSIZE : bsize - bpos - MATCH_BLOCKSIZE; - delta = match_length(a + apos + MATCH_BLOCKSIZE, - b + bpos + MATCH_BLOCKSIZE, - max_delta); + delta = svn_cstring__match_length(a + apos + MATCH_BLOCKSIZE, + b + bpos + MATCH_BLOCKSIZE, + max_delta); /* See if we can extend backwards (max MATCH_BLOCKSIZE-1 steps because A's content has been sampled only every MATCH_BLOCKSIZE positions). */ @@ -362,7 +297,8 @@ store_delta_trailer(svn_txdelta__ops_bat if (max_len == 0) return; - end_match = reverse_match_length(a + asize, b + bsize, max_len); + end_match = svn_cstring__reverse_match_length(a + asize, b + bsize, + max_len); if (end_match <= 4) end_match = 0; @@ -414,7 +350,7 @@ compute_delta(svn_txdelta__ops_baton_t * /* Optimization: directly compare window starts. If more than 4 * bytes match, we can immediately create a matching windows. * Shorter sequences result in a net data increase. */ - lo = match_length(a, b, asize > bsize ? bsize : asize); + lo = svn_cstring__match_length(a, b, asize > bsize ? bsize : asize); if ((lo > 4) || (lo == bsize)) { svn_txdelta__insert_op(build_baton, svn_txdelta_source, @@ -468,7 +404,8 @@ compute_delta(svn_txdelta__ops_baton_t * { /* the match borders on the previous op. Maybe, we found a * match that is better than / overlapping the previous one. */ - apr_size_t len = reverse_match_length(a + apos, b + lo, apos < lo ? apos : lo); + apr_size_t len = svn_cstring__reverse_match_length + (a + apos, b + lo, apos < lo ? apos : lo); if (len > 0) { len = svn_txdelta__remove_copy(build_baton, len); Modified: subversion/branches/cache-server/subversion/libsvn_diff/diff_file.c URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_diff/diff_file.c?rev=1532250&r1=1532249&r2=1532250&view=diff ============================================================================== --- subversion/branches/cache-server/subversion/libsvn_diff/diff_file.c (original) +++ subversion/branches/cache-server/subversion/libsvn_diff/diff_file.c Tue Oct 15 08:52:06 2013 @@ -166,26 +166,39 @@ read_chunk(apr_file_t *file, const char static svn_error_t * map_or_read_file(apr_file_t **file, MMAP_T_PARAM(mm) - char **buffer, apr_off_t *size, + char **buffer, apr_size_t *size_p, const char *path, apr_pool_t *pool) { apr_finfo_t finfo; apr_status_t rv; + apr_size_t size; *buffer = NULL; SVN_ERR(svn_io_file_open(file, path, APR_READ, APR_OS_DEFAULT, pool)); SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, *file, pool)); + if (finfo.size > APR_SIZE_MAX) + { + return svn_error_createf(APR_ENOMEM, NULL, + _("File '%s' is too large to be read in " + "to memory"), path); + } + + size = (apr_size_t) finfo.size; #if APR_HAS_MMAP - if (finfo.size > APR_MMAP_THRESHOLD) + if (size > APR_MMAP_THRESHOLD) { - rv = apr_mmap_create(mm, *file, 0, (apr_size_t) finfo.size, - APR_MMAP_READ, pool); + rv = apr_mmap_create(mm, *file, 0, size, APR_MMAP_READ, pool); if (rv == APR_SUCCESS) { *buffer = (*mm)->mm; } + else + { + /* Clear *MM because output parameters are undefined on error. */ + *mm = NULL; + } /* On failure we just fall through and try reading the file into * memory instead. @@ -193,12 +206,11 @@ map_or_read_file(apr_file_t **file, } #endif /* APR_HAS_MMAP */ - if (*buffer == NULL && finfo.size > 0) + if (*buffer == NULL && size > 0) { - *buffer = apr_palloc(pool, (apr_size_t) finfo.size); + *buffer = apr_palloc(pool, size); - SVN_ERR(svn_io_file_read_full2(*file, *buffer, (apr_size_t) finfo.size, - NULL, NULL, pool)); + SVN_ERR(svn_io_file_read_full2(*file, *buffer, size, NULL, NULL, pool)); /* Since we have the entire contents of the file we can * close it now. @@ -208,7 +220,7 @@ map_or_read_file(apr_file_t **file, *file = NULL; } - *size = finfo.size; + *size_p = size; return SVN_NO_ERROR; } @@ -634,7 +646,7 @@ find_identical_suffix(apr_off_t *suffix_ min_curp[0] += suffix_min_offset0; /* Scan quickly by reading with machine-word granularity. */ - for (i = 0, can_read_word = TRUE; i < file_len; i++) + for (i = 0, can_read_word = TRUE; can_read_word && i < file_len; i++) can_read_word = can_read_word && ( (file_for_suffix[i].curp + 1 - sizeof(apr_uintptr_t)) @@ -652,7 +664,7 @@ find_identical_suffix(apr_off_t *suffix_ if (contains_eol(chunk)) break; - for (i = 1, is_match = TRUE; i < file_len; i++) + for (i = 1, is_match = TRUE; is_match && i < file_len; i++) is_match = is_match && ( chunk == *(const apr_uintptr_t *) @@ -957,7 +969,7 @@ datasource_get_next_token(apr_uint32_t * function. When changing things here, make sure the whitespace settings are - applied, or we mught not reach the exact suffix boundary as token + applied, or we might not reach the exact suffix boundary as token boundary. */ SVN_ERR(read_chunk(file->file, file->path, curp, length, @@ -2360,7 +2372,7 @@ svn_diff_file_output_merge2(svn_stream_t for (idx = 0; idx < 3; idx++) { - apr_off_t size; + apr_size_t size; SVN_ERR(map_or_read_file(&file[idx], MMAP_T_ARG(mm[idx])