summaryrefslogtreecommitdiff
path: root/subversion/svnsync/svnsync.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svnsync/svnsync.c')
-rw-r--r--subversion/svnsync/svnsync.c383
1 files changed, 256 insertions, 127 deletions
diff --git a/subversion/svnsync/svnsync.c b/subversion/svnsync/svnsync.c
index 621b782..6dde1f1 100644
--- a/subversion/svnsync/svnsync.c
+++ b/subversion/svnsync/svnsync.c
@@ -38,7 +38,6 @@
#include "private/svn_opt_private.h"
#include "private/svn_ra_private.h"
#include "private/svn_cmdline_private.h"
-#include "private/svn_subr_private.h"
#include "sync.h"
@@ -69,6 +68,8 @@ enum svnsync__opt {
svnsync_opt_disable_locking,
svnsync_opt_version,
svnsync_opt_trust_server_cert,
+ svnsync_opt_trust_server_cert_failures_src,
+ svnsync_opt_trust_server_cert_failures_dst,
svnsync_opt_allow_non_empty,
svnsync_opt_steal_lock
};
@@ -79,6 +80,8 @@ enum svnsync__opt {
svnsync_opt_auth_username, \
svnsync_opt_auth_password, \
svnsync_opt_trust_server_cert, \
+ svnsync_opt_trust_server_cert_failures_src, \
+ svnsync_opt_trust_server_cert_failures_dst, \
svnsync_opt_source_username, \
svnsync_opt_source_password, \
svnsync_opt_sync_username, \
@@ -113,7 +116,7 @@ static const svn_opt_subcommand_desc2_t svnsync_cmd_table[] =
"mirror of the source repository.\n"),
{ SVNSYNC_OPTS_DEFAULT, svnsync_opt_source_prop_encoding, 'q',
svnsync_opt_allow_non_empty, svnsync_opt_disable_locking,
- svnsync_opt_steal_lock } },
+ svnsync_opt_steal_lock, 'M' } },
{ "synchronize", synchronize_cmd, { "sync" },
N_("usage: svnsync synchronize DEST_URL [SOURCE_URL]\n"
"\n"
@@ -126,7 +129,7 @@ static const svn_opt_subcommand_desc2_t svnsync_cmd_table[] =
"if untrusted users/administrators may have write access to the\n"
"DEST_URL repository.\n"),
{ SVNSYNC_OPTS_DEFAULT, svnsync_opt_source_prop_encoding, 'q',
- svnsync_opt_disable_locking, svnsync_opt_steal_lock } },
+ svnsync_opt_disable_locking, svnsync_opt_steal_lock, 'M' } },
{ "copy-revprops", copy_revprops_cmd, { 0 },
N_("usage:\n"
"\n"
@@ -147,7 +150,7 @@ static const svn_opt_subcommand_desc2_t svnsync_cmd_table[] =
"\n"
"Form 2 is deprecated syntax, equivalent to specifying \"-rREV[:REV2]\".\n"),
{ SVNSYNC_OPTS_DEFAULT, svnsync_opt_source_prop_encoding, 'q', 'r',
- svnsync_opt_disable_locking, svnsync_opt_steal_lock } },
+ svnsync_opt_disable_locking, svnsync_opt_steal_lock, 'M' } },
{ "info", info_cmd, { 0 },
N_("usage: svnsync info DEST_URL\n"
"\n"
@@ -195,11 +198,37 @@ static const apr_getopt_option_t svnsync_options[] =
" "
"see --source-password and --sync-password)") },
{"trust-server-cert", svnsync_opt_trust_server_cert, 0,
- N_("accept SSL server certificates from unknown\n"
+ N_("deprecated; same as\n"
+ " "
+ "--source-trust-server-cert-failures=unknown-ca\n"
+ " "
+ "--sync-trust-server-cert-failures=unknown-ca")},
+ {"source-trust-server-cert-failures", svnsync_opt_trust_server_cert_failures_src, 1,
+ N_("with --non-interactive, accept SSL\n"
+ " "
+ "server certificates with failures.\n"
+ " "
+ "ARG is a comma-separated list of:\n"
+ " "
+ "- 'unknown-ca' (Unknown Authority)\n"
+ " "
+ "- 'cn-mismatch' (Hostname mismatch)\n"
+ " "
+ "- 'expired' (Expired certificate)\n"
+ " "
+ "- 'not-yet-valid' (Not yet valid certificate)\n"
+ " "
+ "- 'other' (all other not separately classified\n"
+ " "
+ " certificate errors).\n"
+ " "
+ "Applied to the source URL.")},
+ {"sync-trust-server-cert-failures", svnsync_opt_trust_server_cert_failures_dst, 1,
+ N_("Like\n"
" "
- "certificate authorities without prompting (but only\n"
+ "--source-trust-server-cert-failures,\n"
" "
- "with '--non-interactive')") },
+ "but applied to the destination URL.")},
{"source-username", svnsync_opt_source_username, 1,
N_("connect to source repository with username ARG") },
{"source-password", svnsync_opt_source_password, 1,
@@ -238,6 +267,10 @@ static const apr_getopt_option_t svnsync_options[] =
"and is not being concurrently accessed by another\n"
" "
"svnsync instance.")},
+ {"memory-cache-size", 'M', 1,
+ N_("size of the extra in-memory cache in MB used to\n"
+ " "
+ "minimize operations for local 'file' scheme.\n")},
{"version", svnsync_opt_version, 0,
N_("show program version information")},
{"help", 'h', 0,
@@ -249,7 +282,13 @@ static const apr_getopt_option_t svnsync_options[] =
typedef struct opt_baton_t {
svn_boolean_t non_interactive;
- svn_boolean_t trust_server_cert;
+ struct {
+ svn_boolean_t trust_server_cert_unknown_ca;
+ svn_boolean_t trust_server_cert_cn_mismatch;
+ svn_boolean_t trust_server_cert_expired;
+ svn_boolean_t trust_server_cert_not_yet_valid;
+ svn_boolean_t trust_server_cert_other_failure;
+ } src_trust, dst_trust;
svn_boolean_t no_auth_cache;
svn_auth_baton_t *source_auth_baton;
svn_auth_baton_t *sync_auth_baton;
@@ -483,7 +522,7 @@ remove_props_not_in_source(svn_ra_session_t *session,
hi;
hi = apr_hash_next(hi))
{
- const char *propname = svn__apr_hash_index_key(hi);
+ const char *propname = apr_hash_this_key(hi);
svn_pool_clear(subpool);
@@ -527,8 +566,8 @@ filter_props(int *filtered_count, apr_hash_t *props,
for (hi = apr_hash_first(pool, props); hi ; hi = apr_hash_next(hi))
{
- const char *propname = svn__apr_hash_index_key(hi);
- void *propval = svn__apr_hash_index_val(hi);
+ const char *propname = apr_hash_this_key(hi);
+ void *propval = apr_hash_this_val(hi);
/* Copy all properties:
- not matching the exclude pattern if provided OR
@@ -569,8 +608,8 @@ write_revprops(int *filtered_count,
for (hi = apr_hash_first(pool, rev_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);
+ const char *propname = apr_hash_this_key(hi);
+ const svn_string_t *propval = apr_hash_this_val(hi);
svn_pool_clear(subpool);
@@ -729,8 +768,10 @@ open_target_session(svn_ra_session_t **to_session_p,
/*** `svnsync init' ***/
/* Initialize the repository associated with RA session TO_SESSION,
- * using information found in BATON, while the repository is
- * locked. Implements `with_locked_func_t' interface.
+ * using information found in BATON.
+ *
+ * Implements `with_locked_func_t' interface. The caller has
+ * acquired a lock on the repository if locking is needed.
*/
static svn_error_t *
do_initialize(svn_ra_session_t *to_session,
@@ -937,7 +978,8 @@ open_source_session(svn_ra_session_t **from_session,
/* ### TODO: Should we validate that FROM_URL_STR->data matches any
provided FROM_URL here? */
if (! from_url)
- from_url = from_url_str->data;
+ SVN_ERR(svn_opt__arg_canonicalize_url(&from_url, from_url_str->data,
+ pool));
/* Open the session to copy the revision data. */
SVN_ERR(svn_ra_open4(from_session, NULL, from_url, from_uuid_str->data,
@@ -967,14 +1009,18 @@ open_target_session(svn_ra_session_t **target_session_p,
typedef struct replay_baton_t {
svn_ra_session_t *from_session;
svn_ra_session_t *to_session;
- /* Extra 'backdoor' session for fetching data *from* the target repo. */
- svn_ra_session_t *extra_to_session;
svn_revnum_t current_revision;
subcommand_baton_t *sb;
svn_boolean_t has_commit_revprops_capability;
+ svn_boolean_t has_atomic_revprops_capability;
int normalized_rev_props_count;
int normalized_node_props_count;
const char *to_root;
+
+#ifdef ENABLE_EV2_SHIMS
+ /* Extra 'backdoor' session for fetching data *from* the target repo. */
+ svn_ra_session_t *extra_to_session;
+#endif
} replay_baton_t;
/* Return a replay baton allocated from POOL and populated with
@@ -1051,7 +1097,7 @@ filter_include_log(const char *key)
return ! filter_exclude_log(key);
}
-
+#ifdef ENABLE_EV2_SHIMS
static svn_error_t *
fetch_base_func(const char **filename,
void *baton,
@@ -1179,6 +1225,7 @@ get_shim_callbacks(replay_baton_t *rb,
return callbacks;
}
+#endif
/* Callback function for svn_ra_replay_range, invoked when starting to parse
@@ -1247,8 +1294,10 @@ replay_rev_started(svn_revnum_t revision,
rb->sb->source_prop_encoding, pool));
rb->normalized_rev_props_count += normalized_count;
+#ifdef ENABLE_EV2_SHIMS
SVN_ERR(svn_ra__register_editor_shim_callbacks(rb->to_session,
get_shim_callbacks(rb, pool)));
+#endif
SVN_ERR(svn_ra_get_commit_editor3(rb->to_session, &commit_editor,
&commit_baton,
filtered,
@@ -1291,6 +1340,7 @@ replay_rev_finished(svn_revnum_t revision,
apr_hash_t *filtered, *existing_props;
int filtered_count;
int normalized_count;
+ const svn_string_t *rev_str;
SVN_ERR(editor->close_edit(edit_baton, pool));
@@ -1330,21 +1380,24 @@ replay_rev_finished(svn_revnum_t revision,
svn_pool_clear(subpool);
+ rev_str = svn_string_createf(subpool, "%ld", revision);
+
/* Ok, we're done, bring the last-merged-rev property up to date. */
SVN_ERR(svn_ra_change_rev_prop2(
rb->to_session,
0,
SVNSYNC_PROP_LAST_MERGED_REV,
NULL,
- svn_string_create(apr_psprintf(pool, "%ld", revision),
- subpool),
+ rev_str,
subpool));
/* And finally drop the currently copying prop, since we're done
with this revision. */
SVN_ERR(svn_ra_change_rev_prop2(rb->to_session, 0,
SVNSYNC_PROP_CURRENTLY_COPYING,
- NULL, NULL, subpool));
+ rb->has_atomic_revprops_capability
+ ? &rev_str : NULL,
+ NULL, subpool));
/* Notify the user that we copied revision properties. */
if (! rb->sb->quiet)
@@ -1356,8 +1409,10 @@ replay_rev_finished(svn_revnum_t revision,
}
/* Synchronize the repository associated with RA session TO_SESSION,
- * using information found in BATON, while the repository is
- * locked. Implements `with_locked_func_t' interface.
+ * using information found in BATON.
+ *
+ * Implements `with_locked_func_t' interface. The caller has
+ * acquired a lock on the repository if locking is needed.
*/
static svn_error_t *
do_synchronize(svn_ra_session_t *to_session,
@@ -1474,6 +1529,11 @@ do_synchronize(svn_ra_session_t *to_session,
SVN_RA_CAPABILITY_COMMIT_REVPROPS,
pool));
+ SVN_ERR(svn_ra_has_capability(rb->to_session,
+ &rb->has_atomic_revprops_capability,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
+
start_revision = last_merged + 1;
end_revision = from_latest;
@@ -1545,8 +1605,10 @@ synchronize_cmd(apr_getopt_t *os, void *b, apr_pool_t *pool)
/*** `svnsync copy-revprops' ***/
/* Copy revision properties to the repository associated with RA
- * session TO_SESSION, using information found in BATON, while the
- * repository is locked. Implements `with_locked_func_t' interface.
+ * session TO_SESSION, using information found in BATON.
+ *
+ * Implements `with_locked_func_t' interface. The caller has
+ * acquired a lock on the repository if locking is needed.
*/
static svn_error_t *
do_copy_revprops(svn_ra_session_t *to_session,
@@ -1848,6 +1910,7 @@ help_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
const char *header =
_("general usage: svnsync SUBCOMMAND DEST_URL [ARGS & OPTIONS ...]\n"
+ "Subversion repository replication tool.\n"
"Type 'svnsync help <subcommand>' for help on a specific subcommand.\n"
"Type 'svnsync --version' to see the program version and RA modules.\n"
"\n"
@@ -1876,8 +1939,13 @@ help_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
/*** Main ***/
-int
-main(int argc, const char *argv[])
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
const svn_opt_subcommand_desc2_t *subcommand = NULL;
apr_array_header_t *received_opts;
@@ -1885,7 +1953,6 @@ main(int argc, const char *argv[])
svn_config_t *config;
apr_status_t apr_err;
apr_getopt_t *os;
- apr_pool_t *pool;
svn_error_t *err;
int opt_id, i;
const char *username = NULL, *source_username = NULL, *sync_username = NULL;
@@ -1894,23 +1961,10 @@ main(int argc, const char *argv[])
const char *source_prop_encoding = NULL;
svn_boolean_t force_interactive = FALSE;
- if (svn_cmdline_init("svnsync", stderr) != EXIT_SUCCESS)
- {
- return EXIT_FAILURE;
- }
+ /* Check library versions */
+ SVN_ERR(check_lib_versions());
- err = check_lib_versions();
- if (err)
- return svn_cmdline_handle_exit_error(err, NULL, "svnsync: ");
-
- /* Create our top-level pool. Use a separate mutexless allocator,
- * given this application is single threaded.
- */
- pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
-
- err = svn_ra_initialize(pool);
- if (err)
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ SVN_ERR(svn_ra_initialize(pool));
/* Initialize the option baton. */
memset(&opt_baton, 0, sizeof(opt_baton));
@@ -1921,14 +1975,12 @@ main(int argc, const char *argv[])
if (argc <= 1)
{
- SVN_INT_ERR(help_cmd(NULL, NULL, pool));
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
+ SVN_ERR(help_cmd(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
- err = svn_cmdline__getopt_init(&os, argc, argv, pool);
- if (err)
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
os->interleave = 1;
@@ -1942,9 +1994,9 @@ main(int argc, const char *argv[])
break;
else if (apr_err)
{
- SVN_INT_ERR(help_cmd(NULL, NULL, pool));
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
+ SVN_ERR(help_cmd(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
APR_ARRAY_PUSH(received_opts, int) = opt_id;
@@ -1959,8 +2011,31 @@ main(int argc, const char *argv[])
force_interactive = TRUE;
break;
- case svnsync_opt_trust_server_cert:
- opt_baton.trust_server_cert = TRUE;
+ case svnsync_opt_trust_server_cert: /* backwards compat */
+ opt_baton.src_trust.trust_server_cert_unknown_ca = TRUE;
+ opt_baton.dst_trust.trust_server_cert_unknown_ca = TRUE;
+ break;
+
+ case svnsync_opt_trust_server_cert_failures_src:
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_trust_options(
+ &opt_baton.src_trust.trust_server_cert_unknown_ca,
+ &opt_baton.src_trust.trust_server_cert_cn_mismatch,
+ &opt_baton.src_trust.trust_server_cert_expired,
+ &opt_baton.src_trust.trust_server_cert_not_yet_valid,
+ &opt_baton.src_trust.trust_server_cert_other_failure,
+ opt_arg, pool));
+ break;
+
+ case svnsync_opt_trust_server_cert_failures_dst:
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_trust_options(
+ &opt_baton.dst_trust.trust_server_cert_unknown_ca,
+ &opt_baton.dst_trust.trust_server_cert_cn_mismatch,
+ &opt_baton.dst_trust.trust_server_cert_expired,
+ &opt_baton.dst_trust.trust_server_cert_not_yet_valid,
+ &opt_baton.dst_trust.trust_server_cert_other_failure,
+ opt_arg, pool));
break;
case svnsync_opt_no_auth_cache:
@@ -2006,12 +2081,10 @@ main(int argc, const char *argv[])
apr_array_make(pool, 1,
sizeof(svn_cmdline__config_argument_t*));
- err = svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool);
- if (!err)
- err = svn_cmdline__parse_config_option(config_options,
- opt_arg, pool);
- if (err)
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_config_option(config_options,
+ opt_arg, "svnsync: ",
+ pool));
break;
case svnsync_opt_source_prop_encoding:
@@ -2045,13 +2118,11 @@ main(int argc, const char *argv[])
opt_arg, pool) != 0)
{
const char *utf8_opt_arg;
- err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
- if (! err)
- err = svn_error_createf(
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ return svn_error_createf(
SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Syntax error in revision argument '%s'"),
utf8_opt_arg);
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
}
/* We only allow numbers and 'HEAD'. */
@@ -2061,13 +2132,28 @@ main(int argc, const char *argv[])
(opt_baton.end_rev.kind != svn_opt_revision_head) &&
(opt_baton.end_rev.kind != svn_opt_revision_unspecified)))
{
- err = svn_error_createf(
+ return svn_error_createf(
SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Invalid revision range '%s' provided"), opt_arg);
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
}
break;
+ case 'M':
+ if (!config_options)
+ config_options =
+ apr_array_make(pool, 1,
+ sizeof(svn_cmdline__config_argument_t*));
+
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_config_option(
+ config_options,
+ apr_psprintf(pool,
+ "config:miscellany:memory-cache-size=%s",
+ opt_arg),
+ NULL /* won't be used */,
+ pool));
+ break;
+
case '?':
case 'h':
opt_baton.help = TRUE;
@@ -2075,14 +2161,14 @@ main(int argc, const char *argv[])
default:
{
- SVN_INT_ERR(help_cmd(NULL, NULL, pool));
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
+ SVN_ERR(help_cmd(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
}
- if(opt_err)
- return svn_cmdline_handle_exit_error(opt_err, pool, "svnsync: ");
+ if (opt_err)
+ return opt_err;
}
if (opt_baton.help)
@@ -2092,10 +2178,9 @@ main(int argc, const char *argv[])
* exclusive. */
if (opt_baton.non_interactive && force_interactive)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--non-interactive and --force-interactive "
- "are mutually exclusive"));
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--non-interactive and --force-interactive "
+ "are mutually exclusive"));
}
else
opt_baton.non_interactive = !svn_cmdline__be_interactive(
@@ -2109,12 +2194,11 @@ main(int argc, const char *argv[])
&& (source_username || sync_username
|| source_password || sync_password))
{
- err = svn_error_create
+ return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Cannot use --username or --password with any of "
"--source-username, --source-password, --sync-username, "
"or --sync-password.\n"));
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
}
if (username)
{
@@ -2134,24 +2218,32 @@ main(int argc, const char *argv[])
/* Disallow mixing of --steal-lock and --disable-locking. */
if (opt_baton.steal_lock && opt_baton.disable_locking)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--disable-locking and --steal-lock are "
- "mutually exclusive"));
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--disable-locking and --steal-lock are "
+ "mutually exclusive"));
}
- /* --trust-server-cert can only be used with --non-interactive */
- if (opt_baton.trust_server_cert && !opt_baton.non_interactive)
+ /* --trust-* can only be used with --non-interactive */
+ if (!opt_baton.non_interactive)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-server-cert requires "
- "--non-interactive"));
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ if (opt_baton.src_trust.trust_server_cert_unknown_ca
+ || opt_baton.src_trust.trust_server_cert_cn_mismatch
+ || opt_baton.src_trust.trust_server_cert_expired
+ || opt_baton.src_trust.trust_server_cert_not_yet_valid
+ || opt_baton.src_trust.trust_server_cert_other_failure
+ || opt_baton.dst_trust.trust_server_cert_unknown_ca
+ || opt_baton.dst_trust.trust_server_cert_cn_mismatch
+ || opt_baton.dst_trust.trust_server_cert_expired
+ || opt_baton.dst_trust.trust_server_cert_not_yet_valid
+ || opt_baton.dst_trust.trust_server_cert_other_failure)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--source-trust-server-cert-failures "
+ "and "
+ "--sync-trust-server-cert-failures require "
+ "--non-interactive"));
}
- err = svn_config_ensure(opt_baton.config_dir, pool);
- if (err)
- return svn_cmdline_handle_exit_error(err, pool, "synsync: ");
+ SVN_ERR(svn_config_ensure(opt_baton.config_dir, pool));
if (subcommand == NULL)
{
@@ -2170,9 +2262,9 @@ main(int argc, const char *argv[])
}
else
{
- SVN_INT_ERR(help_cmd(NULL, NULL, pool));
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
+ SVN_ERR(help_cmd(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
}
else
@@ -2182,9 +2274,9 @@ main(int argc, const char *argv[])
first_arg);
if (subcommand == NULL)
{
- SVN_INT_ERR(help_cmd(NULL, NULL, pool));
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
+ SVN_ERR(help_cmd(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
}
}
@@ -2205,23 +2297,20 @@ main(int argc, const char *argv[])
svn_opt_format_option(&optstr, badopt, FALSE, pool);
if (subcommand->name[0] == '-')
{
- SVN_INT_ERR(help_cmd(NULL, NULL, pool));
+ SVN_ERR(help_cmd(NULL, NULL, pool));
}
else
{
- err = svn_error_createf
+ return svn_error_createf
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Subcommand '%s' doesn't accept option '%s'\n"
"Type 'svnsync help %s' for usage.\n"),
subcommand->name, optstr, subcommand->name);
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
}
}
}
- err = svn_config_get_config(&opt_baton.config, opt_baton.config_dir, pool);
- if (err)
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ SVN_ERR(svn_config_get_config(&opt_baton.config, opt_baton.config_dir, pool));
/* Update the options in the config */
if (config_options)
@@ -2263,27 +2352,37 @@ main(int argc, const char *argv[])
apr_signal(SIGXFSZ, SIG_IGN);
#endif
- err = svn_cmdline_create_auth_baton(&opt_baton.source_auth_baton,
- opt_baton.non_interactive,
- opt_baton.source_username,
- opt_baton.source_password,
- opt_baton.config_dir,
- opt_baton.no_auth_cache,
- opt_baton.trust_server_cert,
- config,
- check_cancel, NULL,
- pool);
+ err = svn_cmdline_create_auth_baton2(
+ &opt_baton.source_auth_baton,
+ opt_baton.non_interactive,
+ opt_baton.source_username,
+ opt_baton.source_password,
+ opt_baton.config_dir,
+ opt_baton.no_auth_cache,
+ opt_baton.src_trust.trust_server_cert_unknown_ca,
+ opt_baton.src_trust.trust_server_cert_cn_mismatch,
+ opt_baton.src_trust.trust_server_cert_expired,
+ opt_baton.src_trust.trust_server_cert_not_yet_valid,
+ opt_baton.src_trust.trust_server_cert_other_failure,
+ config,
+ check_cancel, NULL,
+ pool);
if (! err)
- err = svn_cmdline_create_auth_baton(&opt_baton.sync_auth_baton,
- opt_baton.non_interactive,
- opt_baton.sync_username,
- opt_baton.sync_password,
- opt_baton.config_dir,
- opt_baton.no_auth_cache,
- opt_baton.trust_server_cert,
- config,
- check_cancel, NULL,
- pool);
+ err = svn_cmdline_create_auth_baton2(
+ &opt_baton.sync_auth_baton,
+ opt_baton.non_interactive,
+ opt_baton.sync_username,
+ opt_baton.sync_password,
+ opt_baton.config_dir,
+ opt_baton.no_auth_cache,
+ opt_baton.dst_trust.trust_server_cert_unknown_ca,
+ opt_baton.dst_trust.trust_server_cert_cn_mismatch,
+ opt_baton.dst_trust.trust_server_cert_expired,
+ opt_baton.dst_trust.trust_server_cert_not_yet_valid,
+ opt_baton.dst_trust.trust_server_cert_other_failure,
+ config,
+ check_cancel, NULL,
+ pool);
if (! err)
err = (*subcommand->cmd_func)(os, &opt_baton, pool);
if (err)
@@ -2297,10 +2396,40 @@ main(int argc, const char *argv[])
_("Try 'svnsync help' for more info"));
}
- return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ return err;
}
- svn_pool_destroy(pool);
+ return SVN_NO_ERROR;
+}
- return EXIT_SUCCESS;
+int
+main(int argc, const char *argv[])
+{
+ apr_pool_t *pool;
+ int exit_code = EXIT_SUCCESS;
+ svn_error_t *err;
+
+ /* Initialize the app. */
+ if (svn_cmdline_init("svnsync", stderr) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ /* Create our top-level pool. Use a separate mutexless allocator,
+ * given this application is single threaded.
+ */
+ pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+
+ err = sub_main(&exit_code, argc, argv, pool);
+
+ /* Flush stdout and report if it fails. It would be flushed on exit anyway
+ but this makes sure that output is not silently lost if it fails. */
+ err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
+
+ if (err)
+ {
+ exit_code = EXIT_FAILURE;
+ svn_cmdline_handle_exit_error(err, NULL, "svnsync: ");
+ }
+
+ svn_pool_destroy(pool);
+ return exit_code;
}