diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
commit | cf46733632c7279a9fd0fe6ce26f9185a4ae82a9 (patch) | |
tree | da27775a2161723ef342e91af41a8b51fedef405 /subversion/svnsync/svnsync.c | |
parent | bb0ef45f7c46b0ae221b26265ef98a768c33f820 (diff) | |
download | subversion-tarball-master.tar.gz |
subversion-1.9.7HEADsubversion-1.9.7master
Diffstat (limited to 'subversion/svnsync/svnsync.c')
-rw-r--r-- | subversion/svnsync/svnsync.c | 383 |
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; } |