Hey there! Sorry for the long delay! I've finally amended the patch to make the recommended fixes.
Thanks
Index: subversion/include/svn_io.h =================================================================== --- subversion/include/svn_io.h (revisión: 1818629) +++ subversion/include/svn_io.h (copia de trabajo) @@ -2633,6 +2633,15 @@ apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/** Reads a string from stdin until a newline or EOF is found + * + * @since New in 1.10. + */ +svn_error_t * +svn_io_stdin_readline(const char **result, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** @} */ #ifdef __cplusplus Index: subversion/libsvn_subr/io.c =================================================================== --- subversion/libsvn_subr/io.c (revisión: 1818629) +++ subversion/libsvn_subr/io.c (copia de trabajo) @@ -5440,3 +5440,20 @@ return SVN_NO_ERROR; } + +svn_error_t * +svn_io_stdin_readline(const char **result, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *buf = NULL; + svn_stream_t *stdin = NULL; + svn_boolean_t oob = FALSE; + + SVN_ERR(svn_stream_for_stdin2(&stdin, TRUE, scratch_pool)); + SVN_ERR(svn_stream_readline(stdin, &buf, APR_EOL_STR, &oob, result_pool)); + + *result = buf->data; + + return SVN_NO_ERROR; +} Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revisión: 1818629) +++ subversion/svn/cl.h (copia de trabajo) @@ -178,6 +178,7 @@ svn_boolean_t help; /* print usage message */ const char *auth_username; /* auth username */ const char *auth_password; /* auth password */ + svn_boolean_t auth_password_from_stdin; /* read password from stdin */ const char *extensions; /* subprocess extension args */ apr_array_header_t *targets; /* target list from file */ svn_boolean_t xml; /* output in xml, e.g., "svn log --xml" */ Index: subversion/svn/svn.c =================================================================== --- subversion/svn/svn.c (revisión: 1818629) +++ subversion/svn/svn.c (copia de trabajo) @@ -68,6 +68,7 @@ use the short option letter as identifier. */ typedef enum svn_cl__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_autoprops, opt_changelist, @@ -203,6 +204,9 @@ N_("specify a password ARG (caution: on many operating\n" " " "systems, other users will be able to see this)")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"extensions", 'x', 1, N_("Specify differencing options for external diff or\n" " " @@ -504,7 +508,8 @@ command to take these arguments allows scripts to just pass them willy-nilly to every invocation of 'svn') . */ const int svn_cl__global_options[] = -{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive, +{ opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_force_interactive, opt_trust_server_cert, opt_trust_server_cert_failures, opt_config_dir, opt_config_options, 0 @@ -2036,6 +2041,7 @@ apr_hash_t *changelists; apr_hash_t *cfg_hash; svn_membuf_t buf; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -2331,6 +2337,9 @@ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_encoding: opt_state.encoding = apr_pstrdup(pool, opt_arg); break; @@ -2827,6 +2836,14 @@ "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* Disallow simultaneous use of both --diff-cmd and --internal-diff. */ if (opt_state.diff.diff_cmd && opt_state.diff.internal_diff) @@ -3117,6 +3134,12 @@ conflict_stats, pool)); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Set up our cancellation support. */ svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; Index: subversion/svnbench/svnbench.c =================================================================== --- subversion/svnbench/svnbench.c (revisión: 1818629) +++ subversion/svnbench/svnbench.c (copia de trabajo) @@ -53,6 +53,7 @@ use the short option letter as identifier. */ typedef enum svn_cl__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_config_dir, opt_config_options, @@ -112,6 +113,8 @@ {"verbose", 'v', 0, N_("print extra information")}, {"username", opt_auth_username, 1, N_("specify a username ARG")}, {"password", opt_auth_password, 1, N_("specify a password ARG")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, N_("read password from stdin")}, {"targets", opt_targets, 1, N_("pass contents of file ARG as additional args")}, {"depth", opt_depth, 1, @@ -197,7 +200,8 @@ command to take these arguments allows scripts to just pass them willy-nilly to every invocation of 'svn') . */ const int svn_cl__global_options[] = -{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive, +{ opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_trust_server_cert, opt_trust_server_cert_failures, opt_config_dir, opt_config_options, 0 }; @@ -394,6 +398,7 @@ apr_time_t start_time, time_taken; ra_progress_baton_t ra_progress_baton = {0}; svn_membuf_t buf; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -625,6 +630,9 @@ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_stop_on_copy: opt_state.stop_on_copy = TRUE; break; @@ -842,6 +850,14 @@ "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* Ensure that 'revision_ranges' has at least one item, and make 'start_revision' and 'end_revision' match that item. */ if (opt_state.revision_ranges->nelts == 0) @@ -919,6 +935,12 @@ pool)); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Set up our cancellation support. */ svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; Index: subversion/svnmucc/svnmucc.c =================================================================== --- subversion/svnmucc/svnmucc.c (revisión: 1818629) +++ subversion/svnmucc/svnmucc.c (copia de trabajo) @@ -297,6 +297,7 @@ " -F [--file] ARG : read log message from file ARG\n" " -u [--username] ARG : commit the changes as username ARG\n" " -p [--password] ARG : use ARG as the password\n" + " --password-from-stdin : read password from stdin\n" " -U [--root-url] ARG : interpret all action URLs relative to ARG\n" " -r [--revision] ARG : use revision ARG as baseline for changes\n" " --with-revprop ARG : set revision property in the following format:\n" @@ -480,7 +481,8 @@ non_interactive_opt, force_interactive_opt, trust_server_cert_opt, - trust_server_cert_failures_opt + trust_server_cert_failures_opt, + password_from_stdin_opt }; static const apr_getopt_option_t options[] = { {"message", 'm', 1, ""}, @@ -487,6 +489,7 @@ {"file", 'F', 1, ""}, {"username", 'u', 1, ""}, {"password", 'p', 1, ""}, + {"password-from-stdin", password_from_stdin_opt, 0, ""}, {"root-url", 'U', 1, ""}, {"revision", 'r', 1, ""}, {"with-revprop", with_revprop_opt, 1, ""}, @@ -527,6 +530,7 @@ svn_client_ctx_t *ctx; struct log_message_baton lmb; int i; + svn_boolean_t read_pass_from_stdin = FALSE; /* Check library versions */ SVN_ERR(check_lib_versions()); @@ -572,6 +576,9 @@ case 'p': password = apr_pstrdup(pool, arg); break; + case password_from_stdin_opt: + read_pass_from_stdin = TRUE; + break; case 'U': SVN_ERR(svn_utf_cstring_to_utf8(&root_url, arg, pool)); if (! svn_path_is_url(root_url)) @@ -672,6 +679,15 @@ "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + + /* Copy the rest of our command-line arguments to an array, UTF-8-ing them along the way. */ action_args = apr_array_make(pool, opts->argc, sizeof(const char *)); @@ -721,6 +737,12 @@ "svnmucc: ", "--config-option")); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&password, pool, pool)); + } + SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG); Index: subversion/svnrdump/svnrdump.c =================================================================== --- subversion/svnrdump/svnrdump.c (revisión: 1818629) +++ subversion/svnrdump/svnrdump.c (copia de trabajo) @@ -59,6 +59,7 @@ opt_config_option, opt_auth_username, opt_auth_password, + opt_auth_password_from_stdin, opt_auth_nocache, opt_non_interactive, opt_skip_revprop, @@ -73,6 +74,7 @@ opt_config_option, \ opt_auth_username, \ opt_auth_password, \ + opt_auth_password_from_stdin, \ opt_auth_nocache, \ opt_trust_server_cert, \ opt_trust_server_cert_failures, \ @@ -114,6 +116,8 @@ N_("specify a username ARG")}, {"password", opt_auth_password, 1, N_("specify a password ARG")}, + {"password-from-stdin", opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"non-interactive", opt_non_interactive, 0, N_("do no interactive prompting (default is to prompt\n" " " @@ -154,6 +158,7 @@ "valid certificate) and 'other' (all other not\n" " " "separately classified certificate errors).")}, + {"dumpfile", 'F', 1, N_("Read or write to a dumpfile instead of stdin/stdout")}, {0, 0, 0, 0} }; @@ -174,6 +179,7 @@ svn_client_ctx_t *ctx; svn_ra_session_t *session; const char *url; + const char *dumpfile; svn_boolean_t help; svn_boolean_t version; svn_opt_revision_t start_revision; @@ -463,31 +469,39 @@ svn_revnum_t end_revision, svn_boolean_t quiet, svn_boolean_t incremental, + const char *dumpfile, apr_pool_t *pool) { struct replay_baton *replay_baton; const char *uuid; - svn_stream_t *stdout_stream; + svn_stream_t *output_stream; - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); + if (dumpfile) + { + SVN_ERR(svn_stream_open_writable(&output_stream, dumpfile, pool, pool)); + } + else + { + SVN_ERR(svn_stream_for_stdout(&output_stream, pool)); + } replay_baton = apr_pcalloc(pool, sizeof(*replay_baton)); - replay_baton->stdout_stream = stdout_stream; + replay_baton->stdout_stream = output_stream; replay_baton->extra_ra_session = extra_ra_session; replay_baton->quiet = quiet; /* Write the magic header and UUID */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(output_stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", SVN_REPOS_DUMPFILE_FORMAT_VERSION)); SVN_ERR(svn_ra_get_uuid2(session, &uuid, pool)); - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(output_stream, pool, SVN_REPOS_DUMPFILE_UUID ": %s\n\n", uuid)); /* Fake revision 0 if necessary */ if (start_revision == 0) { - SVN_ERR(dump_revision_header(session, stdout_stream, + SVN_ERR(dump_revision_header(session, output_stream, start_revision, pool)); /* Revision 0 has no tree changes, so we're done. */ @@ -506,7 +520,7 @@ if (!incremental) { SVN_ERR(dump_initial_full_revision(session, extra_ra_session, - stdout_stream, start_revision, + output_stream, start_revision, quiet, pool)); start_revision++; } @@ -538,16 +552,23 @@ static svn_error_t * load_revisions(svn_ra_session_t *session, svn_ra_session_t *aux_session, - const char *url, + const char *dumpfile, svn_boolean_t quiet, apr_hash_t *skip_revprops, apr_pool_t *pool) { - svn_stream_t *stdin_stream; + svn_stream_t *output_stream; - SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, pool)); + if (dumpfile) + { + SVN_ERR(svn_stream_open_readonly(&output_stream, dumpfile, pool, pool)); + } + else + { + SVN_ERR(svn_stream_for_stdin2(&output_stream, TRUE, pool)); + } - SVN_ERR(svn_rdump__load_dumpstream(stdin_stream, session, aux_session, + SVN_ERR(svn_rdump__load_dumpstream(output_stream, session, aux_session, quiet, skip_revprops, check_cancel, NULL, pool)); @@ -616,7 +637,8 @@ return replay_revisions(opt_baton->session, extra_ra_session, opt_baton->start_revision.value.number, opt_baton->end_revision.value.number, - opt_baton->quiet, opt_baton->incremental, pool); + opt_baton->quiet, opt_baton->incremental, + opt_baton->dumpfile, pool); } /* Handle the "load" subcommand. Implements `svn_opt_subcommand_t'. */ @@ -630,8 +652,9 @@ SVN_ERR(svn_client_open_ra_session2(&aux_session, opt_baton->url, NULL, opt_baton->ctx, pool, pool)); - return load_revisions(opt_baton->session, aux_session, opt_baton->url, - opt_baton->quiet, opt_baton->skip_revprops, pool); + return load_revisions(opt_baton->session, aux_session, + opt_baton->dumpfile, opt_baton->quiet, + opt_baton->skip_revprops, pool); } /* Handle the "help" subcommand. Implements `svn_opt_subcommand_t'. */ @@ -772,6 +795,7 @@ apr_getopt_t *os; apr_array_header_t *received_opts; int i; + svn_boolean_t read_pass_from_stdin = FALSE; opt_baton = apr_pcalloc(pool, sizeof(*opt_baton)); opt_baton->start_revision.kind = svn_opt_revision_unspecified; @@ -778,6 +802,7 @@ opt_baton->end_revision.kind = svn_opt_revision_unspecified; opt_baton->url = NULL; opt_baton->skip_revprops = apr_hash_make(pool); + opt_baton->dumpfile = NULL; SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); @@ -850,6 +875,9 @@ case opt_auth_password: SVN_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_auth_nocache: no_auth_cache = TRUE; break; @@ -890,6 +918,11 @@ opt_arg, "svnrdump: ", pool)); + break; + case 'F': + SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool)); + opt_baton->dumpfile = opt_arg; + break; } } @@ -1005,6 +1038,24 @@ "--non-interactive")); } + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + + if (strcmp(subcommand->name, "load") == 0) + { + if (read_pass_from_stdin && opt_baton->dumpfile == NULL) + { + /* error here, since load cannot process a password over stdin */ + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("load subcommand with " + "--password-from-stdin requires -F")); + } + } + /* Expect one more non-option argument: the repository URL. */ if (os->ind != os->argc - 1) { @@ -1039,6 +1090,12 @@ force_interactive = (username == NULL || password == NULL); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&password, pool, pool)); + } + non_interactive = !svn_cmdline__be_interactive(non_interactive, force_interactive); Index: subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout =================================================================== --- subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (revisión: 1818629) +++ subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (copia de trabajo) @@ -135,6 +135,7 @@ --username ARG : specify a username ARG --password ARG : specify a password ARG (caution: on many operating systems, other users will be able to see this) + --password-from-stdin : read password from stdin --no-auth-cache : do not cache authentication tokens --non-interactive : do no interactive prompting (default is to prompt only if standard input is a terminal device) @@ -225,6 +226,7 @@ --username ARG : specify a username ARG --password ARG : specify a password ARG (caution: on many operating systems, other users will be able to see this) + --password-from-stdin : read password from stdin --no-auth-cache : do not cache authentication tokens --non-interactive : do no interactive prompting (default is to prompt only if standard input is a terminal device) Index: tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c =================================================================== --- tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c (revisión: 1818629) +++ tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c (copia de trabajo) @@ -68,6 +68,7 @@ use the short option letter as identifier. */ typedef enum svn_min__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_config_dir, opt_config_options, @@ -113,6 +114,9 @@ N_("specify a password ARG (caution: on many operating\n" " " "systems, other users will be able to see this)")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"targets", opt_targets, 1, N_("pass contents of file ARG as additional args")}, {"depth", opt_depth, 1, @@ -209,11 +213,11 @@ command to take these arguments allows scripts to just pass them willy-nilly to every invocation of 'svn') . */ const int svn_min__global_options[] = -{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive, - opt_force_interactive, opt_trust_server_cert, - opt_trust_server_cert_unknown_ca, opt_trust_server_cert_cn_mismatch, - opt_trust_server_cert_expired, opt_trust_server_cert_not_yet_valid, - opt_trust_server_cert_other_failure, +{ opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_force_interactive, + opt_trust_server_cert, opt_trust_server_cert_unknown_ca, + opt_trust_server_cert_cn_mismatch, opt_trust_server_cert_expired, + opt_trust_server_cert_not_yet_valid, opt_trust_server_cert_other_failure, opt_config_dir, opt_config_options, 0 }; @@ -417,6 +421,7 @@ svn_boolean_t interactive_conflicts = FALSE; svn_boolean_t force_interactive = FALSE; apr_hash_t *cfg_hash; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -528,6 +533,9 @@ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_no_auth_cache: opt_state.no_auth_cache = TRUE; break; @@ -606,6 +614,14 @@ opt_state.non_interactive, force_interactive); + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* ### This really belongs in libsvn_client. The trouble is, there's no one place there to run it from, no svn_client_init(). We'd have to add it to all the public @@ -788,6 +804,12 @@ } #endif + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Create a client context object. */ command_baton.opt_state = &opt_state; SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); Index: tools/client-side/svnconflict/svnconflict.c =================================================================== --- tools/client-side/svnconflict/svnconflict.c (revisión: 1818629) +++ tools/client-side/svnconflict/svnconflict.c (copia de trabajo) @@ -78,6 +78,7 @@ use the short option letter as identifier. */ typedef enum svnconflict_longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_config_dir, opt_config_options, @@ -96,6 +97,9 @@ N_("specify a password ARG (caution: on many operating\n" " " "systems, other users will be able to see this)")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"config-dir", opt_config_dir, 1, N_("read user configuration files from directory ARG")}, {"config-option", opt_config_options, 1, @@ -141,7 +145,8 @@ /* Options that apply to all commands. */ static const int svnconflict_global_options[] = -{ opt_auth_username, opt_auth_password, opt_config_dir, opt_config_options, 0 }; +{ opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_config_dir, opt_config_options, 0 }; static const svn_opt_subcommand_desc2_t svnconflict_cmd_table[] = { @@ -640,6 +645,7 @@ svn_auth_baton_t *ab; svn_config_t *cfg_config; apr_hash_t *cfg_hash; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -705,6 +711,9 @@ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_config_dir: SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); opt_state.config_dir = svn_dirent_internal_style(utf8_opt_arg, pool); @@ -846,6 +855,13 @@ cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG); + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&opt_state.auth_password, pool, pool)); + } + + /* Create a client context object. */ command_baton.opt_state = &opt_state; SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); Index: tools/dev/svnmover/svnmover.c =================================================================== --- tools/dev/svnmover/svnmover.c (revisión: 1818629) +++ tools/dev/svnmover/svnmover.c (copia de trabajo) @@ -4332,7 +4332,8 @@ trust_server_cert_opt, trust_server_cert_failures_opt, ui_opt, - colour_opt + colour_opt, + auth_password_from_stdin_opt }; static const apr_getopt_option_t options[] = { {"verbose", 'v', 0, ""}, @@ -4341,6 +4342,7 @@ {"file", 'F', 1, ""}, {"username", 'u', 1, ""}, {"password", 'p', 1, ""}, + {"password-from-stdin", auth_password_from_stdin_opt, 1, ""}, {"root-url", 'U', 1, ""}, {"revision", 'r', 1, ""}, {"branch-id", 'B', 1, ""}, @@ -4387,6 +4389,7 @@ const char *log_msg; svn_tristate_t coloured_output = svn_tristate_false; svnmover_wc_t *wc; + svn_boolean_t read_pass_from_stdin = FALSE; /* Check library versions */ SVN_ERR(check_lib_versions()); @@ -4431,6 +4434,9 @@ case 'p': password = apr_pstrdup(pool, arg); break; + case auth_password_from_stdin_opt: + read_pass_from_stdin = TRUE; + break; case 'U': SVN_ERR(svn_utf_cstring_to_utf8(&anchor_url, arg, pool)); if (! svn_path_is_url(anchor_url)) @@ -4553,6 +4559,13 @@ "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } /* Now initialize the client context */ @@ -4580,6 +4593,12 @@ "svnmover: ", "--config-option")); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&password, pool, pool)); + } + SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG);