diff options
Diffstat (limited to 'subversion/libsvn_client/deprecated.c')
-rw-r--r-- | subversion/libsvn_client/deprecated.c | 2966 |
1 files changed, 2966 insertions, 0 deletions
diff --git a/subversion/libsvn_client/deprecated.c b/subversion/libsvn_client/deprecated.c new file mode 100644 index 0000000..a67a69b --- /dev/null +++ b/subversion/libsvn_client/deprecated.c @@ -0,0 +1,2966 @@ +/* + * deprecated.c: holding file for all deprecated APIs. + * "we can't lose 'em, but we can shun 'em!" + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +/* ==================================================================== */ + + + +/*** Includes. ***/ + +/* We define this here to remove any further warnings about the usage of + deprecated functions in this file. */ +#define SVN_DEPRECATED + +#include <string.h> +#include "svn_client.h" +#include "svn_path.h" +#include "svn_compat.h" +#include "svn_hash.h" +#include "svn_props.h" +#include "svn_utf.h" +#include "svn_string.h" +#include "svn_pools.h" + +#include "client.h" +#include "mergeinfo.h" + +#include "private/svn_opt_private.h" +#include "private/svn_wc_private.h" +#include "svn_private_config.h" + + + + +/*** Code. ***/ + + +/* Baton for capture_commit_info() */ +struct capture_baton_t { + svn_commit_info_t **info; + apr_pool_t *pool; +}; + + +/* Callback which implements svn_commit_callback2_t for use with some + backward compat functions. */ +static svn_error_t * +capture_commit_info(const svn_commit_info_t *commit_info, + void *baton, + apr_pool_t *pool) +{ + struct capture_baton_t *cb = baton; + + *(cb->info) = svn_commit_info_dup(commit_info, cb->pool); + + return SVN_NO_ERROR; +} + + +/*** From add.c ***/ +svn_error_t * +svn_client_add4(const char *path, + svn_depth_t depth, + svn_boolean_t force, + svn_boolean_t no_ignore, + svn_boolean_t add_parents, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_add5(path, depth, force, no_ignore, FALSE, add_parents, + ctx, pool); +} + +svn_error_t * +svn_client_add3(const char *path, + svn_boolean_t recursive, + svn_boolean_t force, + svn_boolean_t no_ignore, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_add4(path, SVN_DEPTH_INFINITY_OR_EMPTY(recursive), + force, no_ignore, FALSE, ctx, + pool); +} + +svn_error_t * +svn_client_add2(const char *path, + svn_boolean_t recursive, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_add3(path, recursive, force, FALSE, ctx, pool); +} + +svn_error_t * +svn_client_add(const char *path, + svn_boolean_t recursive, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_add3(path, recursive, FALSE, FALSE, ctx, pool); +} + +svn_error_t * +svn_client_mkdir3(svn_commit_info_t **commit_info_p, + const apr_array_header_t *paths, + svn_boolean_t make_parents, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct capture_baton_t cb; + + cb.info = commit_info_p; + cb.pool = pool; + + return svn_client_mkdir4(paths, make_parents, revprop_table, + capture_commit_info, &cb, ctx, pool); +} + +svn_error_t * +svn_client_mkdir2(svn_commit_info_t **commit_info_p, + const apr_array_header_t *paths, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_mkdir3(commit_info_p, paths, FALSE, NULL, ctx, pool); +} + + +svn_error_t * +svn_client_mkdir(svn_client_commit_info_t **commit_info_p, + const apr_array_header_t *paths, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_commit_info_t *commit_info = NULL; + svn_error_t *err; + + err = svn_client_mkdir2(&commit_info, paths, ctx, pool); + /* These structs have the same layout for the common fields. */ + *commit_info_p = (svn_client_commit_info_t *) commit_info; + return svn_error_trace(err); +} + +/*** From blame.c ***/ + +struct blame_receiver_wrapper_baton2 { + void *baton; + svn_client_blame_receiver2_t receiver; +}; + +static svn_error_t * +blame_wrapper_receiver2(void *baton, + svn_revnum_t start_revnum, + svn_revnum_t end_revnum, + apr_int64_t line_no, + svn_revnum_t revision, + apr_hash_t *rev_props, + svn_revnum_t merged_revision, + apr_hash_t *merged_rev_props, + const char *merged_path, + const char *line, + svn_boolean_t local_change, + apr_pool_t *pool) +{ + struct blame_receiver_wrapper_baton2 *brwb = baton; + const char *author = NULL; + const char *date = NULL; + const char *merged_author = NULL; + const char *merged_date = NULL; + + if (rev_props != NULL) + { + author = svn_prop_get_value(rev_props, SVN_PROP_REVISION_AUTHOR); + date = svn_prop_get_value(rev_props, SVN_PROP_REVISION_DATE); + } + if (merged_rev_props != NULL) + { + merged_author = svn_prop_get_value(merged_rev_props, + SVN_PROP_REVISION_AUTHOR); + merged_date = svn_prop_get_value(merged_rev_props, + SVN_PROP_REVISION_DATE); + } + + if (brwb->receiver) + return brwb->receiver(brwb->baton, line_no, revision, author, date, + merged_revision, merged_author, merged_date, + merged_path, line, pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_blame4(const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + const svn_diff_file_options_t *diff_options, + svn_boolean_t ignore_mime_type, + svn_boolean_t include_merged_revisions, + svn_client_blame_receiver2_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct blame_receiver_wrapper_baton2 baton; + + baton.receiver = receiver; + baton.baton = receiver_baton; + + return svn_client_blame5(target, peg_revision, start, end, diff_options, + ignore_mime_type, include_merged_revisions, + blame_wrapper_receiver2, &baton, ctx, pool); +} + + +/* Baton for use with wrap_blame_receiver */ +struct blame_receiver_wrapper_baton { + void *baton; + svn_client_blame_receiver_t receiver; +}; + +/* This implements svn_client_blame_receiver2_t */ +static svn_error_t * +blame_wrapper_receiver(void *baton, + apr_int64_t line_no, + svn_revnum_t revision, + const char *author, + const char *date, + svn_revnum_t merged_revision, + const char *merged_author, + const char *merged_date, + const char *merged_path, + const char *line, + apr_pool_t *pool) +{ + struct blame_receiver_wrapper_baton *brwb = baton; + + if (brwb->receiver) + return brwb->receiver(brwb->baton, + line_no, revision, author, date, line, pool); + + return SVN_NO_ERROR; +} + +static void +wrap_blame_receiver(svn_client_blame_receiver2_t *receiver2, + void **receiver2_baton, + svn_client_blame_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + struct blame_receiver_wrapper_baton *brwb = apr_palloc(pool, sizeof(*brwb)); + + /* Set the user provided old format callback in the baton. */ + brwb->baton = receiver_baton; + brwb->receiver = receiver; + + *receiver2_baton = brwb; + *receiver2 = blame_wrapper_receiver; +} + +svn_error_t * +svn_client_blame3(const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + const svn_diff_file_options_t *diff_options, + svn_boolean_t ignore_mime_type, + svn_client_blame_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_client_blame_receiver2_t receiver2; + void *receiver2_baton; + + wrap_blame_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton, + pool); + + return svn_client_blame4(target, peg_revision, start, end, diff_options, + ignore_mime_type, FALSE, receiver2, receiver2_baton, + ctx, pool); +} + +/* svn_client_blame3 guarantees 'no EOL chars' as part of the receiver + LINE argument. Older versions depend on the fact that if a CR is + required, that CR is already part of the LINE data. + + Because of this difference, we need to trap old receivers and append + a CR to LINE before passing it on to the actual receiver on platforms + which want CRLF line termination. + +*/ + +struct wrapped_receiver_baton_s +{ + svn_client_blame_receiver_t orig_receiver; + void *orig_baton; +}; + +static svn_error_t * +wrapped_receiver(void *baton, + apr_int64_t line_no, + svn_revnum_t revision, + const char *author, + const char *date, + const char *line, + apr_pool_t *pool) +{ + struct wrapped_receiver_baton_s *b = baton; + svn_stringbuf_t *expanded_line = svn_stringbuf_create(line, pool); + + svn_stringbuf_appendbyte(expanded_line, '\r'); + + return b->orig_receiver(b->orig_baton, line_no, revision, author, + date, expanded_line->data, pool); +} + +static void +wrap_pre_blame3_receiver(svn_client_blame_receiver_t *receiver, + void **receiver_baton, + apr_pool_t *pool) +{ + if (sizeof(APR_EOL_STR) == 3) + { + struct wrapped_receiver_baton_s *b = apr_palloc(pool,sizeof(*b)); + + b->orig_receiver = *receiver; + b->orig_baton = *receiver_baton; + + *receiver_baton = b; + *receiver = wrapped_receiver; + } +} + +svn_error_t * +svn_client_blame2(const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + svn_client_blame_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool); + return svn_client_blame3(target, peg_revision, start, end, + svn_diff_file_options_create(pool), FALSE, + receiver, receiver_baton, ctx, pool); +} +svn_error_t * +svn_client_blame(const char *target, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + svn_client_blame_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool); + return svn_client_blame2(target, end, start, end, + receiver, receiver_baton, ctx, pool); +} + +/*** From cmdline.c ***/ +svn_error_t * +svn_client_args_to_target_array(apr_array_header_t **targets_p, + apr_getopt_t *os, + const apr_array_header_t *known_targets, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_args_to_target_array2(targets_p, os, known_targets, ctx, + FALSE, pool); +} + +/*** From commit.c ***/ +svn_error_t * +svn_client_import4(const char *path, + const char *url, + svn_depth_t depth, + svn_boolean_t no_ignore, + svn_boolean_t ignore_unknown_node_types, + const apr_hash_t *revprop_table, + svn_commit_callback2_t commit_callback, + void *commit_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_error_trace(svn_client_import5(path, url, depth, no_ignore, + FALSE, ignore_unknown_node_types, + revprop_table, + NULL, NULL, + commit_callback, commit_baton, + ctx, pool)); +} + + +svn_error_t * +svn_client_import3(svn_commit_info_t **commit_info_p, + const char *path, + const char *url, + svn_depth_t depth, + svn_boolean_t no_ignore, + svn_boolean_t ignore_unknown_node_types, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct capture_baton_t cb; + + cb.info = commit_info_p; + cb.pool = pool; + + return svn_client_import4(path, url, depth, no_ignore, + ignore_unknown_node_types, revprop_table, + capture_commit_info, &cb, ctx, pool); +} + +svn_error_t * +svn_client_import2(svn_commit_info_t **commit_info_p, + const char *path, + const char *url, + svn_boolean_t nonrecursive, + svn_boolean_t no_ignore, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_import3(commit_info_p, + path, url, + SVN_DEPTH_INFINITY_OR_FILES(! nonrecursive), + no_ignore, FALSE, NULL, ctx, pool); +} + +svn_error_t * +svn_client_import(svn_client_commit_info_t **commit_info_p, + const char *path, + const char *url, + svn_boolean_t nonrecursive, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_commit_info_t *commit_info = NULL; + svn_error_t *err; + + err = svn_client_import2(&commit_info, + path, url, nonrecursive, + FALSE, ctx, pool); + /* These structs have the same layout for the common fields. */ + *commit_info_p = (svn_client_commit_info_t *) commit_info; + return svn_error_trace(err); +} + + +/* Wrapper notify_func2 function and baton for downgrading + svn_wc_notify_commit_copied and svn_wc_notify_commit_copied_replaced + to svn_wc_notify_commit_added and svn_wc_notify_commit_replaced, + respectively. */ +struct downgrade_commit_copied_notify_baton +{ + svn_wc_notify_func2_t orig_notify_func2; + void *orig_notify_baton2; +}; + +static void +downgrade_commit_copied_notify_func(void *baton, + const svn_wc_notify_t *notify, + apr_pool_t *pool) +{ + struct downgrade_commit_copied_notify_baton *b = baton; + + if (notify->action == svn_wc_notify_commit_copied) + { + svn_wc_notify_t *my_notify = svn_wc_dup_notify(notify, pool); + my_notify->action = svn_wc_notify_commit_added; + notify = my_notify; + } + else if (notify->action == svn_wc_notify_commit_copied_replaced) + { + svn_wc_notify_t *my_notify = svn_wc_dup_notify(notify, pool); + my_notify->action = svn_wc_notify_commit_replaced; + notify = my_notify; + } + + /* Call the wrapped notification system (if any) with MY_NOTIFY, + which is either the original NOTIFY object, or a tweaked deep + copy thereof. */ + if (b->orig_notify_func2) + b->orig_notify_func2(b->orig_notify_baton2, notify, pool); +} + +svn_error_t * +svn_client_commit5(const apr_array_header_t *targets, + svn_depth_t depth, + svn_boolean_t keep_locks, + svn_boolean_t keep_changelists, + svn_boolean_t commit_as_operations, + const apr_array_header_t *changelists, + const apr_hash_t *revprop_table, + svn_commit_callback2_t commit_callback, + void *commit_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_commit6(targets, depth, keep_locks, keep_changelists, + commit_as_operations, + FALSE, /* include_file_externals */ + FALSE, /* include_dir_externals */ + changelists, revprop_table, commit_callback, + commit_baton, ctx, pool); +} + +svn_error_t * +svn_client_commit4(svn_commit_info_t **commit_info_p, + const apr_array_header_t *targets, + svn_depth_t depth, + svn_boolean_t keep_locks, + svn_boolean_t keep_changelists, + const apr_array_header_t *changelists, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct capture_baton_t cb; + struct downgrade_commit_copied_notify_baton notify_baton; + svn_error_t *err; + + notify_baton.orig_notify_func2 = ctx->notify_func2; + notify_baton.orig_notify_baton2 = ctx->notify_baton2; + + *commit_info_p = NULL; + cb.info = commit_info_p; + cb.pool = pool; + + /* Swap out the notification system (if any) with a thin filtering + wrapper. */ + if (ctx->notify_func2) + { + ctx->notify_func2 = downgrade_commit_copied_notify_func; + ctx->notify_baton2 = ¬ify_baton; + } + + err = svn_client_commit5(targets, depth, keep_locks, keep_changelists, FALSE, + changelists, revprop_table, + capture_commit_info, &cb, ctx, pool); + + /* Ensure that the original notification system is in place. */ + ctx->notify_func2 = notify_baton.orig_notify_func2; + ctx->notify_baton2 = notify_baton.orig_notify_baton2; + + SVN_ERR(err); + + if (! *commit_info_p) + *commit_info_p = svn_create_commit_info(pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_commit3(svn_commit_info_t **commit_info_p, + const apr_array_header_t *targets, + svn_boolean_t recurse, + svn_boolean_t keep_locks, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recurse); + + return svn_client_commit4(commit_info_p, targets, depth, keep_locks, + FALSE, NULL, NULL, ctx, pool); +} + +svn_error_t * +svn_client_commit2(svn_client_commit_info_t **commit_info_p, + const apr_array_header_t *targets, + svn_boolean_t recurse, + svn_boolean_t keep_locks, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_commit_info_t *commit_info = NULL; + svn_error_t *err; + + err = svn_client_commit3(&commit_info, targets, recurse, keep_locks, + ctx, pool); + /* These structs have the same layout for the common fields. */ + *commit_info_p = (svn_client_commit_info_t *) commit_info; + return svn_error_trace(err); +} + +svn_error_t * +svn_client_commit(svn_client_commit_info_t **commit_info_p, + const apr_array_header_t *targets, + svn_boolean_t nonrecursive, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_commit2(commit_info_p, targets, + ! nonrecursive, + TRUE, + ctx, pool); +} + +/*** From copy.c ***/ +svn_error_t * +svn_client_copy5(svn_commit_info_t **commit_info_p, + const apr_array_header_t *sources, + const char *dst_path, + svn_boolean_t copy_as_child, + svn_boolean_t make_parents, + svn_boolean_t ignore_externals, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct capture_baton_t cb; + + cb.info = commit_info_p; + cb.pool = pool; + + return svn_client_copy6(sources, dst_path, copy_as_child, make_parents, + ignore_externals, revprop_table, + capture_commit_info, &cb, ctx, pool); +} + +svn_error_t * +svn_client_copy4(svn_commit_info_t **commit_info_p, + const apr_array_header_t *sources, + const char *dst_path, + svn_boolean_t copy_as_child, + svn_boolean_t make_parents, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_copy5(commit_info_p, sources, dst_path, copy_as_child, + make_parents, FALSE, revprop_table, ctx, pool); +} + +svn_error_t * +svn_client_copy3(svn_commit_info_t **commit_info_p, + const char *src_path, + const svn_opt_revision_t *src_revision, + const char *dst_path, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + apr_array_header_t *sources = apr_array_make(pool, 1, + sizeof(const svn_client_copy_source_t *)); + svn_client_copy_source_t copy_source; + + copy_source.path = src_path; + copy_source.revision = src_revision; + copy_source.peg_revision = src_revision; + + APR_ARRAY_PUSH(sources, const svn_client_copy_source_t *) = ©_source; + + return svn_client_copy4(commit_info_p, sources, dst_path, FALSE, FALSE, + NULL, ctx, pool); +} + +svn_error_t * +svn_client_copy2(svn_commit_info_t **commit_info_p, + const char *src_path, + const svn_opt_revision_t *src_revision, + const char *dst_path, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_error_t *err; + + err = svn_client_copy3(commit_info_p, src_path, src_revision, + dst_path, ctx, pool); + + /* If the target exists, try to copy the source as a child of the target. + This will obviously fail if target is not a directory, but that's exactly + what we want. */ + if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS + || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS)) + { + const char *src_basename = svn_path_basename(src_path, pool); + + svn_error_clear(err); + + return svn_client_copy3(commit_info_p, src_path, src_revision, + svn_path_join(dst_path, src_basename, pool), + ctx, pool); + } + + return svn_error_trace(err); +} + +svn_error_t * +svn_client_copy(svn_client_commit_info_t **commit_info_p, + const char *src_path, + const svn_opt_revision_t *src_revision, + const char *dst_path, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_commit_info_t *commit_info = NULL; + svn_error_t *err; + + err = svn_client_copy2(&commit_info, src_path, src_revision, dst_path, + ctx, pool); + /* These structs have the same layout for the common fields. */ + *commit_info_p = (svn_client_commit_info_t *) commit_info; + return svn_error_trace(err); +} + +svn_error_t * +svn_client_move6(const apr_array_header_t *src_paths, + const char *dst_path, + svn_boolean_t move_as_child, + svn_boolean_t make_parents, + const apr_hash_t *revprop_table, + svn_commit_callback2_t commit_callback, + void *commit_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_error_trace(svn_client_move7(src_paths, dst_path, + move_as_child, make_parents, + TRUE /* allow_mixed_revisions */, + FALSE /* metadata_only */, + revprop_table, + commit_callback, commit_baton, + ctx, pool)); +} + +svn_error_t * +svn_client_move5(svn_commit_info_t **commit_info_p, + const apr_array_header_t *src_paths, + const char *dst_path, + svn_boolean_t force, + svn_boolean_t move_as_child, + svn_boolean_t make_parents, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct capture_baton_t cb; + + cb.info = commit_info_p; + cb.pool = pool; + + return svn_client_move6(src_paths, dst_path, move_as_child, + make_parents, revprop_table, + capture_commit_info, &cb, ctx, pool); +} + +svn_error_t * +svn_client_move4(svn_commit_info_t **commit_info_p, + const char *src_path, + const char *dst_path, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + apr_array_header_t *src_paths = + apr_array_make(pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(src_paths, const char *) = src_path; + + + return svn_client_move5(commit_info_p, src_paths, dst_path, force, FALSE, + FALSE, NULL, ctx, pool); +} + +svn_error_t * +svn_client_move3(svn_commit_info_t **commit_info_p, + const char *src_path, + const char *dst_path, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_error_t *err; + + err = svn_client_move4(commit_info_p, src_path, dst_path, force, ctx, pool); + + /* If the target exists, try to move the source as a child of the target. + This will obviously fail if target is not a directory, but that's exactly + what we want. */ + if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS + || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS)) + { + const char *src_basename = svn_path_basename(src_path, pool); + + svn_error_clear(err); + + return svn_client_move4(commit_info_p, src_path, + svn_path_join(dst_path, src_basename, pool), + force, ctx, pool); + } + + return svn_error_trace(err); +} + +svn_error_t * +svn_client_move2(svn_client_commit_info_t **commit_info_p, + const char *src_path, + const char *dst_path, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_commit_info_t *commit_info = NULL; + svn_error_t *err; + + err = svn_client_move3(&commit_info, src_path, dst_path, force, ctx, pool); + /* These structs have the same layout for the common fields. */ + *commit_info_p = (svn_client_commit_info_t *) commit_info; + return svn_error_trace(err); +} + + +svn_error_t * +svn_client_move(svn_client_commit_info_t **commit_info_p, + const char *src_path, + const svn_opt_revision_t *src_revision, + const char *dst_path, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + /* It doesn't make sense to specify revisions in a move. */ + + /* ### todo: this check could fail wrongly. For example, + someone could pass in an svn_opt_revision_number that just + happens to be the HEAD. It's fair enough to punt then, IMHO, + and just demand that the user not specify a revision at all; + beats mucking up this function with RA calls and such. */ + if (src_revision->kind != svn_opt_revision_unspecified + && src_revision->kind != svn_opt_revision_head) + { + return svn_error_create + (SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Cannot specify revisions (except HEAD) with move operations")); + } + + return svn_client_move2(commit_info_p, src_path, dst_path, force, ctx, pool); +} + +/*** From delete.c ***/ +svn_error_t * +svn_client_delete3(svn_commit_info_t **commit_info_p, + const apr_array_header_t *paths, + svn_boolean_t force, + svn_boolean_t keep_local, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct capture_baton_t cb; + + cb.info = commit_info_p; + cb.pool = pool; + + return svn_client_delete4(paths, force, keep_local, revprop_table, + capture_commit_info, &cb, ctx, pool); +} + +svn_error_t * +svn_client_delete2(svn_commit_info_t **commit_info_p, + const apr_array_header_t *paths, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_delete3(commit_info_p, paths, force, FALSE, NULL, + ctx, pool); +} + +svn_error_t * +svn_client_delete(svn_client_commit_info_t **commit_info_p, + const apr_array_header_t *paths, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_commit_info_t *commit_info = NULL; + svn_error_t *err = NULL; + + err = svn_client_delete2(&commit_info, paths, force, ctx, pool); + /* These structs have the same layout for the common fields. */ + *commit_info_p = (svn_client_commit_info_t *) commit_info; + return svn_error_trace(err); +} + +/*** From diff.c ***/ + +svn_error_t * +svn_client_diff5(const apr_array_header_t *diff_options, + const char *path1, + const svn_opt_revision_t *revision1, + const char *path2, + const svn_opt_revision_t *revision2, + const char *relative_to_dir, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t show_copies_as_adds, + svn_boolean_t ignore_content_type, + svn_boolean_t use_git_diff_format, + const char *header_encoding, + apr_file_t *outfile, + apr_file_t *errfile, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool); + svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool); + + return svn_client_diff6(diff_options, path1, revision1, path2, + revision2, relative_to_dir, depth, + ignore_ancestry, FALSE /* no_diff_added */, + no_diff_deleted, show_copies_as_adds, + ignore_content_type, FALSE /* ignore_properties */, + FALSE /* properties_only */, use_git_diff_format, + header_encoding, + outstream, errstream, changelists, ctx, pool); +} + +svn_error_t * +svn_client_diff4(const apr_array_header_t *options, + const char *path1, + const svn_opt_revision_t *revision1, + const char *path2, + const svn_opt_revision_t *revision2, + const char *relative_to_dir, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t ignore_content_type, + const char *header_encoding, + apr_file_t *outfile, + apr_file_t *errfile, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff5(options, path1, revision1, path2, + revision2, relative_to_dir, depth, + ignore_ancestry, no_diff_deleted, FALSE, + ignore_content_type, FALSE, header_encoding, + outfile, errfile, changelists, ctx, pool); +} + +svn_error_t * +svn_client_diff3(const apr_array_header_t *options, + const char *path1, + const svn_opt_revision_t *revision1, + const char *path2, + const svn_opt_revision_t *revision2, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t ignore_content_type, + const char *header_encoding, + apr_file_t *outfile, + apr_file_t *errfile, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff4(options, path1, revision1, path2, + revision2, NULL, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, no_diff_deleted, + ignore_content_type, header_encoding, + outfile, errfile, NULL, ctx, pool); +} + +svn_error_t * +svn_client_diff2(const apr_array_header_t *options, + const char *path1, + const svn_opt_revision_t *revision1, + const char *path2, + const svn_opt_revision_t *revision2, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t ignore_content_type, + apr_file_t *outfile, + apr_file_t *errfile, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff3(options, path1, revision1, path2, revision2, + recurse, ignore_ancestry, no_diff_deleted, + ignore_content_type, SVN_APR_LOCALE_CHARSET, + outfile, errfile, ctx, pool); +} + +svn_error_t * +svn_client_diff(const apr_array_header_t *options, + const char *path1, + const svn_opt_revision_t *revision1, + const char *path2, + const svn_opt_revision_t *revision2, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + apr_file_t *outfile, + apr_file_t *errfile, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff2(options, path1, revision1, path2, revision2, + recurse, ignore_ancestry, no_diff_deleted, FALSE, + outfile, errfile, ctx, pool); +} + +svn_error_t * +svn_client_diff_peg5(const apr_array_header_t *diff_options, + const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start_revision, + const svn_opt_revision_t *end_revision, + const char *relative_to_dir, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t show_copies_as_adds, + svn_boolean_t ignore_content_type, + svn_boolean_t use_git_diff_format, + const char *header_encoding, + apr_file_t *outfile, + apr_file_t *errfile, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool); + svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool); + + return svn_client_diff_peg6(diff_options, + path, + peg_revision, + start_revision, + end_revision, + relative_to_dir, + depth, + ignore_ancestry, + FALSE /* no_diff_added */, + no_diff_deleted, + show_copies_as_adds, + ignore_content_type, + FALSE /* ignore_properties */, + FALSE /* properties_only */, + use_git_diff_format, + header_encoding, + outstream, + errstream, + changelists, + ctx, + pool); +} + +svn_error_t * +svn_client_diff_peg4(const apr_array_header_t *options, + const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start_revision, + const svn_opt_revision_t *end_revision, + const char *relative_to_dir, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t ignore_content_type, + const char *header_encoding, + apr_file_t *outfile, + apr_file_t *errfile, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff_peg5(options, + path, + peg_revision, + start_revision, + end_revision, + relative_to_dir, + depth, + ignore_ancestry, + no_diff_deleted, + FALSE, + ignore_content_type, + FALSE, + header_encoding, + outfile, + errfile, + changelists, + ctx, + pool); +} + +svn_error_t * +svn_client_diff_peg3(const apr_array_header_t *options, + const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start_revision, + const svn_opt_revision_t *end_revision, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t ignore_content_type, + const char *header_encoding, + apr_file_t *outfile, + apr_file_t *errfile, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff_peg4(options, + path, + peg_revision, + start_revision, + end_revision, + NULL, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, + no_diff_deleted, + ignore_content_type, + header_encoding, + outfile, + errfile, + NULL, + ctx, + pool); +} + +svn_error_t * +svn_client_diff_peg2(const apr_array_header_t *options, + const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start_revision, + const svn_opt_revision_t *end_revision, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + svn_boolean_t ignore_content_type, + apr_file_t *outfile, + apr_file_t *errfile, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff_peg3(options, path, peg_revision, start_revision, + end_revision, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, no_diff_deleted, + ignore_content_type, SVN_APR_LOCALE_CHARSET, + outfile, errfile, ctx, pool); +} + +svn_error_t * +svn_client_diff_peg(const apr_array_header_t *options, + const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start_revision, + const svn_opt_revision_t *end_revision, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_deleted, + apr_file_t *outfile, + apr_file_t *errfile, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff_peg2(options, path, peg_revision, + start_revision, end_revision, recurse, + ignore_ancestry, no_diff_deleted, FALSE, + outfile, errfile, ctx, pool); +} + +svn_error_t * +svn_client_diff_summarize(const char *path1, + const svn_opt_revision_t *revision1, + const char *path2, + const svn_opt_revision_t *revision2, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_client_diff_summarize_func_t summarize_func, + void *summarize_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff_summarize2(path1, revision1, path2, + revision2, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, NULL, summarize_func, + summarize_baton, ctx, pool); +} + +svn_error_t * +svn_client_diff_summarize_peg(const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start_revision, + const svn_opt_revision_t *end_revision, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_client_diff_summarize_func_t summarize_func, + void *summarize_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff_summarize_peg2(path, peg_revision, + start_revision, end_revision, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, NULL, + summarize_func, summarize_baton, + ctx, pool); +} + +/*** From export.c ***/ +svn_error_t * +svn_client_export4(svn_revnum_t *result_rev, + const char *from_path_or_url, + const char *to_path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t overwrite, + svn_boolean_t ignore_externals, + svn_depth_t depth, + const char *native_eol, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_export5(result_rev, from_path_or_url, to_path, + peg_revision, revision, overwrite, ignore_externals, + FALSE, depth, native_eol, ctx, pool); +} + +svn_error_t * +svn_client_export3(svn_revnum_t *result_rev, + const char *from_path_or_url, + const char *to_path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t overwrite, + svn_boolean_t ignore_externals, + svn_boolean_t recurse, + const char *native_eol, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_export4(result_rev, from_path_or_url, to_path, + peg_revision, revision, overwrite, ignore_externals, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + native_eol, ctx, pool); +} + +svn_error_t * +svn_client_export2(svn_revnum_t *result_rev, + const char *from_path_or_url, + const char *to_path, + svn_opt_revision_t *revision, + svn_boolean_t force, + const char *native_eol, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_opt_revision_t peg_revision; + + peg_revision.kind = svn_opt_revision_unspecified; + + return svn_client_export3(result_rev, from_path_or_url, to_path, + &peg_revision, revision, force, FALSE, TRUE, + native_eol, ctx, pool); +} + + +svn_error_t * +svn_client_export(svn_revnum_t *result_rev, + const char *from_path_or_url, + const char *to_path, + svn_opt_revision_t *revision, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_export2(result_rev, from_path_or_url, to_path, revision, + force, NULL, ctx, pool); +} + +/*** 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, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + 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) +{ + return svn_client_list2(path_or_url, + peg_revision, + revision, + SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse), + dirent_fields, + fetch_locks, + list_func, + baton, + ctx, + pool); +} + +/* Baton used by compatibility wrapper svn_client_ls3. */ +struct ls_baton { + apr_hash_t *dirents; + apr_hash_t *locks; + apr_pool_t *pool; +}; + +/* This implements svn_client_list_func_t. */ +static svn_error_t * +store_dirent(void *baton, const char *path, const svn_dirent_t *dirent, + const svn_lock_t *lock, const char *abs_path, apr_pool_t *pool) +{ + struct ls_baton *lb = baton; + + /* The dirent is allocated in a temporary pool, so duplicate it into the + correct pool. Note, however, that the locks are stored in the correct + pool already. */ + dirent = svn_dirent_dup(dirent, lb->pool); + + /* An empty path means we are called for the target of the operation. + For compatibility, we only store the target if it is a file, and we + store it under the basename of the URL. Note that this makes it + impossible to differentiate between the target being a directory with a + child with the same basename as the target and the target being a file, + but that's how it was implemented. */ + if (path[0] == '\0') + { + if (dirent->kind == svn_node_file) + { + const char *base_name = svn_path_basename(abs_path, lb->pool); + svn_hash_sets(lb->dirents, base_name, dirent); + if (lock) + svn_hash_sets(lb->locks, base_name, lock); + } + } + else + { + path = apr_pstrdup(lb->pool, path); + svn_hash_sets(lb->dirents, path, dirent); + if (lock) + svn_hash_sets(lb->locks, path, lock); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_ls3(apr_hash_t **dirents, + apr_hash_t **locks, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct ls_baton lb; + + *dirents = lb.dirents = apr_hash_make(pool); + if (locks) + *locks = lb.locks = apr_hash_make(pool); + lb.pool = pool; + + return svn_client_list(path_or_url, peg_revision, revision, recurse, + SVN_DIRENT_ALL, locks != NULL, + store_dirent, &lb, ctx, pool); +} + +svn_error_t * +svn_client_ls2(apr_hash_t **dirents, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + + return svn_client_ls3(dirents, NULL, path_or_url, peg_revision, + revision, recurse, ctx, pool); +} + + +svn_error_t * +svn_client_ls(apr_hash_t **dirents, + const char *path_or_url, + svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_ls2(dirents, path_or_url, revision, + revision, recurse, ctx, pool); +} + +/*** From log.c ***/ +svn_error_t * +svn_client_log4(const apr_array_header_t *targets, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_boolean_t include_merged_revisions, + const apr_array_header_t *revprops, + svn_log_entry_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + apr_array_header_t *revision_ranges; + + revision_ranges = apr_array_make(pool, 1, + sizeof(svn_opt_revision_range_t *)); + APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) + = svn_opt__revision_range_create(start, end, pool); + + return svn_client_log5(targets, peg_revision, revision_ranges, limit, + discover_changed_paths, strict_node_history, + include_merged_revisions, revprops, receiver, + receiver_baton, ctx, pool); +} + + +svn_error_t * +svn_client_log3(const apr_array_header_t *targets, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_log_message_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_log_entry_receiver_t receiver2; + void *receiver2_baton; + + svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton, + receiver, receiver_baton, + pool); + + return svn_client_log4(targets, peg_revision, start, end, limit, + discover_changed_paths, strict_node_history, FALSE, + svn_compat_log_revprops_in(pool), + receiver2, receiver2_baton, ctx, pool); +} + +svn_error_t * +svn_client_log2(const apr_array_header_t *targets, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_log_message_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_opt_revision_t peg_revision; + peg_revision.kind = svn_opt_revision_unspecified; + return svn_client_log3(targets, &peg_revision, start, end, limit, + discover_changed_paths, strict_node_history, + receiver, receiver_baton, ctx, pool); +} + +svn_error_t * +svn_client_log(const apr_array_header_t *targets, + const svn_opt_revision_t *start, + const svn_opt_revision_t *end, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_log_message_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_error_t *err = SVN_NO_ERROR; + + err = svn_client_log2(targets, start, end, 0, discover_changed_paths, + strict_node_history, receiver, receiver_baton, ctx, + pool); + + /* Special case: If there have been no commits, we'll get an error + * for requesting log of a revision higher than 0. But the + * default behavior of "svn log" is to give revisions HEAD through + * 1, on the assumption that HEAD >= 1. + * + * So if we got that error for that reason, and it looks like the + * user was just depending on the defaults (rather than explicitly + * requesting the log for revision 1), then we don't error. Instead + * we just invoke the receiver manually on a hand-constructed log + * message for revision 0. + * + * See also http://subversion.tigris.org/issues/show_bug.cgi?id=692. + */ + if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION) + && (start->kind == svn_opt_revision_head) + && ((end->kind == svn_opt_revision_number) + && (end->value.number == 1))) + { + + /* We don't need to check if HEAD is 0, because that must be the case, + * by logical deduction: The revision range specified is HEAD:1. + * HEAD cannot not exist, so the revision to which "no such revision" + * applies is 1. If revision 1 does not exist, then HEAD is 0. + * Hence, we deduce the repository is empty without needing access + * to further information. */ + + svn_error_clear(err); + err = SVN_NO_ERROR; + + /* Log receivers are free to handle revision 0 specially... But + just in case some don't, we make up a message here. */ + SVN_ERR(receiver(receiver_baton, + NULL, 0, "", "", _("No commits in repository"), + pool)); + } + + return svn_error_trace(err); +} + +/*** From merge.c ***/ + +svn_error_t * +svn_client_merge4(const char *source1, + const svn_opt_revision_t *revision1, + const char *source2, + const svn_opt_revision_t *revision2, + const char *target_wcpath, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t record_only, + svn_boolean_t dry_run, + svn_boolean_t allow_mixed_rev, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + SVN_ERR(svn_client_merge5(source1, revision1, + source2, revision2, + target_wcpath, + depth, + ignore_ancestry /*ignore_mergeinfo*/, + ignore_ancestry /*diff_ignore_ancestry*/, + force_delete, record_only, + dry_run, allow_mixed_rev, + merge_options, ctx, pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_merge3(const char *source1, + const svn_opt_revision_t *revision1, + const char *source2, + const svn_opt_revision_t *revision2, + const char *target_wcpath, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t force, + svn_boolean_t record_only, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_merge4(source1, revision1, source2, revision2, + target_wcpath, depth, ignore_ancestry, force, + record_only, dry_run, TRUE, merge_options, + ctx, pool); +} + +svn_error_t * +svn_client_merge2(const char *source1, + const svn_opt_revision_t *revision1, + const char *source2, + const svn_opt_revision_t *revision2, + const char *target_wcpath, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t force, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_merge3(source1, revision1, source2, revision2, + target_wcpath, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, force, FALSE, dry_run, + merge_options, ctx, pool); +} + +svn_error_t * +svn_client_merge(const char *source1, + const svn_opt_revision_t *revision1, + const char *source2, + const svn_opt_revision_t *revision2, + const char *target_wcpath, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t force, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_merge2(source1, revision1, source2, revision2, + target_wcpath, recurse, ignore_ancestry, force, + dry_run, NULL, ctx, pool); +} + +svn_error_t * +svn_client_merge_peg4(const char *source_path_or_url, + const apr_array_header_t *ranges_to_merge, + const svn_opt_revision_t *source_peg_revision, + const char *target_wcpath, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t record_only, + svn_boolean_t dry_run, + svn_boolean_t allow_mixed_rev, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + SVN_ERR(svn_client_merge_peg5(source_path_or_url, + ranges_to_merge, + source_peg_revision, + target_wcpath, + depth, + ignore_ancestry /*ignore_mergeinfo*/, + ignore_ancestry /*diff_ignore_ancestry*/, + force_delete, record_only, + dry_run, allow_mixed_rev, + merge_options, ctx, pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_merge_peg3(const char *source, + const apr_array_header_t *ranges_to_merge, + const svn_opt_revision_t *peg_revision, + const char *target_wcpath, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t force, + svn_boolean_t record_only, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_merge_peg4(source, ranges_to_merge, peg_revision, + target_wcpath, depth, ignore_ancestry, force, + record_only, dry_run, TRUE, merge_options, + ctx, pool); +} + +svn_error_t * +svn_client_merge_peg2(const char *source, + const svn_opt_revision_t *revision1, + const svn_opt_revision_t *revision2, + const svn_opt_revision_t *peg_revision, + const char *target_wcpath, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t force, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + apr_array_header_t *ranges_to_merge = + apr_array_make(pool, 1, sizeof(svn_opt_revision_range_t *)); + + APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *) + = svn_opt__revision_range_create(revision1, revision2, pool); + return svn_client_merge_peg3(source, ranges_to_merge, + peg_revision, + target_wcpath, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_ancestry, force, FALSE, dry_run, + merge_options, ctx, pool); +} + +svn_error_t * +svn_client_merge_peg(const char *source, + const svn_opt_revision_t *revision1, + const svn_opt_revision_t *revision2, + const svn_opt_revision_t *peg_revision, + const char *target_wcpath, + svn_boolean_t recurse, + svn_boolean_t ignore_ancestry, + svn_boolean_t force, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_merge_peg2(source, revision1, revision2, peg_revision, + target_wcpath, recurse, ignore_ancestry, force, + dry_run, NULL, ctx, pool); +} + +/*** From prop_commands.c ***/ +svn_error_t * +svn_client_propset3(svn_commit_info_t **commit_info_p, + const char *propname, + const svn_string_t *propval, + const char *target, + svn_depth_t depth, + svn_boolean_t skip_checks, + svn_revnum_t base_revision_for_url, + const apr_array_header_t *changelists, + const apr_hash_t *revprop_table, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + if (svn_path_is_url(target)) + { + struct capture_baton_t cb; + + cb.info = commit_info_p; + cb.pool = pool; + + SVN_ERR(svn_client_propset_remote(propname, propval, target, skip_checks, + base_revision_for_url, revprop_table, + capture_commit_info, &cb, ctx, pool)); + } + else + { + apr_array_header_t *targets = apr_array_make(pool, 1, + sizeof(const char *)); + + APR_ARRAY_PUSH(targets, const char *) = target; + SVN_ERR(svn_client_propset_local(propname, propval, targets, depth, + skip_checks, changelists, ctx, pool)); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_propset2(const char *propname, + const svn_string_t *propval, + const char *target, + svn_boolean_t recurse, + svn_boolean_t skip_checks, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_propset3(NULL, propname, propval, target, + SVN_DEPTH_INFINITY_OR_EMPTY(recurse), + skip_checks, SVN_INVALID_REVNUM, + NULL, NULL, ctx, pool); +} + + +svn_error_t * +svn_client_propset(const char *propname, + const svn_string_t *propval, + const char *target, + svn_boolean_t recurse, + apr_pool_t *pool) +{ + svn_client_ctx_t *ctx; + + SVN_ERR(svn_client_create_context(&ctx, pool)); + + return svn_client_propset2(propname, propval, target, recurse, FALSE, + ctx, pool); +} + +svn_error_t * +svn_client_revprop_set(const char *propname, + const svn_string_t *propval, + const char *URL, + const svn_opt_revision_t *revision, + svn_revnum_t *set_rev, + svn_boolean_t force, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_revprop_set2(propname, propval, NULL, URL, + revision, set_rev, force, ctx, pool); + +} + +svn_error_t * +svn_client_propget4(apr_hash_t **props, + const char *propname, + const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_revnum_t *actual_revnum, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(svn_client_propget5(props, NULL, propname, target, + peg_revision, revision, + actual_revnum, depth, + changelists, ctx, + result_pool, scratch_pool)); +} + +svn_error_t * +svn_client_propget3(apr_hash_t **props, + const char *propname, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_revnum_t *actual_revnum, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + const char *target; + apr_hash_t *temp_props; + svn_error_t *err; + + if (svn_path_is_url(path_or_url)) + target = path_or_url; + else + SVN_ERR(svn_dirent_get_absolute(&target, path_or_url, pool)); + + err = svn_client_propget4(&temp_props, propname, target, + peg_revision, revision, actual_revnum, + depth, changelists, ctx, pool, pool); + + if (err && err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) + { + err->apr_err = SVN_ERR_ENTRY_NOT_FOUND; + return svn_error_trace(err); + } + else + SVN_ERR(err); + + if (actual_revnum + && !svn_path_is_url(path_or_url) + && !SVN_IS_VALID_REVNUM(*actual_revnum)) + { + /* Get the actual_revnum; added nodes have no revision yet, and old + * callers expected the mock-up revision of 0. */ + svn_boolean_t added; + + SVN_ERR(svn_wc__node_is_added(&added, ctx->wc_ctx, target, pool)); + if (added) + *actual_revnum = 0; + } + + /* We may need to fix up our hash keys for legacy callers. */ + if (!svn_path_is_url(path_or_url) && strcmp(target, path_or_url) != 0) + { + apr_hash_index_t *hi; + + *props = apr_hash_make(pool); + for (hi = apr_hash_first(pool, temp_props); hi; + hi = apr_hash_next(hi)) + { + const char *abspath = svn__apr_hash_index_key(hi); + svn_string_t *value = svn__apr_hash_index_val(hi); + const char *relpath = svn_dirent_join(path_or_url, + svn_dirent_skip_ancestor(target, abspath), + pool); + + svn_hash_sets(*props, relpath, value); + } + } + else + *props = temp_props; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_propget2(apr_hash_t **props, + const char *propname, + const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_propget3(props, + propname, + target, + peg_revision, + revision, + NULL, + SVN_DEPTH_INFINITY_OR_EMPTY(recurse), + NULL, + ctx, + pool); +} + +svn_error_t * +svn_client_propget(apr_hash_t **props, + const char *propname, + const char *target, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_propget2(props, propname, target, revision, revision, + recurse, ctx, pool); +} + + +/* Duplicate a HASH containing (char * -> svn_string_t *) key/value + pairs using POOL. */ +static apr_hash_t * +string_hash_dup(apr_hash_t *hash, apr_pool_t *pool) +{ + apr_hash_index_t *hi; + apr_hash_t *new_hash = apr_hash_make(pool); + + for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi)) + { + const char *key = apr_pstrdup(pool, svn__apr_hash_index_key(hi)); + apr_ssize_t klen = svn__apr_hash_index_klen(hi); + svn_string_t *val = svn_string_dup(svn__apr_hash_index_val(hi), pool); + + apr_hash_set(new_hash, key, klen, val); + } + return new_hash; +} + +svn_client_proplist_item_t * +svn_client_proplist_item_dup(const svn_client_proplist_item_t *item, + apr_pool_t * pool) +{ + svn_client_proplist_item_t *new_item = apr_pcalloc(pool, sizeof(*new_item)); + + if (item->node_name) + new_item->node_name = svn_stringbuf_dup(item->node_name, pool); + + if (item->prop_hash) + new_item->prop_hash = string_hash_dup(item->prop_hash, pool); + + return new_item; +} + +/* Baton for use with wrap_proplist_receiver */ +struct proplist_receiver_wrapper_baton { + void *baton; + svn_proplist_receiver_t receiver; +}; + +/* This implements svn_client_proplist_receiver2_t */ +static svn_error_t * +proplist_wrapper_receiver(void *baton, + const char *path, + apr_hash_t *prop_hash, + apr_array_header_t *inherited_props, + apr_pool_t *pool) +{ + struct proplist_receiver_wrapper_baton *plrwb = baton; + + if (plrwb->receiver) + return plrwb->receiver(plrwb->baton, path, prop_hash, pool); + + return SVN_NO_ERROR; +} + +static void +wrap_proplist_receiver(svn_proplist_receiver2_t *receiver2, + void **receiver2_baton, + svn_proplist_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + struct proplist_receiver_wrapper_baton *plrwb = apr_palloc(pool, + sizeof(*plrwb)); + + /* Set the user provided old format callback in the baton. */ + plrwb->baton = receiver_baton; + plrwb->receiver = receiver; + + *receiver2_baton = plrwb; + *receiver2 = proplist_wrapper_receiver; +} + +svn_error_t * +svn_client_proplist3(const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_proplist_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + + svn_proplist_receiver2_t receiver2; + void *receiver2_baton; + + wrap_proplist_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton, + pool); + + return svn_error_trace(svn_client_proplist4(target, peg_revision, revision, + depth, changelists, FALSE, + receiver2, receiver2_baton, + ctx, pool)); +} + +/* Receiver baton used by proplist2() */ +struct proplist_receiver_baton { + apr_array_header_t *props; + apr_pool_t *pool; +}; + +/* Receiver function used by proplist2(). */ +static svn_error_t * +proplist_receiver_cb(void *baton, + const char *path, + apr_hash_t *prop_hash, + apr_pool_t *pool) +{ + struct proplist_receiver_baton *pl_baton = + (struct proplist_receiver_baton *) baton; + svn_client_proplist_item_t *tmp_item = apr_palloc(pool, sizeof(*tmp_item)); + svn_client_proplist_item_t *item; + + /* Because the pool passed to the receiver function is likely to be a + temporary pool of some kind, we need to make copies of *path and + *prop_hash in the pool provided by the baton. */ + tmp_item->node_name = svn_stringbuf_create(path, pl_baton->pool); + tmp_item->prop_hash = prop_hash; + + item = svn_client_proplist_item_dup(tmp_item, pl_baton->pool); + + APR_ARRAY_PUSH(pl_baton->props, const svn_client_proplist_item_t *) = item; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_proplist2(apr_array_header_t **props, + const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct proplist_receiver_baton pl_baton; + + *props = apr_array_make(pool, 5, sizeof(svn_client_proplist_item_t *)); + pl_baton.props = *props; + pl_baton.pool = pool; + + return svn_client_proplist3(target, peg_revision, revision, + SVN_DEPTH_INFINITY_OR_EMPTY(recurse), NULL, + proplist_receiver_cb, &pl_baton, ctx, pool); +} + + +svn_error_t * +svn_client_proplist(apr_array_header_t **props, + const char *target, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_proplist2(props, target, revision, revision, + recurse, ctx, pool); +} + +/*** From status.c ***/ + +struct status4_wrapper_baton +{ + svn_wc_context_t *wc_ctx; + svn_wc_status_func3_t old_func; + void *old_baton; +}; + +/* Implements svn_client_status_func_t */ +static svn_error_t * +status4_wrapper_func(void *baton, + const char *path, + const svn_client_status_t *status, + apr_pool_t *scratch_pool) +{ + struct status4_wrapper_baton *swb = baton; + svn_wc_status2_t *dup; + const char *local_abspath; + const svn_wc_status3_t *wc_status = status->backwards_compatibility_baton; + + SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool)); + SVN_ERR(svn_wc__status2_from_3(&dup, wc_status, swb->wc_ctx, + local_abspath, scratch_pool, + scratch_pool)); + + return (*swb->old_func)(swb->old_baton, path, dup, scratch_pool); +} + +svn_error_t * +svn_client_status4(svn_revnum_t *result_rev, + const char *path, + const svn_opt_revision_t *revision, + svn_wc_status_func3_t status_func, + void *status_baton, + svn_depth_t depth, + svn_boolean_t get_all, + svn_boolean_t update, + svn_boolean_t no_ignore, + svn_boolean_t ignore_externals, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct status4_wrapper_baton swb; + + swb.wc_ctx = ctx->wc_ctx; + swb.old_func = status_func; + swb.old_baton = status_baton; + + return svn_client_status5(result_rev, ctx, path, revision, depth, get_all, + update, no_ignore, ignore_externals, TRUE, + changelists, status4_wrapper_func, &swb, pool); +} + +struct status3_wrapper_baton +{ + svn_wc_status_func2_t old_func; + void *old_baton; +}; + +static svn_error_t * +status3_wrapper_func(void *baton, + const char *path, + svn_wc_status2_t *status, + apr_pool_t *pool) +{ + struct status3_wrapper_baton *swb = baton; + + swb->old_func(swb->old_baton, path, status); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_status3(svn_revnum_t *result_rev, + const char *path, + const svn_opt_revision_t *revision, + svn_wc_status_func2_t status_func, + void *status_baton, + svn_depth_t depth, + svn_boolean_t get_all, + svn_boolean_t update, + svn_boolean_t no_ignore, + svn_boolean_t ignore_externals, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct status3_wrapper_baton swb = { 0 }; + swb.old_func = status_func; + swb.old_baton = status_baton; + return svn_client_status4(result_rev, path, revision, status3_wrapper_func, + &swb, depth, get_all, update, no_ignore, + ignore_externals, changelists, ctx, pool); +} + +svn_error_t * +svn_client_status2(svn_revnum_t *result_rev, + const char *path, + const svn_opt_revision_t *revision, + svn_wc_status_func2_t status_func, + void *status_baton, + svn_boolean_t recurse, + svn_boolean_t get_all, + svn_boolean_t update, + svn_boolean_t no_ignore, + svn_boolean_t ignore_externals, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_status3(result_rev, path, revision, + status_func, status_baton, + SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse), + get_all, update, no_ignore, ignore_externals, NULL, + ctx, pool); +} + + +/* Baton for old_status_func_cb; does what you think it does. */ +struct old_status_func_cb_baton +{ + svn_wc_status_func_t original_func; + void *original_baton; +}; + +/* Help svn_client_status() accept an old-style status func and baton, + by wrapping them before passing along to svn_client_status2(). + + This implements the 'svn_wc_status_func2_t' function type. */ +static void old_status_func_cb(void *baton, + const char *path, + svn_wc_status2_t *status) +{ + struct old_status_func_cb_baton *b = baton; + svn_wc_status_t *stat = (svn_wc_status_t *) status; + + b->original_func(b->original_baton, path, stat); +} + + +svn_error_t * +svn_client_status(svn_revnum_t *result_rev, + const char *path, + svn_opt_revision_t *revision, + svn_wc_status_func_t status_func, + void *status_baton, + svn_boolean_t recurse, + svn_boolean_t get_all, + svn_boolean_t update, + svn_boolean_t no_ignore, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct old_status_func_cb_baton *b = apr_pcalloc(pool, sizeof(*b)); + b->original_func = status_func; + b->original_baton = status_baton; + + return svn_client_status2(result_rev, path, revision, + old_status_func_cb, b, + recurse, get_all, update, no_ignore, FALSE, + ctx, pool); +} + +/*** From update.c ***/ +svn_error_t * +svn_client_update3(apr_array_header_t **result_revs, + const apr_array_header_t *paths, + const svn_opt_revision_t *revision, + svn_depth_t depth, + svn_boolean_t depth_is_sticky, + svn_boolean_t ignore_externals, + svn_boolean_t allow_unver_obstructions, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_update4(result_revs, paths, revision, + depth, depth_is_sticky, ignore_externals, + allow_unver_obstructions, TRUE, FALSE, + ctx, pool); +} + +svn_error_t * +svn_client_update2(apr_array_header_t **result_revs, + const apr_array_header_t *paths, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_boolean_t ignore_externals, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_update3(result_revs, paths, revision, + SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE, + ignore_externals, FALSE, ctx, pool); +} + +svn_error_t * +svn_client_update(svn_revnum_t *result_rev, + const char *path, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char *)); + apr_array_header_t *result_revs; + + APR_ARRAY_PUSH(paths, const char *) = path; + + SVN_ERR(svn_client_update2(&result_revs, paths, revision, recurse, FALSE, + ctx, pool)); + + *result_rev = APR_ARRAY_IDX(result_revs, 0, svn_revnum_t); + + return SVN_NO_ERROR; +} + +/*** From switch.c ***/ +svn_error_t * +svn_client_switch2(svn_revnum_t *result_rev, + const char *path, + const char *switch_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + svn_boolean_t depth_is_sticky, + svn_boolean_t ignore_externals, + svn_boolean_t allow_unver_obstructions, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_switch3(result_rev, path, switch_url, peg_revision, + revision, depth, depth_is_sticky, ignore_externals, + allow_unver_obstructions, + TRUE /* ignore_ancestry */, + ctx, pool); +} + +svn_error_t * +svn_client_switch(svn_revnum_t *result_rev, + const char *path, + const char *switch_url, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_opt_revision_t peg_revision; + peg_revision.kind = svn_opt_revision_unspecified; + return svn_client_switch2(result_rev, path, switch_url, + &peg_revision, revision, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + FALSE, FALSE, FALSE, ctx, pool); +} + +/*** From cat.c ***/ +svn_error_t * +svn_client_cat(svn_stream_t *out, + const char *path_or_url, + const svn_opt_revision_t *revision, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_cat2(out, path_or_url, revision, revision, + ctx, pool); +} + +/*** From checkout.c ***/ +svn_error_t * +svn_client_checkout2(svn_revnum_t *result_rev, + const char *URL, + const char *path, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_boolean_t ignore_externals, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_error_trace(svn_client_checkout3(result_rev, URL, path, + peg_revision, revision, + SVN_DEPTH_INFINITY_OR_FILES(recurse), + ignore_externals, FALSE, ctx, pool)); +} + +svn_error_t * +svn_client_checkout(svn_revnum_t *result_rev, + const char *URL, + const char *path, + const svn_opt_revision_t *revision, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_opt_revision_t peg_revision; + + peg_revision.kind = svn_opt_revision_unspecified; + + return svn_error_trace(svn_client_checkout2(result_rev, URL, path, + &peg_revision, revision, recurse, + FALSE, ctx, pool)); +} + +/*** From info.c ***/ + +svn_info_t * +svn_info_dup(const svn_info_t *info, apr_pool_t *pool) +{ + svn_info_t *dupinfo = apr_palloc(pool, sizeof(*dupinfo)); + + /* Perform a trivial copy ... */ + *dupinfo = *info; + + /* ...and then re-copy stuff that needs to be duped into our pool. */ + if (info->URL) + dupinfo->URL = apr_pstrdup(pool, info->URL); + if (info->repos_root_URL) + dupinfo->repos_root_URL = apr_pstrdup(pool, info->repos_root_URL); + if (info->repos_UUID) + dupinfo->repos_UUID = apr_pstrdup(pool, info->repos_UUID); + if (info->last_changed_author) + dupinfo->last_changed_author = apr_pstrdup(pool, + info->last_changed_author); + if (info->lock) + dupinfo->lock = svn_lock_dup(info->lock, pool); + if (info->copyfrom_url) + dupinfo->copyfrom_url = apr_pstrdup(pool, info->copyfrom_url); + if (info->checksum) + dupinfo->checksum = apr_pstrdup(pool, info->checksum); + if (info->conflict_old) + dupinfo->conflict_old = apr_pstrdup(pool, info->conflict_old); + if (info->conflict_new) + dupinfo->conflict_new = apr_pstrdup(pool, info->conflict_new); + if (info->conflict_wrk) + dupinfo->conflict_wrk = apr_pstrdup(pool, info->conflict_wrk); + if (info->prejfile) + dupinfo->prejfile = apr_pstrdup(pool, info->prejfile); + + return dupinfo; +} + +/* Convert an svn_client_info2_t to an svn_info_t, doing shallow copies. */ +static svn_error_t * +info_from_info2(svn_info_t **new_info, + svn_wc_context_t *wc_ctx, + const svn_client_info2_t *info2, + apr_pool_t *pool) +{ + svn_info_t *info = apr_pcalloc(pool, sizeof(*info)); + + info->URL = info2->URL; + /* Goofy backward compat handling for added nodes. */ + if (SVN_IS_VALID_REVNUM(info2->rev)) + info->rev = info2->rev; + else + info->rev = 0; + + info->kind = info2->kind; + info->repos_root_URL = info2->repos_root_URL; + info->repos_UUID = info2->repos_UUID; + info->last_changed_rev = info2->last_changed_rev; + info->last_changed_date = info2->last_changed_date; + info->last_changed_author = info2->last_changed_author; + + /* Stupid old structure has a non-const LOCK member. Sigh. */ + info->lock = (svn_lock_t *)info2->lock; + + info->size64 = info2->size; + if (info2->size == SVN_INVALID_FILESIZE) + info->size = SVN_INFO_SIZE_UNKNOWN; + else if (((svn_filesize_t)(apr_size_t)info->size64) == info->size64) + info->size = (apr_size_t)info->size64; + else /* >= 4GB */ + info->size = SVN_INFO_SIZE_UNKNOWN; + + if (info2->wc_info) + { + info->has_wc_info = TRUE; + info->schedule = info2->wc_info->schedule; + info->copyfrom_url = info2->wc_info->copyfrom_url; + info->copyfrom_rev = info2->wc_info->copyfrom_rev; + info->text_time = info2->wc_info->recorded_time; + info->prop_time = 0; + if (info2->wc_info->checksum + && info2->wc_info->checksum->kind == svn_checksum_md5) + info->checksum = svn_checksum_to_cstring( + info2->wc_info->checksum, pool); + else + info->checksum = NULL; + info->changelist = info2->wc_info->changelist; + info->depth = info2->wc_info->depth; + + if (info->depth == svn_depth_unknown && info->kind == svn_node_file) + info->depth = svn_depth_infinity; + + info->working_size64 = info2->wc_info->recorded_size; + if (((svn_filesize_t)(apr_size_t)info->working_size64) == info->working_size64) + info->working_size = (apr_size_t)info->working_size64; + else /* >= 4GB */ + info->working_size = SVN_INFO_SIZE_UNKNOWN; + } + else + { + info->has_wc_info = FALSE; + info->working_size = SVN_INFO_SIZE_UNKNOWN; + info->working_size64 = SVN_INVALID_FILESIZE; + info->depth = svn_depth_unknown; + } + + /* Populate conflict fields. */ + if (info2->wc_info && info2->wc_info->conflicts) + { + int i; + + for (i = 0; i < info2->wc_info->conflicts->nelts; i++) + { + const svn_wc_conflict_description2_t *conflict + = APR_ARRAY_IDX(info2->wc_info->conflicts, i, + const svn_wc_conflict_description2_t *); + + /* ### Not really sure what we should do if we get multiple + ### conflicts of the same type. */ + switch (conflict->kind) + { + case svn_wc_conflict_kind_tree: + info->tree_conflict = svn_wc__cd2_to_cd(conflict, pool); + break; + + case svn_wc_conflict_kind_text: + info->conflict_old = conflict->base_abspath; + info->conflict_new = conflict->my_abspath; + info->conflict_wrk = conflict->their_abspath; + break; + + case svn_wc_conflict_kind_property: + info->prejfile = conflict->their_abspath; + break; + } + } + } + + if (info2->wc_info && info2->wc_info->checksum) + { + const svn_checksum_t *md5_checksum; + + SVN_ERR(svn_wc__node_get_md5_from_sha1(&md5_checksum, + wc_ctx, + info2->wc_info->wcroot_abspath, + info2->wc_info->checksum, + pool, pool)); + + info->checksum = svn_checksum_to_cstring(md5_checksum, pool); + } + + *new_info = info; + return SVN_NO_ERROR; +} + +struct info_to_relpath_baton +{ + const char *anchor_abspath; + const char *anchor_relpath; + svn_info_receiver_t info_receiver; + void *info_baton; + svn_wc_context_t *wc_ctx; +}; + +static svn_error_t * +info_receiver_relpath_wrapper(void *baton, + const char *abspath_or_url, + const svn_client_info2_t *info2, + apr_pool_t *scratch_pool) +{ + struct info_to_relpath_baton *rb = baton; + const char *path = abspath_or_url; + svn_info_t *info; + + if (rb->anchor_relpath && + svn_dirent_is_ancestor(rb->anchor_abspath, abspath_or_url)) + { + path = svn_dirent_join(rb->anchor_relpath, + svn_dirent_skip_ancestor(rb->anchor_abspath, + abspath_or_url), + scratch_pool); + } + + SVN_ERR(info_from_info2(&info, rb->wc_ctx, info2, scratch_pool)); + + SVN_ERR(rb->info_receiver(rb->info_baton, + path, + info, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_info2(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_info_receiver_t receiver, + void *receiver_baton, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + struct info_to_relpath_baton rb; + const char *abspath_or_url = path_or_url; + + rb.anchor_relpath = NULL; + rb.info_receiver = receiver; + rb.info_baton = receiver_baton; + rb.wc_ctx = ctx->wc_ctx; + + if (!svn_path_is_url(path_or_url)) + { + SVN_ERR(svn_dirent_get_absolute(&abspath_or_url, path_or_url, pool)); + rb.anchor_abspath = abspath_or_url; + rb.anchor_relpath = path_or_url; + } + + SVN_ERR(svn_client_info3(abspath_or_url, + peg_revision, + revision, + depth, + FALSE, TRUE, + changelists, + info_receiver_relpath_wrapper, + &rb, + ctx, + pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_info(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_info_receiver_t receiver, + void *receiver_baton, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_info2(path_or_url, peg_revision, revision, + receiver, receiver_baton, + SVN_DEPTH_INFINITY_OR_EMPTY(recurse), + NULL, ctx, pool); +} + +/*** From resolved.c ***/ +svn_error_t * +svn_client_resolved(const char *path, + svn_boolean_t recursive, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recursive); + return svn_client_resolve(path, depth, + svn_wc_conflict_choose_merged, ctx, pool); +} +/*** From revert.c ***/ +svn_error_t * +svn_client_revert(const apr_array_header_t *paths, + svn_boolean_t recursive, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_revert2(paths, SVN_DEPTH_INFINITY_OR_EMPTY(recursive), + NULL, ctx, pool); +} + +/*** From ra.c ***/ +svn_error_t * +svn_client_open_ra_session(svn_ra_session_t **session, + const char *url, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_error_trace( + svn_client_open_ra_session2(session, url, + NULL, ctx, + pool, pool)); +} + +svn_error_t * +svn_client_uuid_from_url(const char **uuid, + const char *url, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_error_t *err; + apr_pool_t *subpool = svn_pool_create(pool); + + err = svn_client_get_repos_root(NULL, uuid, url, + ctx, pool, subpool); + /* destroy the RA session */ + svn_pool_destroy(subpool); + + return svn_error_trace(err);; +} + +svn_error_t * +svn_client_uuid_from_path2(const char **uuid, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace( + svn_client_get_repos_root(NULL, uuid, + local_abspath, ctx, + result_pool, scratch_pool)); +} + +svn_error_t * +svn_client_uuid_from_path(const char **uuid, + const char *path, + svn_wc_adm_access_t *adm_access, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + const char *local_abspath; + + SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); + return svn_error_trace( + svn_client_uuid_from_path2(uuid, local_abspath, ctx, pool, pool)); +} + +/*** From url.c ***/ +svn_error_t * +svn_client_root_url_from_path(const char **url, + const char *path_or_url, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + apr_pool_t *subpool = svn_pool_create(pool); + svn_error_t *err; + if (!svn_path_is_url(path_or_url)) + SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool)); + + err = svn_client_get_repos_root(url, NULL, path_or_url, + ctx, pool, subpool); + + /* close ra session */ + svn_pool_destroy(subpool); + return svn_error_trace(err); +} + +svn_error_t * +svn_client_url_from_path(const char **url, + const char *path_or_url, + apr_pool_t *pool) +{ + svn_client_ctx_t *ctx; + + SVN_ERR(svn_client_create_context(&ctx, pool)); + + return svn_client_url_from_path2(url, path_or_url, ctx, pool, pool); +} + +/*** From mergeinfo.c ***/ +svn_error_t * +svn_client_mergeinfo_log(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, + svn_log_entry_receiver_t receiver, + void *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) +{ + svn_opt_revision_t start_revision, end_revision; + + start_revision.kind = svn_opt_revision_unspecified; + end_revision.kind = svn_opt_revision_unspecified; + + return svn_client_mergeinfo_log2(finding_merged, + target_path_or_url, target_peg_revision, + source_path_or_url, source_peg_revision, + &start_revision, &end_revision, + receiver, receiver_baton, + discover_changed_paths, depth, revprops, + ctx, scratch_pool); +} + +svn_error_t * +svn_client_mergeinfo_log_merged(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const char *merge_source_path_or_url, + const svn_opt_revision_t *src_peg_revision, + svn_log_entry_receiver_t log_receiver, + void *log_receiver_baton, + svn_boolean_t discover_changed_paths, + const apr_array_header_t *revprops, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_mergeinfo_log(TRUE, path_or_url, peg_revision, + merge_source_path_or_url, + src_peg_revision, + log_receiver, log_receiver_baton, + discover_changed_paths, + svn_depth_empty, revprops, ctx, + pool); +} + +svn_error_t * +svn_client_mergeinfo_log_eligible(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const char *merge_source_path_or_url, + const svn_opt_revision_t *src_peg_revision, + svn_log_entry_receiver_t log_receiver, + void *log_receiver_baton, + svn_boolean_t discover_changed_paths, + const apr_array_header_t *revprops, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_mergeinfo_log(FALSE, path_or_url, peg_revision, + merge_source_path_or_url, + src_peg_revision, + log_receiver, log_receiver_baton, + discover_changed_paths, + svn_depth_empty, revprops, ctx, + pool); +} + +/*** From relocate.c ***/ +svn_error_t * +svn_client_relocate(const char *path, + const char *from_prefix, + const char *to_prefix, + svn_boolean_t recurse, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + if (! recurse) + SVN_ERR(svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Non-recursive relocation not supported"))); + return svn_client_relocate2(path, from_prefix, to_prefix, TRUE, ctx, pool); +} + +/*** From util.c ***/ +svn_error_t * +svn_client_commit_item_create(const svn_client_commit_item3_t **item, + apr_pool_t *pool) +{ + *item = svn_client_commit_item3_create(pool); + return SVN_NO_ERROR; +} + +svn_client_commit_item2_t * +svn_client_commit_item2_dup(const svn_client_commit_item2_t *item, + apr_pool_t *pool) +{ + svn_client_commit_item2_t *new_item = apr_palloc(pool, sizeof(*new_item)); + + *new_item = *item; + + if (new_item->path) + new_item->path = apr_pstrdup(pool, new_item->path); + + if (new_item->url) + new_item->url = apr_pstrdup(pool, new_item->url); + + if (new_item->copyfrom_url) + new_item->copyfrom_url = apr_pstrdup(pool, new_item->copyfrom_url); + + if (new_item->wcprop_changes) + new_item->wcprop_changes = svn_prop_array_dup(new_item->wcprop_changes, + pool); + + return new_item; +} + |