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 341ACDD89 for ; Thu, 27 Dec 2012 04:04:36 +0000 (UTC) Received: (qmail 93215 invoked by uid 500); 27 Dec 2012 04:04:36 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 92873 invoked by uid 500); 27 Dec 2012 04:04:34 -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 92686 invoked by uid 99); 27 Dec 2012 04:04:32 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Dec 2012 04:04:32 +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; Thu, 27 Dec 2012 04:04:28 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 5401D238899C; Thu, 27 Dec 2012 04:04:08 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1426116 [3/16] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/win32/ contrib/server-side/svncutter/ notes/ subversion/bindings/cxxhl/ subversion/bindings/swig/ subversion/bindings/swig/perl/native/ s... Date: Thu, 27 Dec 2012 04:03:55 -0000 To: commits@subversion.apache.org From: vmpn@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121227040408.5401D238899C@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/javahl-ra/subversion/libsvn_client/client.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/client.h?rev=1426116&r1=1426115&r2=1426116&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/client.h (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/client.h Thu Dec 27 04:03:49 2012 @@ -394,7 +394,6 @@ svn_error_t *svn_client__get_all_auto_pr RESULT_POOL. Use SCRATCH_POOL for temporary allocations. */ svn_error_t *svn_client__get_all_ignores(apr_array_header_t **ignores, const char *local_abspath, - svn_boolean_t no_ignore, svn_client_ctx_t *ctx, apr_pool_t *result_pool, apr_pool_t *scratch_pool); @@ -596,6 +595,58 @@ svn_client__switch_internal(svn_revnum_t /* ---------------------------------------------------------------- */ +/*** List ***/ + +/* List the file/directory entries for PATH_OR_URL at REVISION. + The actual node revision selected is determined by the path as + it exists in PEG_REVISION. + + If DEPTH is svn_depth_infinity, then list all file and directory entries + recursively. Else if DEPTH is svn_depth_files, list all files under + PATH_OR_URL (if any), but not subdirectories. Else if DEPTH is + svn_depth_immediates, list all files and include immediate + subdirectories (at svn_depth_empty). Else if DEPTH is + svn_depth_empty, just list PATH_OR_URL with none of its entries. + + DIRENT_FIELDS controls which fields in the svn_dirent_t's are + filled in. To have them totally filled in use SVN_DIRENT_ALL, + otherwise simply bitwise OR together the combination of SVN_DIRENT_* + fields you care about. + + If FETCH_LOCKS is TRUE, include locks when reporting directory entries. + + If INCLUDE_EXTERNALS is TRUE, also list all external items + reached by recursion. DEPTH value passed to the original list target + applies for the externals also. EXTERNAL_PARENT_URL is url of the + directory which has the externals definitions. EXTERNAL_TARGET is the + target subdirectory of externals definitions. + + Report directory entries by invoking LIST_FUNC/BATON. + Pass EXTERNAL_PARENT_URL and EXTERNAL_TARGET to LIST_FUNC when external + items are listed, otherwise both are set to NULL. + + Use authentication baton cached in CTX to authenticate against the + repository. + + Use POOL for all allocations. +*/ +svn_error_t * +svn_client__list_internal(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_boolean_t fetch_locks, + svn_boolean_t include_externals, + const char *external_parent_url, + const char *external_target, + svn_client_list_func2_t list_func, + void *baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + +/* ---------------------------------------------------------------- */ + /*** Inheritable Properties ***/ /* Fetch the inherited properties for the base of LOCAL_ABSPATH as well @@ -901,6 +952,17 @@ svn_client__condense_commit_items(const apr_pool_t *pool); +/* Like svn_ra_stat() on the ra session root, but with a compatibility + hack for pre-1.2 svnserve that don't support this api. */ +svn_error_t * +svn_client__ra_stat_compatible(svn_ra_session_t *ra_session, + svn_revnum_t rev, + svn_dirent_t **dirent_p, + apr_uint32_t dirent_fields, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool); + + /* Commit the items in the COMMIT_ITEMS array using EDITOR/EDIT_BATON to describe the committed local mods. Prior to this call, COMMIT_ITEMS should have been run through (and BASE_URL generated @@ -1024,6 +1086,22 @@ svn_client__do_external_status(svn_clien void *status_baton, apr_pool_t *pool); + +/* List external items defined on each external in EXTERNALS, a const char * + externals_parent_url(url of the directory which has the externals + definitions) of all externals mapping to the svn_string_t * externals_desc + (externals description text). All other options are the same as those + passed to svn_client_list(). */ +svn_error_t * +svn_client__list_externals(apr_hash_t *externals, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_boolean_t fetch_locks, + svn_client_list_func2_t list_func, + void *baton, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + /* Baton for svn_client__dirent_fetcher */ struct svn_client__dirent_fetcher_baton_t { Modified: subversion/branches/javahl-ra/subversion/libsvn_client/commit.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/commit.c?rev=1426116&r1=1426115&r2=1426116&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/commit.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/commit.c Thu Dec 27 04:03:49 2012 @@ -30,11 +30,8 @@ #include #include #include -#include #include "svn_wc.h" #include "svn_ra.h" -#include "svn_delta.h" -#include "svn_subst.h" #include "svn_client.h" #include "svn_string.h" #include "svn_pools.h" @@ -42,743 +39,14 @@ #include "svn_error_codes.h" #include "svn_dirent_uri.h" #include "svn_path.h" -#include "svn_io.h" -#include "svn_time.h" #include "svn_sorts.h" -#include "svn_props.h" #include "client.h" #include "private/svn_wc_private.h" -#include "private/svn_subr_private.h" #include "private/svn_ra_private.h" -#include "private/svn_magic.h" #include "svn_private_config.h" -/* Import context baton. - - ### TODO: Add the following items to this baton: - /` import editor/baton. `/ - const svn_delta_editor_t *editor; - void *edit_baton; - - /` Client context baton `/ - svn_client_ctx_t `ctx; - - /` Paths (keys) excluded from the import (values ignored) `/ - apr_hash_t *excludes; -*/ -typedef struct import_ctx_t -{ - /* Whether any changes were made to the repository */ - svn_boolean_t repos_changed; - - /* A magic cookie for mime-type detection. */ - svn_magic__cookie_t *magic_cookie; - - /* Collection of all possible configuration file dictated auto-props and - svn:auto-props. A hash mapping const char * file patterns to a - second hash which maps const char * property names to const char * - property values. Properties which don't have a value, e.g. - svn:executable, simply map the property name to an empty string. - May be NULL if autoprops are disabled. */ - apr_hash_t *autoprops; -} import_ctx_t; - - -/* Apply LOCAL_ABSPATH's contents (as a delta against the empty string) to - FILE_BATON in EDITOR. Use POOL for any temporary allocation. - PROPERTIES is the set of node properties set on this file. - - Fill DIGEST with the md5 checksum of the sent file; DIGEST must be - at least APR_MD5_DIGESTSIZE bytes long. */ - -/* ### how does this compare against svn_wc_transmit_text_deltas2() ??? */ - -static svn_error_t * -send_file_contents(const char *local_abspath, - void *file_baton, - const svn_delta_editor_t *editor, - apr_hash_t *properties, - unsigned char *digest, - apr_pool_t *pool) -{ - svn_stream_t *contents; - svn_txdelta_window_handler_t handler; - void *handler_baton; - const svn_string_t *eol_style_val = NULL, *keywords_val = NULL; - svn_boolean_t special = FALSE; - svn_subst_eol_style_t eol_style; - const char *eol; - apr_hash_t *keywords; - - /* If there are properties, look for EOL-style and keywords ones. */ - if (properties) - { - eol_style_val = apr_hash_get(properties, SVN_PROP_EOL_STYLE, - sizeof(SVN_PROP_EOL_STYLE) - 1); - keywords_val = apr_hash_get(properties, SVN_PROP_KEYWORDS, - sizeof(SVN_PROP_KEYWORDS) - 1); - if (apr_hash_get(properties, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING)) - special = TRUE; - } - - /* Get an editor func that wants to consume the delta stream. */ - SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool, - &handler, &handler_baton)); - - if (eol_style_val) - svn_subst_eol_style_from_value(&eol_style, &eol, eol_style_val->data); - else - { - eol = NULL; - eol_style = svn_subst_eol_style_none; - } - - if (keywords_val) - SVN_ERR(svn_subst_build_keywords2(&keywords, keywords_val->data, - APR_STRINGIFY(SVN_INVALID_REVNUM), - "", 0, "", pool)); - else - keywords = NULL; - - if (special) - { - SVN_ERR(svn_subst_read_specialfile(&contents, local_abspath, - pool, pool)); - } - else - { - /* Open the working copy file. */ - SVN_ERR(svn_stream_open_readonly(&contents, local_abspath, pool, pool)); - - /* If we have EOL styles or keywords, then detranslate the file. */ - if (svn_subst_translation_required(eol_style, eol, keywords, - FALSE, TRUE)) - { - if (eol_style == svn_subst_eol_style_unknown) - return svn_error_createf(SVN_ERR_IO_UNKNOWN_EOL, NULL, - _("%s property on '%s' contains " - "unrecognized EOL-style '%s'"), - SVN_PROP_EOL_STYLE, - svn_dirent_local_style(local_abspath, - pool), - eol_style_val->data); - - /* We're importing, so translate files with 'native' eol-style to - * repository-normal form, not to this platform's native EOL. */ - if (eol_style == svn_subst_eol_style_native) - eol = SVN_SUBST_NATIVE_EOL_STR; - - /* Wrap the working copy stream with a filter to detranslate it. */ - contents = svn_subst_stream_translated(contents, - eol, - TRUE /* repair */, - keywords, - FALSE /* expand */, - pool); - } - } - - /* Send the file's contents to the delta-window handler. */ - return svn_error_trace(svn_txdelta_send_stream(contents, handler, - handler_baton, digest, - pool)); -} - - -/* Import file PATH as EDIT_PATH in the repository directory indicated - * by DIR_BATON in EDITOR. - * - * Accumulate file paths and their batons in FILES, which must be - * non-null. (These are used to send postfix textdeltas later). - * - * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON - * for each file. - * - * Use POOL for any temporary allocation. - */ -static svn_error_t * -import_file(const svn_delta_editor_t *editor, - void *dir_baton, - const char *local_abspath, - const char *edit_path, - const svn_io_dirent2_t *dirent, - import_ctx_t *import_ctx, - svn_client_ctx_t *ctx, - apr_pool_t *pool) -{ - void *file_baton; - const char *mimetype = NULL; - unsigned char digest[APR_MD5_DIGESTSIZE]; - const char *text_checksum; - apr_hash_t* properties; - apr_hash_index_t *hi; - - SVN_ERR(svn_path_check_valid(local_abspath, pool)); - - /* Add the file, using the pool from the FILES hash. */ - SVN_ERR(editor->add_file(edit_path, dir_baton, NULL, SVN_INVALID_REVNUM, - pool, &file_baton)); - - /* Remember that the repository was modified */ - import_ctx->repos_changed = TRUE; - - if (! dirent->special) - { - /* add automatic properties */ - SVN_ERR(svn_client__get_paths_auto_props(&properties, &mimetype, - local_abspath, - import_ctx->magic_cookie, - import_ctx->autoprops, - ctx, pool, pool)); - } - else - properties = apr_hash_make(pool); - - if (properties) - { - for (hi = apr_hash_first(pool, properties); hi; hi = apr_hash_next(hi)) - { - const char *pname = svn__apr_hash_index_key(hi); - const svn_string_t *pval = svn__apr_hash_index_val(hi); - - SVN_ERR(editor->change_file_prop(file_baton, pname, pval, pool)); - } - } - - if (ctx->notify_func2) - { - svn_wc_notify_t *notify - = svn_wc_create_notify(local_abspath, svn_wc_notify_commit_added, - pool); - notify->kind = svn_node_file; - notify->mime_type = mimetype; - notify->content_state = notify->prop_state - = svn_wc_notify_state_inapplicable; - notify->lock_state = svn_wc_notify_lock_state_inapplicable; - (*ctx->notify_func2)(ctx->notify_baton2, notify, pool); - } - - /* If this is a special file, we need to set the svn:special - property and create a temporary detranslated version in order to - send to the server. */ - if (dirent->special) - { - apr_hash_set(properties, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING, - svn_string_create(SVN_PROP_BOOLEAN_TRUE, pool)); - SVN_ERR(editor->change_file_prop(file_baton, SVN_PROP_SPECIAL, - apr_hash_get(properties, - SVN_PROP_SPECIAL, - APR_HASH_KEY_STRING), - pool)); - } - - /* Now, transmit the file contents. */ - SVN_ERR(send_file_contents(local_abspath, file_baton, editor, - properties, digest, pool)); - - /* Finally, close the file. */ - text_checksum = - svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool); - - return editor->close_file(file_baton, text_checksum, pool); -} - - -/* Return in CHILDREN a mapping of basenames to dirents for the importable - * children of DIR_ABSPATH. EXCLUDES is a hash of absolute paths to filter - * out. IGNORES and GLOBAL_IGNORES, if non-NULL, are lists of basename - * patterns to filter out. - * FILTER_CALLBACK and FILTER_BATON will be called for each absolute path, - * allowing users to further filter the list of returned entries. - * - * Results are returned in RESULT_POOL; use SCRATCH_POOL for temporary data.*/ -static svn_error_t * -get_filtered_children(apr_hash_t **children, - const char *dir_abspath, - apr_hash_t *excludes, - apr_array_header_t *ignores, - apr_array_header_t *global_ignores, - svn_client_import_filter_func_t filter_callback, - void *filter_baton, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - apr_hash_t *dirents; - apr_hash_index_t *hi; - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - - SVN_ERR(svn_io_get_dirents3(&dirents, dir_abspath, TRUE, result_pool, - scratch_pool)); - - for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi)) - { - const char *base_name = svn__apr_hash_index_key(hi); - const svn_io_dirent2_t *dirent = svn__apr_hash_index_val(hi); - const char *local_abspath; - - svn_pool_clear(iterpool); - - local_abspath = svn_dirent_join(dir_abspath, base_name, iterpool); - - if (svn_wc_is_adm_dir(base_name, iterpool)) - { - /* If someone's trying to import a directory named the same - as our administrative directories, that's probably not - what they wanted to do. If they are importing a file - with that name, something is bound to blow up when they - checkout what they've imported. So, just skip items with - that name. */ - if (ctx->notify_func2) - { - svn_wc_notify_t *notify - = svn_wc_create_notify(svn_dirent_join(local_abspath, base_name, - iterpool), - svn_wc_notify_skip, iterpool); - notify->kind = svn_node_dir; - notify->content_state = notify->prop_state - = svn_wc_notify_state_inapplicable; - notify->lock_state = svn_wc_notify_lock_state_inapplicable; - (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool); - } - - apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL); - continue; - } - /* If this is an excluded path, exclude it. */ - if (apr_hash_get(excludes, local_abspath, APR_HASH_KEY_STRING)) - { - apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL); - continue; - } - - if (ignores && svn_wc_match_ignore_list(base_name, ignores, iterpool)) - { - apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL); - continue; - } - - if (global_ignores && - svn_wc_match_ignore_list(base_name, global_ignores, iterpool)) - { - apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL); - continue; - } - - if (filter_callback) - { - svn_boolean_t filter = FALSE; - - SVN_ERR(filter_callback(filter_baton, &filter, local_abspath, - dirent, iterpool)); - - if (filter) - { - apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL); - continue; - } - } - } - svn_pool_destroy(iterpool); - - *children = dirents; - return SVN_NO_ERROR; -} - -static svn_error_t * -import_dir(const svn_delta_editor_t *editor, - void *dir_baton, - const char *local_abspath, - const char *edit_path, - svn_depth_t depth, - apr_hash_t *excludes, - apr_array_header_t *global_ignores, - svn_boolean_t no_ignore, - svn_boolean_t no_autoprops, - svn_boolean_t ignore_unknown_node_types, - svn_client_import_filter_func_t filter_callback, - void *filter_baton, - import_ctx_t *import_ctx, - svn_client_ctx_t *ctx, - apr_pool_t *pool); - - -/* Import the children of DIR_ABSPATH, with other arguments similar to - * import_dir(). */ -static svn_error_t * -import_children(const char *dir_abspath, - const char *edit_path, - apr_hash_t *dirents, - const svn_delta_editor_t *editor, - void *dir_baton, - svn_depth_t depth, - apr_hash_t *excludes, - apr_array_header_t *global_ignores, - svn_boolean_t no_ignore, - svn_boolean_t no_autoprops, - svn_boolean_t ignore_unknown_node_types, - svn_client_import_filter_func_t filter_callback, - void *filter_baton, - import_ctx_t *import_ctx, - svn_client_ctx_t *ctx, - apr_pool_t *scratch_pool) -{ - apr_array_header_t *sorted_dirents; - int i; - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - - sorted_dirents = svn_sort__hash(dirents, svn_sort_compare_items_lexically, - scratch_pool); - for (i = 0; i < sorted_dirents->nelts; i++) - { - const char *this_abspath, *this_edit_path; - svn_sort__item_t item = APR_ARRAY_IDX(sorted_dirents, i, - svn_sort__item_t); - const char *filename = item.key; - const svn_io_dirent2_t *dirent = item.value; - - svn_pool_clear(iterpool); - - if (ctx->cancel_func) - SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); - - /* Typically, we started importing from ".", in which case - edit_path is "". So below, this_path might become "./blah", - and this_edit_path might become "blah", for example. */ - this_abspath = svn_dirent_join(dir_abspath, filename, iterpool); - this_edit_path = svn_relpath_join(edit_path, filename, iterpool); - - if (dirent->kind == svn_node_dir && depth >= svn_depth_immediates) - { - /* Recurse. */ - svn_depth_t depth_below_here = depth; - if (depth == svn_depth_immediates) - depth_below_here = svn_depth_empty; - - SVN_ERR(import_dir(editor, dir_baton, this_abspath, - this_edit_path, depth_below_here, excludes, - global_ignores, no_ignore, no_autoprops, - ignore_unknown_node_types, filter_callback, - filter_baton, import_ctx, ctx, iterpool)); - } - else if (dirent->kind == svn_node_file && depth >= svn_depth_files) - { - SVN_ERR(import_file(editor, dir_baton, this_abspath, - this_edit_path, dirent, - import_ctx, ctx, iterpool)); - } - else if (dirent->kind != svn_node_dir && dirent->kind != svn_node_file) - { - if (ignore_unknown_node_types) - { - /*## warn about it*/ - if (ctx->notify_func2) - { - svn_wc_notify_t *notify - = svn_wc_create_notify(this_abspath, - svn_wc_notify_skip, iterpool); - notify->kind = svn_node_dir; - notify->content_state = notify->prop_state - = svn_wc_notify_state_inapplicable; - notify->lock_state = svn_wc_notify_lock_state_inapplicable; - (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool); - } - } - else - return svn_error_createf - (SVN_ERR_NODE_UNKNOWN_KIND, NULL, - _("Unknown or unversionable type for '%s'"), - svn_dirent_local_style(this_abspath, iterpool)); - } - } - - svn_pool_destroy(iterpool); - return SVN_NO_ERROR; -} - - -/* Import directory LOCAL_ABSPATH into the repository directory indicated by - * DIR_BATON in EDITOR. EDIT_PATH is the path imported as the root - * directory, so all edits are relative to that. - * - * DEPTH is the depth at this point in the descent (it may be changed - * for recursive calls). - * - * Accumulate file paths and their batons in FILES, which must be - * non-null. (These are used to send postfix textdeltas later). - * - * EXCLUDES is a hash whose keys are absolute paths to exclude from - * the import (values are unused). - * - * GLOBAL_IGNORES is an array of const char * ignore patterns. Any child - * of LOCAL_ABSPATH which matches one or more of the patterns is not imported. - * - * If NO_IGNORE is FALSE, don't import files or directories that match - * ignore patterns. - * - * If FILTER_CALLBACK is not NULL, call it with FILTER_BATON on each to be - * imported node below LOCAL_ABSPATH to allow filtering nodes. - * - * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for each - * directory. - * - * Use POOL for any temporary allocation. */ -static svn_error_t * -import_dir(const svn_delta_editor_t *editor, - void *dir_baton, - const char *local_abspath, - const char *edit_path, - svn_depth_t depth, - apr_hash_t *excludes, - apr_array_header_t *global_ignores, - svn_boolean_t no_ignore, - svn_boolean_t no_autoprops, - svn_boolean_t ignore_unknown_node_types, - svn_client_import_filter_func_t filter_callback, - void *filter_baton, - import_ctx_t *import_ctx, - svn_client_ctx_t *ctx, - apr_pool_t *pool) -{ - apr_hash_t *dirents; - void *this_dir_baton; - - SVN_ERR(svn_path_check_valid(local_abspath, pool)); - SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, NULL, - global_ignores, filter_callback, - filter_baton, ctx, pool, pool)); - - /* Import this directory, but not yet its children. */ - { - /* Add the new subdirectory, getting a descent baton from the editor. */ - SVN_ERR(editor->add_directory(edit_path, dir_baton, NULL, - SVN_INVALID_REVNUM, pool, &this_dir_baton)); - - /* Remember that the repository was modified */ - import_ctx->repos_changed = TRUE; - - /* By notifying before the recursive call below, we display - a directory add before displaying adds underneath the - directory. To do it the other way around, just move this - after the recursive call. */ - if (ctx->notify_func2) - { - svn_wc_notify_t *notify - = svn_wc_create_notify(local_abspath, svn_wc_notify_commit_added, - pool); - notify->kind = svn_node_dir; - notify->content_state = notify->prop_state - = svn_wc_notify_state_inapplicable; - notify->lock_state = svn_wc_notify_lock_state_inapplicable; - (*ctx->notify_func2)(ctx->notify_baton2, notify, pool); - } - } - - /* Now import the children recursively. */ - SVN_ERR(import_children(local_abspath, edit_path, dirents, editor, - this_dir_baton, depth, excludes, global_ignores, - no_ignore, no_autoprops, ignore_unknown_node_types, - filter_callback, filter_baton, - import_ctx, ctx, pool)); - - /* Finally, close the sub-directory. */ - SVN_ERR(editor->close_directory(this_dir_baton, pool)); - - return SVN_NO_ERROR; -} - - -/* Recursively import PATH to a repository using EDITOR and - * EDIT_BATON. PATH can be a file or directory. - * - * DEPTH is the depth at which to import PATH; it behaves as for - * svn_client_import4(). - * - * NEW_ENTRIES is an ordered array of path components that must be - * created in the repository (where the ordering direction is - * parent-to-child). If PATH is a directory, NEW_ENTRIES may be empty - * -- the result is an import which creates as many new entries in the - * top repository target directory as there are importable entries in - * the top of PATH; but if NEW_ENTRIES is not empty, its last item is - * the name of a new subdirectory in the repository to hold the - * import. If PATH is a file, NEW_ENTRIES may not be empty, and its - * last item is the name used for the file in the repository. If - * NEW_ENTRIES contains more than one item, all but the last item are - * the names of intermediate directories that are created before the - * real import begins. NEW_ENTRIES may NOT be NULL. - * - * EXCLUDES is a hash whose keys are absolute paths to exclude from - * the import (values are unused). - * - * AUTOPROPS is hash of all config file autoprops and - * svn:auto-props inherited by the import target, see the - * IMPORT_CTX member of the same name. - * - * LOCAL_IGNORES is an array of const char * ignore patterns which - * correspond to the svn:ignore property (if any) set on the root of the - * repository target and thus dictates which immediate children of that - * target should be ignored and not imported. - * - * GLOBAL_IGNORES is an array of const char * ignore patterns which - * correspond to the svn:global-ignores properties (if any) set on - * the root of the repository target or inherited by it. - * - * If NO_IGNORE is FALSE, don't import files or directories that match - * ignore patterns. - * - * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for - * each imported path, passing actions svn_wc_notify_commit_added. - * - * Use POOL for any temporary allocation. - * - * Note: the repository directory receiving the import was specified - * when the editor was fetched. (I.e, when EDITOR->open_root() is - * called, it returns a directory baton for that directory, which is - * not necessarily the root.) - */ -static svn_error_t * -import(const char *local_abspath, - const apr_array_header_t *new_entries, - const svn_delta_editor_t *editor, - void *edit_baton, - svn_depth_t depth, - apr_hash_t *excludes, - apr_hash_t *autoprops, - apr_array_header_t *local_ignores, - apr_array_header_t *global_ignores, - svn_boolean_t no_ignore, - svn_boolean_t no_autoprops, - svn_boolean_t ignore_unknown_node_types, - svn_client_import_filter_func_t filter_callback, - void *filter_baton, - svn_client_ctx_t *ctx, - apr_pool_t *pool) -{ - void *root_baton; - apr_array_header_t *batons = NULL; - const char *edit_path = ""; - import_ctx_t *import_ctx = apr_pcalloc(pool, sizeof(*import_ctx)); - const svn_io_dirent2_t *dirent; - - import_ctx->autoprops = autoprops; - svn_magic__init(&import_ctx->magic_cookie, pool); - - /* Get a root dir baton. We pass an invalid revnum to open_root - to mean "base this on the youngest revision". Should we have an - SVN_YOUNGEST_REVNUM defined for these purposes? */ - SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, - pool, &root_baton)); - - /* Import a file or a directory tree. */ - SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, FALSE, pool, pool)); - - /* Make the intermediate directory components necessary for properly - rooting our import source tree. */ - if (new_entries->nelts) - { - int i; - - batons = apr_array_make(pool, new_entries->nelts, sizeof(void *)); - for (i = 0; i < new_entries->nelts; i++) - { - const char *component = APR_ARRAY_IDX(new_entries, i, const char *); - edit_path = svn_relpath_join(edit_path, component, pool); - - /* If this is the last path component, and we're importing a - file, then this component is the name of the file, not an - intermediate directory. */ - if ((i == new_entries->nelts - 1) && (dirent->kind == svn_node_file)) - break; - - APR_ARRAY_PUSH(batons, void *) = root_baton; - SVN_ERR(editor->add_directory(edit_path, - root_baton, - NULL, SVN_INVALID_REVNUM, - pool, &root_baton)); - - /* Remember that the repository was modified */ - import_ctx->repos_changed = TRUE; - } - } - else if (dirent->kind == svn_node_file) - { - return svn_error_create - (SVN_ERR_NODE_UNKNOWN_KIND, NULL, - _("New entry name required when importing a file")); - } - - /* Note that there is no need to check whether PATH's basename is - the same name that we reserve for our administrative - subdirectories. It would be strange -- though not illegal -- to - import the contents of a directory of that name, because the - directory's own name is not part of those contents. Of course, - if something underneath it also has our reserved name, then we'll - error. */ - - if (dirent->kind == svn_node_file) - { - /* This code path ignores EXCLUDES and FILTER, but they don't make - much sense for a single file import anyway. */ - svn_boolean_t ignores_match = FALSE; - - if (!no_ignore) - ignores_match = - (svn_wc_match_ignore_list(local_abspath, global_ignores, pool) - || svn_wc_match_ignore_list(local_abspath, local_ignores, pool)); - - if (!ignores_match) - SVN_ERR(import_file(editor, root_baton, local_abspath, edit_path, - dirent, import_ctx, ctx, pool)); - } - else if (dirent->kind == svn_node_dir) - { - apr_hash_t *dirents; - - /* If we are creating a new repository directory path to import to, - then we disregard any svn:ignore property. */ - if (!no_ignore && new_entries->nelts) - local_ignores = NULL; - - SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, - local_ignores, global_ignores, - filter_callback, filter_baton, ctx, - pool, pool)); - - SVN_ERR(import_children(local_abspath, edit_path, dirents, editor, - root_baton, depth, excludes, global_ignores, - no_ignore, no_autoprops, - ignore_unknown_node_types, filter_callback, - filter_baton, import_ctx, ctx, pool)); - - } - else if (dirent->kind == svn_node_none - || dirent->kind == svn_node_unknown) - { - return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL, - _("'%s' does not exist"), - svn_dirent_local_style(local_abspath, pool)); - } - - /* Close up shop; it's time to go home. */ - SVN_ERR(editor->close_directory(root_baton, pool)); - if (batons && batons->nelts) - { - void **baton; - while ((baton = (void **) apr_array_pop(batons))) - { - SVN_ERR(editor->close_directory(*baton, pool)); - } - } - - if (import_ctx->repos_changed) - return editor->close_edit(edit_baton, pool); - else - return editor->abort_edit(edit_baton, pool); -} - - struct capture_baton_t { svn_commit_callback2_t original_callback; void *original_baton; @@ -866,208 +134,6 @@ get_ra_editor(const svn_delta_editor_t * /*** Public Interfaces. ***/ -svn_error_t * -svn_client_import5(const char *path, - const char *url, - svn_depth_t depth, - svn_boolean_t no_ignore, - svn_boolean_t no_autoprops, - svn_boolean_t ignore_unknown_node_types, - const apr_hash_t *revprop_table, - svn_client_import_filter_func_t filter_callback, - void *filter_baton, - svn_commit_callback2_t commit_callback, - void *commit_baton, - svn_client_ctx_t *ctx, - apr_pool_t *scratch_pool) -{ - svn_error_t *err = SVN_NO_ERROR; - const char *log_msg = ""; - const svn_delta_editor_t *editor; - void *edit_baton; - svn_ra_session_t *ra_session; - apr_hash_t *excludes = apr_hash_make(scratch_pool); - svn_node_kind_t kind; - const char *local_abspath; - apr_array_header_t *new_entries = apr_array_make(scratch_pool, 4, - sizeof(const char *)); - const char *temp; - const char *dir; - apr_hash_t *commit_revprops; - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - apr_hash_t *autoprops = NULL; - apr_array_header_t *global_ignores; - apr_hash_t *local_ignores_hash; - apr_array_header_t *local_ignores_arr; - - if (svn_path_is_url(path)) - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - _("'%s' is not a local path"), path); - - SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool)); - - /* Create a new commit item and add it to the array. */ - if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx)) - { - /* If there's a log message gatherer, create a temporary commit - item array solely to help generate the log message. The - array is not used for the import itself. */ - svn_client_commit_item3_t *item; - const char *tmp_file; - apr_array_header_t *commit_items - = apr_array_make(scratch_pool, 1, sizeof(item)); - - item = svn_client_commit_item3_create(scratch_pool); - item->path = apr_pstrdup(scratch_pool, path); - item->state_flags = SVN_CLIENT_COMMIT_ITEM_ADD; - APR_ARRAY_PUSH(commit_items, svn_client_commit_item3_t *) = item; - - SVN_ERR(svn_client__get_log_msg(&log_msg, &tmp_file, commit_items, - ctx, scratch_pool)); - if (! log_msg) - return SVN_NO_ERROR; - if (tmp_file) - { - const char *abs_path; - SVN_ERR(svn_dirent_get_absolute(&abs_path, tmp_file, scratch_pool)); - apr_hash_set(excludes, abs_path, APR_HASH_KEY_STRING, (void *)1); - } - } - - SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool)); - - SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, NULL, - NULL, FALSE, TRUE, ctx, - scratch_pool)); - - /* Figure out all the path components we need to create just to have - a place to stick our imported tree. */ - SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind, - iterpool)); - - /* We can import into directories, but if a file already exists, that's - an error. */ - if (kind == svn_node_file) - return svn_error_createf - (SVN_ERR_ENTRY_EXISTS, NULL, - _("Path '%s' already exists"), url); - - while (kind == svn_node_none) - { - svn_pool_clear(iterpool); - - svn_uri_split(&temp, &dir, url, scratch_pool); - APR_ARRAY_PUSH(new_entries, const char *) = dir; - url = temp; - SVN_ERR(svn_ra_reparent(ra_session, url, iterpool)); - - SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind, - iterpool)); - } - - /* Reverse the order of the components we added to our NEW_ENTRIES array. */ - if (new_entries->nelts) - { - int i, j; - const char *component; - for (i = 0; i < (new_entries->nelts / 2); i++) - { - j = new_entries->nelts - i - 1; - component = - APR_ARRAY_IDX(new_entries, i, const char *); - APR_ARRAY_IDX(new_entries, i, const char *) = - APR_ARRAY_IDX(new_entries, j, const char *); - APR_ARRAY_IDX(new_entries, j, const char *) = - component; - } - } - - /* The repository doesn't know about the reserved administrative - directory. */ - if (new_entries->nelts - /* What's this, what's this? This assignment is here because we - use the value to construct the error message just below. It - may not be aesthetically pleasing, but it's less ugly than - calling APR_ARRAY_IDX twice. */ - && svn_wc_is_adm_dir(temp = APR_ARRAY_IDX(new_entries, - new_entries->nelts - 1, - const char *), - scratch_pool)) - return svn_error_createf - (SVN_ERR_CL_ADM_DIR_RESERVED, NULL, - _("'%s' is a reserved name and cannot be imported"), - svn_dirent_local_style(temp, scratch_pool)); - - SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table, - log_msg, ctx, scratch_pool)); - - /* Fetch RA commit editor. */ - SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session, - svn_client__get_shim_callbacks(ctx->wc_ctx, - NULL, scratch_pool))); - SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton, - commit_revprops, commit_callback, - commit_baton, NULL, TRUE, - scratch_pool)); - - /* Get inherited svn:auto-props, svn:global-ignores, and - svn:ignores for the location we are importing to. */ - if (!no_autoprops) - SVN_ERR(svn_client__get_all_auto_props(&autoprops, url, ctx, - scratch_pool, iterpool)); - if (no_ignore) - { - global_ignores = NULL; - local_ignores_arr = NULL; - } - else - { - svn_opt_revision_t rev; - apr_array_header_t *config_ignores; - - SVN_ERR(svn_client__get_inherited_ignores(&global_ignores, url, ctx, - scratch_pool, iterpool)); - SVN_ERR(svn_wc_get_default_ignores(&config_ignores, ctx->config, - scratch_pool)); - global_ignores = apr_array_append(scratch_pool, global_ignores, - config_ignores); - - rev.kind = svn_opt_revision_head; - SVN_ERR(svn_client_propget5(&local_ignores_hash, NULL, SVN_PROP_IGNORE, url, - &rev, &rev, NULL, svn_depth_empty, NULL, ctx, - scratch_pool, scratch_pool)); - local_ignores_arr = apr_array_make(scratch_pool, 1, sizeof(const char *)); - - if (apr_hash_count(local_ignores_hash)) - { - svn_string_t *propval = apr_hash_get(local_ignores_hash, url, - APR_HASH_KEY_STRING); - if (propval) - { - svn_cstring_split_append(local_ignores_arr, propval->data, - "\n\r\t\v ", FALSE, scratch_pool); - } - } - } - - /* If an error occurred during the commit, abort the edit and return - the error. We don't even care if the abort itself fails. */ - if ((err = import(local_abspath, new_entries, editor, edit_baton, - depth, excludes, autoprops, local_ignores_arr, - global_ignores, no_ignore, no_autoprops, - ignore_unknown_node_types, filter_callback, - filter_baton, ctx, iterpool))) - { - svn_error_clear(editor->abort_edit(edit_baton, iterpool)); - return svn_error_trace(err); - } - - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} - - static svn_error_t * reconcile_errors(svn_error_t *commit_err, svn_error_t *unlock_err, Modified: subversion/branches/javahl-ra/subversion/libsvn_client/copy.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/copy.c?rev=1426116&r1=1426115&r2=1426116&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/copy.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/copy.c Thu Dec 27 04:03:49 2012 @@ -1152,8 +1152,9 @@ repos_to_repos_copy(const apr_array_head if (err) { /* At least try to abort the edit (and fs txn) before throwing err. */ - svn_error_clear(editor->abort_edit(edit_baton, pool)); - return svn_error_trace(err); + return svn_error_compose_create( + err, + editor->abort_edit(edit_baton, pool)); } /* Close the edit. */ Modified: subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c?rev=1426116&r1=1426115&r2=1426116&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c Thu Dec 27 04:03:49 2012 @@ -1282,6 +1282,77 @@ svn_client_export(svn_revnum_t *result_r } /*** From list.c ***/ + +/* Baton for use with wrap_list_func */ +struct list_func_wrapper_baton { + void *list_func1_baton; + svn_client_list_func_t list_func1; +}; + +/* This implements svn_client_list_func2_t */ +static svn_error_t * +list_func_wrapper(void *baton, + const char *path, + const svn_dirent_t *dirent, + const svn_lock_t *lock, + const char *abs_path, + const char *external_parent_url, + const char *external_target, + apr_pool_t *scratch_pool) +{ + struct list_func_wrapper_baton *lfwb = baton; + + if (lfwb->list_func1) + return lfwb->list_func1(lfwb->list_func1_baton, path, dirent, + lock, abs_path, scratch_pool); + + return SVN_NO_ERROR; +} + +/* Helper function for svn_client_list2(). It wraps old format baton + and callback function in list_func_wrapper_baton and + returns new baton and callback to use with svn_client_list3(). */ +static void +wrap_list_func(svn_client_list_func2_t *list_func2, + void **list_func2_baton, + svn_client_list_func_t list_func, + void *baton, + apr_pool_t *result_pool) +{ + struct list_func_wrapper_baton *lfwb = apr_palloc(result_pool, + sizeof(*lfwb)); + + /* Set the user provided old format callback in the baton. */ + lfwb->list_func1_baton = baton; + lfwb->list_func1 = list_func; + + *list_func2_baton = lfwb; + *list_func2 = list_func_wrapper; +} + +svn_error_t * +svn_client_list2(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_boolean_t fetch_locks, + svn_client_list_func_t list_func, + void *baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_client_list_func2_t list_func2; + void *list_func2_baton; + + wrap_list_func(&list_func2, &list_func2_baton, list_func, baton, pool); + + return svn_client_list3(path_or_url, peg_revision, revision, depth, + dirent_fields, fetch_locks, + FALSE /* include externals */, + list_func2, list_func2_baton, ctx, pool); +} + svn_error_t * svn_client_list(const char *path_or_url, const svn_opt_revision_t *peg_revision, Modified: subversion/branches/javahl-ra/subversion/libsvn_client/diff.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/diff.c?rev=1426116&r1=1426115&r2=1426116&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/diff.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/diff.c Thu Dec 27 04:03:49 2012 @@ -52,134 +52,19 @@ #include "client.h" #include "private/svn_wc_private.h" +#include "private/svn_diff_private.h" #include "svn_private_config.h" -/* - * Constant separator strings - */ -static const char equal_string[] = - "==================================================================="; -static const char under_string[] = - "___________________________________________________________________"; - - -/*-----------------------------------------------------------------*/ - /* Utilities */ -/* A helper function for display_prop_diffs. Output the differences between - the mergeinfo stored in ORIG_MERGEINFO_VAL and NEW_MERGEINFO_VAL in a - human-readable form to OUTSTREAM, using ENCODING. Use POOL for temporary - allocations. */ -static svn_error_t * -display_mergeinfo_diff(const char *old_mergeinfo_val, - const char *new_mergeinfo_val, - const char *encoding, - svn_stream_t *outstream, - apr_pool_t *pool) -{ - apr_hash_t *old_mergeinfo_hash, *new_mergeinfo_hash, *added, *deleted; - apr_pool_t *iterpool = svn_pool_create(pool); - apr_hash_index_t *hi; - - if (old_mergeinfo_val) - SVN_ERR(svn_mergeinfo_parse(&old_mergeinfo_hash, old_mergeinfo_val, pool)); - else - old_mergeinfo_hash = NULL; - - if (new_mergeinfo_val) - SVN_ERR(svn_mergeinfo_parse(&new_mergeinfo_hash, new_mergeinfo_val, pool)); - else - new_mergeinfo_hash = NULL; - - SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, old_mergeinfo_hash, - new_mergeinfo_hash, - TRUE, pool, pool)); - - for (hi = apr_hash_first(pool, deleted); - hi; hi = apr_hash_next(hi)) - { - const char *from_path = svn__apr_hash_index_key(hi); - svn_rangelist_t *merge_revarray = svn__apr_hash_index_val(hi); - svn_string_t *merge_revstr; - - svn_pool_clear(iterpool); - SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray, - iterpool)); - - SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool, - _(" Reverse-merged %s:r%s%s"), - from_path, merge_revstr->data, - APR_EOL_STR)); - } - - for (hi = apr_hash_first(pool, added); - hi; hi = apr_hash_next(hi)) - { - const char *from_path = svn__apr_hash_index_key(hi); - svn_rangelist_t *merge_revarray = svn__apr_hash_index_val(hi); - svn_string_t *merge_revstr; - - svn_pool_clear(iterpool); - SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray, - iterpool)); - - SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool, - _(" Merged %s:r%s%s"), - from_path, merge_revstr->data, - APR_EOL_STR)); - } - - svn_pool_destroy(iterpool); - return SVN_NO_ERROR; -} - #define MAKE_ERR_BAD_RELATIVE_PATH(path, relative_to_dir) \ svn_error_createf(SVN_ERR_BAD_RELATIVE_PATH, NULL, \ _("Path '%s' must be an immediate child of " \ "the directory '%s'"), path, relative_to_dir) -/* A helper function used by display_prop_diffs. - TOKEN is a string holding a property value. - If TOKEN is empty, or is already terminated by an EOL marker, - return TOKEN unmodified. Else, return a new string consisting - of the concatenation of TOKEN and the system's default EOL marker. - The new string is allocated from POOL. - If HAD_EOL is not NULL, indicate in *HAD_EOL if the token had a EOL. */ -static const svn_string_t * -maybe_append_eol(const svn_string_t *token, svn_boolean_t *had_eol, - apr_pool_t *pool) -{ - const char *curp; - - if (had_eol) - *had_eol = FALSE; - - if (token->len == 0) - return token; - - curp = token->data + token->len - 1; - if (*curp == '\r') - { - if (had_eol) - *had_eol = TRUE; - return token; - } - else if (*curp != '\n') - { - return svn_string_createf(pool, "%s%s", token->data, APR_EOL_STR); - } - else - { - if (had_eol) - *had_eol = TRUE; - return token; - } -} - /* Adjust PATH to be relative to the repository root beneath ORIG_TARGET, * using RA_SESSION and WC_CTX, and return the result in *ADJUSTED_PATH. * ORIG_TARGET is one of the original targets passed to the diff command, @@ -548,10 +433,8 @@ display_prop_diffs(const apr_array_heade const char *wc_root_abspath, apr_pool_t *pool) { - int i; const char *path1 = orig_path1; const char *path2 = orig_path2; - apr_pool_t *iterpool; if (use_git_diff_format) { @@ -588,8 +471,8 @@ display_prop_diffs(const apr_array_heade SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool, "Index: %s" APR_EOL_STR - "%s" APR_EOL_STR, - path, equal_string)); + SVN_DIFF__EQUAL_STRING APR_EOL_STR, + path)); if (use_git_diff_format) SVN_ERR(print_git_diff_header(outstream, &label1, &label2, @@ -598,11 +481,10 @@ display_prop_diffs(const apr_array_heade SVN_INVALID_REVNUM, encoding, pool)); - SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool, - "--- %s" APR_EOL_STR - "+++ %s" APR_EOL_STR, - label1, - label2)); + /* --- label1 + * +++ label2 */ + SVN_ERR(svn_diff__unidiff_write_header( + outstream, encoding, label1, label2, pool)); } SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool, @@ -612,107 +494,11 @@ display_prop_diffs(const apr_array_heade APR_EOL_STR)); SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, pool, - "%s" APR_EOL_STR, under_string)); + SVN_DIFF__UNDER_STRING APR_EOL_STR)); - iterpool = svn_pool_create(pool); - for (i = 0; i < propchanges->nelts; i++) - { - const char *action; - const svn_string_t *original_value; - const svn_prop_t *propchange = - &APR_ARRAY_IDX(propchanges, i, svn_prop_t); - - if (original_props) - original_value = apr_hash_get(original_props, - propchange->name, APR_HASH_KEY_STRING); - else - original_value = NULL; - - /* If the property doesn't exist on either side, or if it exists - with the same value, skip it. */ - if ((! (original_value || propchange->value)) - || (original_value && propchange->value - && svn_string_compare(original_value, propchange->value))) - continue; - - svn_pool_clear(iterpool); - - if (! original_value) - action = "Added"; - else if (! propchange->value) - action = "Deleted"; - else - action = "Modified"; - SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool, - "%s: %s%s", action, - propchange->name, APR_EOL_STR)); - - if (strcmp(propchange->name, SVN_PROP_MERGEINFO) == 0) - { - const char *orig = original_value ? original_value->data : NULL; - const char *val = propchange->value ? propchange->value->data : NULL; - svn_error_t *err = display_mergeinfo_diff(orig, val, encoding, - outstream, iterpool); - - /* Issue #3896: If we can't pretty-print mergeinfo differences - because invalid mergeinfo is present, then don't let the diff - fail, just print the diff as any other property. */ - if (err && err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) - { - svn_error_clear(err); - } - else - { - SVN_ERR(err); - continue; - } - } - - { - svn_diff_t *diff; - svn_diff_file_options_t options = { 0 }; - const svn_string_t *tmp; - const svn_string_t *orig; - const svn_string_t *val; - svn_boolean_t val_has_eol; - - /* The last character in a property is often not a newline. - An eol character is appended to prevent the diff API to add a - ' \ No newline at end of file' line. We add - ' \ No newline at end of property' manually if needed. */ - tmp = original_value ? original_value - : svn_string_create_empty(iterpool); - orig = maybe_append_eol(tmp, NULL, iterpool); - - tmp = propchange->value ? propchange->value : - svn_string_create_empty(iterpool); - val = maybe_append_eol(tmp, &val_has_eol, iterpool); - - SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, - iterpool)); - - /* UNIX patch will try to apply a diff even if the diff header - * is missing. It tries to be helpful by asking the user for a - * target filename when it can't determine the target filename - * from the diff header. But there usually are no files which - * UNIX patch could apply the property diff to, so we use "##" - * instead of "@@" as the default hunk delimiter for property diffs. - * We also supress the diff header. */ - SVN_ERR(svn_diff_mem_string_output_unified2(outstream, diff, FALSE, - "##", - svn_dirent_local_style(path, - iterpool), - svn_dirent_local_style(path, - iterpool), - encoding, orig, val, iterpool)); - if (!val_has_eol) - { - const char *s = "\\ No newline at end of property" APR_EOL_STR; - SVN_ERR(svn_stream_puts(outstream, s)); - } - } - } - svn_pool_destroy(iterpool); + SVN_ERR(svn_diff__display_prop_diffs( + outstream, encoding, propchanges, original_props, + TRUE /* pretty_print_mergeinfo */, pool)); return SVN_NO_ERROR; } @@ -959,7 +745,9 @@ diff_content_changed(const char *path, /* Print out the diff header. */ SVN_ERR(svn_stream_printf_from_utf8(outstream, diff_cmd_baton->header_encoding, subpool, - "Index: %s" APR_EOL_STR "%s" APR_EOL_STR, path, equal_string)); + "Index: %s" APR_EOL_STR + SVN_DIFF__EQUAL_STRING APR_EOL_STR, + path)); /* ### Print git diff headers. */ @@ -1007,7 +795,9 @@ diff_content_changed(const char *path, /* Print out the diff header. */ SVN_ERR(svn_stream_printf_from_utf8(outstream, diff_cmd_baton->header_encoding, subpool, - "Index: %s" APR_EOL_STR "%s" APR_EOL_STR, path, equal_string)); + "Index: %s" APR_EOL_STR + SVN_DIFF__EQUAL_STRING APR_EOL_STR, + path)); /* ### Do we want to add git diff headers here too? I'd say no. The * ### 'Index' and '===' line is something subversion has added. The rest @@ -1062,8 +852,9 @@ diff_content_changed(const char *path, /* Print out the diff header. */ SVN_ERR(svn_stream_printf_from_utf8(outstream, diff_cmd_baton->header_encoding, subpool, - "Index: %s" APR_EOL_STR "%s" APR_EOL_STR, - path, equal_string)); + "Index: %s" APR_EOL_STR + SVN_DIFF__EQUAL_STRING APR_EOL_STR, + path)); if (diff_cmd_baton->use_git_diff_format) { @@ -1270,8 +1061,9 @@ diff_file_deleted(svn_wc_notify_state_t { SVN_ERR(svn_stream_printf_from_utf8(diff_cmd_baton->outstream, diff_cmd_baton->header_encoding, scratch_pool, - "Index: %s (deleted)" APR_EOL_STR "%s" APR_EOL_STR, - path, equal_string)); + "Index: %s (deleted)" APR_EOL_STR + SVN_DIFF__EQUAL_STRING APR_EOL_STR, + path)); } else { Modified: subversion/branches/javahl-ra/subversion/libsvn_client/export.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/export.c?rev=1426116&r1=1426115&r2=1426116&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/export.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/export.c Thu Dec 27 04:03:49 2012 @@ -43,8 +43,13 @@ #include "svn_private_config.h" #include "private/svn_subr_private.h" +#include "private/svn_delta_private.h" #include "private/svn_wc_private.h" +#ifndef ENABLE_EV2_IMPL +#define ENABLE_EV2_IMPL 0 +#endif + /*** Code. ***/ @@ -677,7 +682,9 @@ window_handler(svn_txdelta_window_t *win if (err) { /* We failed to apply the patch; clean up the temporary file. */ - svn_error_clear(svn_io_remove_file2(hb->tmppath, TRUE, hb->pool)); + err = svn_error_compose_create( + err, + svn_io_remove_file2(hb->tmppath, TRUE, hb->pool)); } return svn_error_trace(err); @@ -857,26 +864,6 @@ close_file(void *file_baton, } static svn_error_t * -fetch_kind_func(svn_kind_t *kind, - void *baton, - const char *path, - svn_revnum_t base_revision, - apr_pool_t *scratch_pool) -{ - /* We know the root of the edit is a directory. */ - if (path[0] == '\0') - *kind = svn_kind_dir; - - /* ### TODO: We could possibly fetch the kind of the object in question - from the server with a second ra_session, but right now this - seems to work. */ - else - *kind = svn_kind_unknown; - - return SVN_NO_ERROR; -} - -static svn_error_t * fetch_props_func(apr_hash_t **props, void *baton, const char *path, @@ -905,6 +892,479 @@ fetch_base_func(const char **filename, return SVN_NO_ERROR; } +static svn_error_t * +get_editor_ev1(const svn_delta_editor_t **export_editor, + void **edit_baton, + struct edit_baton *eb, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_delta_editor_t *editor = svn_delta_default_editor(result_pool); + + editor->set_target_revision = set_target_revision; + editor->open_root = open_root; + editor->add_directory = add_directory; + editor->add_file = add_file; + editor->apply_textdelta = apply_textdelta; + editor->close_file = close_file; + editor->change_file_prop = change_file_prop; + editor->change_dir_prop = change_dir_prop; + + SVN_ERR(svn_delta_get_cancellation_editor(ctx->cancel_func, + ctx->cancel_baton, + editor, + eb, + export_editor, + edit_baton, + result_pool)); + + return SVN_NO_ERROR; +} + + +/*** The Ev2 Implementation ***/ + +static svn_error_t * +add_file_ev2(void *baton, + const char *relpath, + const svn_checksum_t *checksum, + svn_stream_t *contents, + apr_hash_t *props, + svn_revnum_t replaces_rev, + apr_pool_t *scratch_pool) +{ + struct edit_baton *eb = baton; + const char *full_path = svn_dirent_join(eb->root_path, relpath, + scratch_pool); + /* RELPATH is not canonicalized, i.e. it may still contain spaces etc. + * but EB->root_url is. */ + const char *full_url = svn_path_url_add_component2(eb->root_url, + relpath, + scratch_pool); + const svn_string_t *val; + /* The four svn: properties we might actually care about. */ + const svn_string_t *eol_style_val = NULL; + const svn_string_t *keywords_val = NULL; + const svn_string_t *executable_val = NULL; + svn_boolean_t special = FALSE; + /* Any keyword vals to be substituted */ + const char *revision = NULL; + const char *author = NULL; + apr_time_t date = 0; + + /* Look at any properties for additional information. */ + if ( (val = apr_hash_get(props, SVN_PROP_EOL_STYLE, APR_HASH_KEY_STRING)) ) + eol_style_val = val; + + if ( !eb->ignore_keywords && (val = apr_hash_get(props, SVN_PROP_KEYWORDS, + APR_HASH_KEY_STRING)) ) + keywords_val = val; + + if ( (val = apr_hash_get(props, SVN_PROP_EXECUTABLE, APR_HASH_KEY_STRING)) ) + executable_val = val; + + /* Try to fill out the baton's keywords-structure too. */ + if ( (val = apr_hash_get(props, SVN_PROP_ENTRY_COMMITTED_REV, + APR_HASH_KEY_STRING)) ) + revision = val->data; + + if ( (val = apr_hash_get(props, SVN_PROP_ENTRY_COMMITTED_DATE, + APR_HASH_KEY_STRING)) ) + SVN_ERR(svn_time_from_cstring(&date, val->data, scratch_pool)); + + if ( (val = apr_hash_get(props, SVN_PROP_ENTRY_LAST_AUTHOR, + APR_HASH_KEY_STRING)) ) + author = val->data; + + if ( (val = apr_hash_get(props, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING)) ) + special = TRUE; + + if (special) + { + svn_stream_t *tmp_stream; + + SVN_ERR(svn_subst_create_specialfile(&tmp_stream, full_path, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_copy3(contents, tmp_stream, eb->cancel_func, + eb->cancel_baton, scratch_pool)); + } + else + { + svn_stream_t *tmp_stream; + const char *tmppath; + + /* Create a temporary file in the same directory as the file. We're going + to rename the thing into place when we're done. */ + SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmppath, + svn_dirent_dirname(full_path, + scratch_pool), + svn_io_file_del_none, + scratch_pool, scratch_pool)); + + /* Possibly wrap the stream to be translated, as dictated by + the props. */ + if (eol_style_val || keywords_val) + { + svn_subst_eol_style_t style; + const char *eol = NULL; + svn_boolean_t repair = FALSE; + apr_hash_t *final_kw = NULL; + + if (eol_style_val) + { + SVN_ERR(get_eol_style(&style, &eol, eol_style_val->data, + eb->native_eol)); + repair = TRUE; + } + + if (keywords_val) + SVN_ERR(svn_subst_build_keywords2(&final_kw, keywords_val->data, + revision, full_url, date, + author, scratch_pool)); + + /* Writing through a translated stream is more efficient than + reading through one, so we wrap TMP_STREAM and not CONTENTS. */ + tmp_stream = svn_subst_stream_translated(tmp_stream, eol, repair, + final_kw, TRUE, /* expand */ + scratch_pool); + } + + SVN_ERR(svn_stream_copy3(contents, tmp_stream, eb->cancel_func, + eb->cancel_baton, scratch_pool)); + + /* Move the file into place. */ + SVN_ERR(svn_io_file_rename(tmppath, full_path, scratch_pool)); + } + + if (executable_val) + SVN_ERR(svn_io_set_file_executable(full_path, TRUE, FALSE, scratch_pool)); + + if (date && (! special)) + SVN_ERR(svn_io_set_file_affected_time(date, full_path, scratch_pool)); + + if (eb->notify_func) + { + svn_wc_notify_t *notify = svn_wc_create_notify(full_path, + svn_wc_notify_update_add, + scratch_pool); + notify->kind = svn_node_file; + (*eb->notify_func)(eb->notify_baton, notify, scratch_pool); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +add_directory_ev2(void *baton, + const char *relpath, + const apr_array_header_t *children, + apr_hash_t *props, + svn_revnum_t replaces_rev, + apr_pool_t *scratch_pool) +{ + struct edit_baton *eb = baton; + svn_node_kind_t kind; + const char *full_path = svn_dirent_join(eb->root_path, relpath, + scratch_pool); + svn_string_t *val; + + SVN_ERR(svn_io_check_path(full_path, &kind, scratch_pool)); + if (kind == svn_node_none) + SVN_ERR(svn_io_dir_make(full_path, APR_OS_DEFAULT, scratch_pool)); + else if (kind == svn_node_file) + return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, + _("'%s' exists and is not a directory"), + svn_dirent_local_style(full_path, scratch_pool)); + else if (! (kind == svn_node_dir && eb->force)) + return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, + _("'%s' already exists"), + svn_dirent_local_style(full_path, scratch_pool)); + + if ( (val = apr_hash_get(props, SVN_PROP_EXTERNALS, APR_HASH_KEY_STRING)) ) + SVN_ERR(add_externals(eb->externals, full_path, val)); + + if (eb->notify_func) + { + svn_wc_notify_t *notify = svn_wc_create_notify(full_path, + svn_wc_notify_update_add, + scratch_pool); + notify->kind = svn_node_dir; + (*eb->notify_func)(eb->notify_baton, notify, scratch_pool); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +target_revision_func(void *baton, + svn_revnum_t target_revision, + apr_pool_t *scratch_pool) +{ + struct edit_baton *eb = baton; + + *eb->target_revision = target_revision; + + return SVN_NO_ERROR; +} + +static svn_error_t * +get_editor_ev2(const svn_delta_editor_t **export_editor, + void **edit_baton, + struct edit_baton *eb, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_editor_t *editor; + struct svn_delta__extra_baton *exb = apr_pcalloc(result_pool, sizeof(*exb)); + svn_boolean_t *found_abs_paths = apr_palloc(result_pool, + sizeof(*found_abs_paths)); + + exb->baton = eb; + exb->target_revision = target_revision_func; + + SVN_ERR(svn_editor_create(&editor, eb, ctx->cancel_func, ctx->cancel_baton, + result_pool, scratch_pool)); + SVN_ERR(svn_editor_setcb_add_directory(editor, add_directory_ev2, + scratch_pool)); + SVN_ERR(svn_editor_setcb_add_file(editor, add_file_ev2, scratch_pool)); + + *found_abs_paths = TRUE; + + SVN_ERR(svn_delta__delta_from_editor(export_editor, edit_baton, + editor, NULL, NULL, found_abs_paths, + NULL, NULL, + fetch_props_func, eb, + fetch_base_func, eb, + exb, result_pool)); + + /* Create the root of the export. */ + SVN_ERR(open_root_internal(eb->root_path, eb->force, eb->notify_func, + eb->notify_baton, scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +export_file_ev2(const char *from_path_or_url, + const char *to_path, + struct edit_baton *eb, + svn_client__pathrev_t *loc, + svn_ra_session_t *ra_session, + svn_boolean_t overwrite, + apr_pool_t *scratch_pool) +{ + svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url); + apr_hash_t *props; + svn_stream_t *tmp_stream; + svn_node_kind_t to_kind; + + if (svn_path_is_empty(to_path)) + { + if (from_is_url) + to_path = svn_uri_basename(from_path_or_url, scratch_pool); + else + to_path = svn_dirent_basename(from_path_or_url, NULL); + eb->root_path = to_path; + } + else + { + SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, + from_is_url, scratch_pool)); + eb->root_path = to_path; + } + + SVN_ERR(svn_io_check_path(to_path, &to_kind, scratch_pool)); + + if ((to_kind == svn_node_file || to_kind == svn_node_unknown) && + ! overwrite) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("Destination file '%s' exists, and " + "will not be overwritten unless forced"), + svn_dirent_local_style(to_path, scratch_pool)); + else if (to_kind == svn_node_dir) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("Destination '%s' exists. Cannot " + "overwrite directory with non-directory"), + svn_dirent_local_style(to_path, scratch_pool)); + + tmp_stream = svn_stream_buffered(scratch_pool); + + SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, + tmp_stream, NULL, &props, scratch_pool)); + + /* Since you cannot actually root an editor at a file, we manually drive + * a function of our editor. */ + SVN_ERR(add_file_ev2(eb, "", NULL, tmp_stream, props, SVN_INVALID_REVNUM, + scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +export_file(const char *from_path_or_url, + const char *to_path, + struct edit_baton *eb, + svn_client__pathrev_t *loc, + svn_ra_session_t *ra_session, + svn_boolean_t overwrite, + apr_pool_t *scratch_pool) +{ + apr_hash_t *props; + apr_hash_index_t *hi; + struct file_baton *fb = apr_pcalloc(scratch_pool, sizeof(*fb)); + svn_node_kind_t to_kind; + svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url); + + if (svn_path_is_empty(to_path)) + { + if (from_is_url) + to_path = svn_uri_basename(from_path_or_url, scratch_pool); + else + to_path = svn_dirent_basename(from_path_or_url, NULL); + eb->root_path = to_path; + } + else + { + SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, + from_is_url, scratch_pool)); + eb->root_path = to_path; + } + + SVN_ERR(svn_io_check_path(to_path, &to_kind, scratch_pool)); + + if ((to_kind == svn_node_file || to_kind == svn_node_unknown) && + ! overwrite) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("Destination file '%s' exists, and " + "will not be overwritten unless forced"), + svn_dirent_local_style(to_path, scratch_pool)); + else if (to_kind == svn_node_dir) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("Destination '%s' exists. Cannot " + "overwrite directory with non-directory"), + svn_dirent_local_style(to_path, scratch_pool)); + + /* Since you cannot actually root an editor at a file, we + * manually drive a few functions of our editor. */ + + /* This is the equivalent of a parentless add_file(). */ + fb->edit_baton = eb; + fb->path = eb->root_path; + fb->url = eb->root_url; + fb->pool = scratch_pool; + + /* Copied from apply_textdelta(). */ + SVN_ERR(svn_stream_open_unique(&fb->tmp_stream, &fb->tmppath, + svn_dirent_dirname(fb->path, scratch_pool), + svn_io_file_del_none, + fb->pool, fb->pool)); + + /* Step outside the editor-likeness for a moment, to actually talk + * to the repository. */ + /* ### note: the stream will not be closed */ + SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, + fb->tmp_stream, + NULL, &props, scratch_pool)); + + /* Push the props into change_file_prop(), to update the file_baton + * with information. */ + for (hi = apr_hash_first(scratch_pool, props); hi; hi = apr_hash_next(hi)) + { + const char *propname = svn__apr_hash_index_key(hi); + const svn_string_t *propval = svn__apr_hash_index_val(hi); + + SVN_ERR(change_file_prop(fb, propname, propval, scratch_pool)); + } + + /* And now just use close_file() to do all the keyword and EOL + * work, and put the file into place. */ + SVN_ERR(close_file(fb, NULL, scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +export_directory(const char *from_path_or_url, + const char *to_path, + struct edit_baton *eb, + svn_client__pathrev_t *loc, + svn_ra_session_t *ra_session, + svn_boolean_t overwrite, + svn_boolean_t ignore_externals, + svn_boolean_t ignore_keywords, + svn_depth_t depth, + const char *native_eol, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + void *edit_baton; + const svn_delta_editor_t *export_editor; + const svn_ra_reporter3_t *reporter; + void *report_baton; + svn_boolean_t use_sleep = FALSE; + svn_node_kind_t kind; + + if (!ENABLE_EV2_IMPL) + SVN_ERR(get_editor_ev1(&export_editor, &edit_baton, eb, ctx, + scratch_pool, scratch_pool)); + else + SVN_ERR(get_editor_ev2(&export_editor, &edit_baton, eb, ctx, + scratch_pool, scratch_pool)); + + /* Manufacture a basic 'report' to the update reporter. */ + SVN_ERR(svn_ra_do_update2(ra_session, + &reporter, &report_baton, + loc->rev, + "", /* no sub-target */ + depth, + FALSE, /* don't want copyfrom-args */ + export_editor, edit_baton, scratch_pool)); + + SVN_ERR(reporter->set_path(report_baton, "", loc->rev, + /* Depth is irrelevant, as we're + passing start_empty=TRUE anyway. */ + svn_depth_infinity, + TRUE, /* "help, my dir is empty!" */ + NULL, scratch_pool)); + + SVN_ERR(reporter->finish_report(report_baton, scratch_pool)); + + /* Special case: Due to our sly export/checkout method of updating an + * empty directory, no target will have been created if the exported + * item is itself an empty directory (export_editor->open_root never + * gets called, because there are no "changes" to make to the empty + * dir we reported to the repository). + * + * So we just create the empty dir manually; but we do it via + * open_root_internal(), in order to get proper notification. + */ + SVN_ERR(svn_io_check_path(to_path, &kind, scratch_pool)); + if (kind == svn_node_none) + SVN_ERR(open_root_internal + (to_path, overwrite, ctx->notify_func2, + ctx->notify_baton2, scratch_pool)); + + if (! ignore_externals && depth == svn_depth_infinity) + { + const char *repos_root_url; + const char *to_abspath; + + SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, + scratch_pool)); + SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, scratch_pool)); + SVN_ERR(svn_client__export_externals(eb->externals, + from_path_or_url, + to_abspath, repos_root_url, + depth, native_eol, + ignore_keywords, &use_sleep, + ctx, scratch_pool)); + } + + return SVN_NO_ERROR; +} + /*** Public Interfaces ***/ @@ -966,162 +1426,19 @@ svn_client_export5(svn_revnum_t *result_ if (kind == svn_node_file) { - apr_hash_t *props; - apr_hash_index_t *hi; - struct file_baton *fb = apr_pcalloc(pool, sizeof(*fb)); - svn_node_kind_t to_kind; - - if (svn_path_is_empty(to_path)) - { - if (from_is_url) - to_path = svn_uri_basename(from_path_or_url, pool); - else - to_path = svn_dirent_basename(from_path_or_url, NULL); - eb->root_path = to_path; - } + if (!ENABLE_EV2_IMPL) + SVN_ERR(export_file(from_path_or_url, to_path, eb, loc, ra_session, + overwrite, pool)); else - { - SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, - from_is_url, pool)); - eb->root_path = to_path; - } - - SVN_ERR(svn_io_check_path(to_path, &to_kind, pool)); - - if ((to_kind == svn_node_file || to_kind == svn_node_unknown) && - ! overwrite) - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - _("Destination file '%s' exists, and " - "will not be overwritten unless forced"), - svn_dirent_local_style(to_path, pool)); - else if (to_kind == svn_node_dir) - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - _("Destination '%s' exists. Cannot " - "overwrite directory with non-directory"), - svn_dirent_local_style(to_path, pool)); - - /* Since you cannot actually root an editor at a file, we - * manually drive a few functions of our editor. */ - - /* This is the equivalent of a parentless add_file(). */ - fb->edit_baton = eb; - fb->path = eb->root_path; - fb->url = eb->root_url; - fb->pool = pool; - - /* Copied from apply_textdelta(). */ - SVN_ERR(svn_stream_open_unique(&fb->tmp_stream, &fb->tmppath, - svn_dirent_dirname(fb->path, pool), - svn_io_file_del_none, - fb->pool, fb->pool)); - - /* Step outside the editor-likeness for a moment, to actually talk - * to the repository. */ - /* ### note: the stream will not be closed */ - SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, - fb->tmp_stream, - NULL, &props, pool)); - - /* Push the props into change_file_prop(), to update the file_baton - * with information. */ - for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi)) - { - const char *propname = svn__apr_hash_index_key(hi); - const svn_string_t *propval = svn__apr_hash_index_val(hi); - - SVN_ERR(change_file_prop(fb, propname, propval, pool)); - } - - /* And now just use close_file() to do all the keyword and EOL - * work, and put the file into place. */ - SVN_ERR(close_file(fb, NULL, pool)); + SVN_ERR(export_file_ev2(from_path_or_url, to_path, eb, loc, + ra_session, overwrite, pool)); } else if (kind == svn_node_dir) { - void *edit_baton; - const svn_delta_editor_t *export_editor; - const svn_ra_reporter3_t *reporter; - void *report_baton; - svn_delta_editor_t *editor = svn_delta_default_editor(pool); - svn_boolean_t use_sleep = FALSE; - svn_delta_shim_callbacks_t *shim_callbacks = - svn_delta_shim_callbacks_default(pool); - - editor->set_target_revision = set_target_revision; - editor->open_root = open_root; - editor->add_directory = add_directory; - editor->add_file = add_file; - editor->apply_textdelta = apply_textdelta; - editor->close_file = close_file; - editor->change_file_prop = change_file_prop; - editor->change_dir_prop = change_dir_prop; - - SVN_ERR(svn_delta_get_cancellation_editor(ctx->cancel_func, - ctx->cancel_baton, - editor, - eb, - &export_editor, - &edit_baton, - pool)); - - shim_callbacks->fetch_kind_func = fetch_kind_func; - shim_callbacks->fetch_props_func = fetch_props_func; - shim_callbacks->fetch_base_func = fetch_base_func; - shim_callbacks->fetch_baton = eb; - - SVN_ERR(svn_editor__insert_shims(&export_editor, &edit_baton, - export_editor, edit_baton, - NULL, NULL, shim_callbacks, - pool, pool)); - - /* Manufacture a basic 'report' to the update reporter. */ - SVN_ERR(svn_ra_do_update2(ra_session, - &reporter, &report_baton, - loc->rev, - "", /* no sub-target */ - depth, - FALSE, /* don't want copyfrom-args */ - export_editor, edit_baton, pool)); - - SVN_ERR(reporter->set_path(report_baton, "", loc->rev, - /* Depth is irrelevant, as we're - passing start_empty=TRUE anyway. */ - svn_depth_infinity, - TRUE, /* "help, my dir is empty!" */ - NULL, pool)); - - SVN_ERR(reporter->finish_report(report_baton, pool)); - - /* Special case: Due to our sly export/checkout method of - * updating an empty directory, no target will have been created - * if the exported item is itself an empty directory - * (export_editor->open_root never gets called, because there - * are no "changes" to make to the empty dir we reported to the - * repository). - * - * So we just create the empty dir manually; but we do it via - * open_root_internal(), in order to get proper notification. - */ - SVN_ERR(svn_io_check_path(to_path, &kind, pool)); - if (kind == svn_node_none) - SVN_ERR(open_root_internal - (to_path, overwrite, ctx->notify_func2, - ctx->notify_baton2, pool)); - - if (! ignore_externals && depth == svn_depth_infinity) - { - const char *repos_root_url; - const char *to_abspath; - - SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool)); - SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, pool)); - SVN_ERR(svn_client__export_externals(eb->externals, - from_path_or_url, - to_abspath, repos_root_url, - depth, native_eol, - ignore_keywords, &use_sleep, - ctx, pool)); - } + SVN_ERR(export_directory(from_path_or_url, to_path, + eb, loc, ra_session, overwrite, + ignore_externals, ignore_keywords, depth, + native_eol, ctx, pool)); } else if (kind == svn_node_none) {