On Sat, Oct 07, 2017 at 03:18:11PM -0700, William Orr wrote: > Thanks for the feedback. I've finally gotten the chance to update the > patch with the suggestions. Lemme know if this addresses your concerns, > and I can write up the changelog for it. > > Thanks, > William Orr >
Thanks. Some remarks inline below. > Index: subversion/include/svn_io.h > =================================================================== > --- subversion/include/svn_io.h (revisi??n: 1811402) > +++ subversion/include/svn_io.h (copia de trabajo) > @@ -2633,6 +2633,14 @@ svn_io_file_readline(apr_file_t *file, > 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.9. This should say "1.10" because our current trunk will become 1.10, not 1.9. > + */ > +svn_error_t * > +svn_io_stdin_readline(const char **result, > + apr_pool_t *pool); Most of our APIs now use a dual-pool idiom: A scratch pool for temporary data, and a result pool for data which the function will return. Can we use this idiom here? > + > /** @} */ > > #ifdef __cplusplus > Index: subversion/libsvn_subr/io.c > =================================================================== > --- subversion/libsvn_subr/io.c (revisi??n: 1811402) > +++ subversion/libsvn_subr/io.c (copia de trabajo) > @@ -5440,3 +5440,19 @@ svn_io_file_readline(apr_file_t *file, > > return SVN_NO_ERROR; > } > + > +svn_error_t * > +svn_io_stdin_readline(const char **result, > + apr_pool_t *pool) > +{ > + svn_stringbuf_t *buf = NULL; > + svn_stream_t *stdin = NULL; > + svn_boolean_t oob = FALSE; > + > + SVN_ERR(svn_stream_for_stdin2(&stdin, TRUE, pool)); The stream would be stored in the scratch_pool. > + SVN_ERR(svn_stream_readline(stdin, &buf, APR_EOL_STR, &oob, pool)); The stringbuf would be stored in the result_pool. > + > + *result = buf->data; > + > + return SVN_NO_ERROR; > +} > Index: subversion/svn/cl.h > =================================================================== > --- subversion/svn/cl.h (revisi??n: 1811402) > +++ subversion/svn/cl.h (copia de trabajo) > @@ -178,6 +178,7 @@ typedef struct svn_cl__opt_state_t > 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; /* fd to read password from */ The above comment still talks about a file descriptor. Update it? > 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: 1811402) > +++ 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, > @@ -200,6 +201,9 @@ const apr_getopt_option_t svn_cl__options[] = > 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" > " " > @@ -495,7 +499,8 @@ const apr_getopt_option_t svn_cl__options[] = > 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 > @@ -1959,6 +1964,7 @@ sub_main(int *exit_code, int argc, const char *arg > 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)); > > @@ -2251,6 +2257,9 @@ sub_main(int *exit_code, int argc, const char *arg > 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; > @@ -2745,6 +2754,14 @@ sub_main(int *exit_code, int argc, const char *arg > "--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) > @@ -3034,6 +3051,12 @@ sub_main(int *exit_code, int argc, const char *arg > conflict_stats, pool)); > } > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&opt_state.auth_password, pool); This call needs to be wrapped in SVN_ERR(). In developer builds (./configure --enable-maintainer-mode), ignoring an 'svn_error_t' ("error leak") will make the svn binary dump core upon exit. > + } > + > /* 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: 1811402) > +++ 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 @@ const apr_getopt_option_t svn_cl__options[] = > {"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 @@ const apr_getopt_option_t svn_cl__options[] = > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > "--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 @@ sub_main(int *exit_code, int argc, const char *arg > pool)); > } > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&opt_state.auth_password, pool); This call needs to be wrapped in SVN_ERR(). > + } > + > /* 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: 1811402) > +++ subversion/svnmucc/svnmucc.c (copia de trabajo) > @@ -297,6 +297,7 @@ help(FILE *stream, apr_pool_t *pool) > " -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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > {"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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > "--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 @@ sub_main(int *exit_code, int argc, const char *arg > "svnmucc: ", "--config-option")); > } > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&password, pool); This call needs to be wrapped in SVN_ERR(). > + } > + > 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: 1811402) > +++ subversion/svnrdump/svnrdump.c (copia de trabajo) > @@ -59,6 +59,7 @@ enum svn_svnrdump__longopt_t > opt_config_option, > opt_auth_username, > opt_auth_password, > + opt_auth_password_from_stdin, > opt_auth_nocache, > opt_non_interactive, > opt_skip_revprop, > @@ -66,7 +67,7 @@ enum svn_svnrdump__longopt_t > opt_incremental, > opt_trust_server_cert, > opt_trust_server_cert_failures, > - opt_version > + opt_version, Is the comma here added on purpose? It's not strictly needed. Since we're tyring to be C89 compatible (yes, that's old), I suspect adding this comma could cause problems with some compilers. > }; > > #define SVN_SVNRDUMP__BASE_OPTIONS opt_config_dir, \ > @@ -73,6 +74,7 @@ enum svn_svnrdump__longopt_t > 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 @@ static const apr_getopt_option_t svnrdump__options > 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 @@ static const apr_getopt_option_t svnrdump__options > "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 @@ typedef struct opt_baton_t { > 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; > @@ -366,7 +372,8 @@ init_client_context(svn_client_ctx_t **ctx_p, > > /* Default authentication providers for non-interactive use */ > SVN_ERR(svn_cmdline_create_auth_baton2(&(ctx->auth_baton), non_interactive, > - username, password, config_dir, > + username, password, > + config_dir, Adding line wrapping here is unnecessary. > no_auth_cache, trust_unknown_ca, > trust_cn_mismatch, trust_expired, > trust_not_yet_valid, > @@ -463,31 +470,39 @@ replay_revisions(svn_ra_session_t *session, > 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 *dump_stream; This is very nitpicky of me, but maybe call it 'output_stream'? In any case, I agree that stdout_stream should be renamed. > > - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); > + if (dumpfile) > + { > + SVN_ERR(svn_stream_open_writable(&dump_stream, dumpfile, pool, pool)); > + } > + else > + { > + SVN_ERR(svn_stream_for_stdout(&dump_stream, pool)); > + } > > replay_baton = apr_pcalloc(pool, sizeof(*replay_baton)); > - replay_baton->stdout_stream = stdout_stream; > + replay_baton->stdout_stream = dump_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(dump_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(dump_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, dump_stream, > start_revision, pool)); > > /* Revision 0 has no tree changes, so we're done. */ > @@ -506,7 +521,7 @@ replay_revisions(svn_ra_session_t *session, > if (!incremental) > { > SVN_ERR(dump_initial_full_revision(session, extra_ra_session, > - stdout_stream, start_revision, > + dump_stream, start_revision, > quiet, pool)); > start_revision++; > } > @@ -538,16 +553,23 @@ replay_revisions(svn_ra_session_t *session, > 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 *dump_stream; > > - SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, pool)); > + if (dumpfile) > + { > + SVN_ERR(svn_stream_open_readonly(&dump_stream, dumpfile, pool, pool)); > + } > + else > + { > + SVN_ERR(svn_stream_for_stdin2(&dump_stream, TRUE, pool)); > + } > > - SVN_ERR(svn_rdump__load_dumpstream(stdin_stream, session, aux_session, > + SVN_ERR(svn_rdump__load_dumpstream(dump_stream, session, aux_session, > quiet, skip_revprops, > check_cancel, NULL, pool)); > > @@ -616,7 +638,8 @@ dump_cmd(apr_getopt_t *os, > 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 +653,9 @@ load_cmd(apr_getopt_t *os, > > 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 +796,7 @@ sub_main(int *exit_code, int argc, const char *arg > 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 +803,7 @@ sub_main(int *exit_code, int argc, const char *arg > 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 +876,9 @@ sub_main(int *exit_code, int argc, const char *arg > 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 +919,11 @@ sub_main(int *exit_code, int argc, const char *arg > 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 +1039,20 @@ sub_main(int *exit_code, int argc, const char *arg > "--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) > + { > + } There seems to be some code missing above. > + } > + > /* Expect one more non-option argument: the repository URL. */ > if (os->ind != os->argc - 1) > { > @@ -1039,9 +1087,16 @@ sub_main(int *exit_code, int argc, const char *arg > force_interactive = (username == NULL || password == NULL); > } > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&password, pool); The above call needs to be wrapped in SVN_ERR(). > + } > + > non_interactive = !svn_cmdline__be_interactive(non_interactive, > force_interactive); > > + Adding an empty line here is not necessary. > SVN_ERR(init_client_context(&(opt_baton->ctx), > non_interactive, > username, > 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: 1811402) > +++ subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout > (copia de trabajo) > @@ -134,6 +134,7 @@ Global options: > --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) > @@ -224,6 +225,7 @@ Global options: > --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: 1811402) > +++ 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 @@ const apr_getopt_option_t svn_min__options[] = > 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 @@ const apr_getopt_option_t svn_min__options[] = > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > } > #endif > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&opt_state.auth_password, pool); The above call needs to be wrapped in SVN_ERR(). > + } > + > /* 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: 1811402) > +++ tools/client-side/svnconflict/svnconflict.c (copia de trabajo) > @@ -78,6 +78,7 @@ typedef struct svnconflict_cmd_baton_t > 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 @@ static const apr_getopt_option_t svnconflict_optio > 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 @@ static svn_error_t * svnconflict_resolve_tree(apr_ > > /* 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[] = > { > @@ -639,6 +644,7 @@ sub_main(int *exit_code, int argc, const char *arg > 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)); > > @@ -704,6 +710,9 @@ sub_main(int *exit_code, int argc, const char *arg > 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); > @@ -845,6 +854,13 @@ sub_main(int *exit_code, int argc, const char *arg > > cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG); > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&opt_state.auth_password, pool); The above call needs to be wrapped in SVN_ERR(). > + } > + > + > /* 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: 1811402) > +++ tools/dev/svnmover/svnmover.c (copia de trabajo) > @@ -4332,7 +4332,8 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > {"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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > 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 @@ sub_main(int *exit_code, int argc, const char *arg > "--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 @@ sub_main(int *exit_code, int argc, const char *arg > "svnmover: ", > "--config-option")); > } > > + /* Get password from stdin if necessary */ > + if (read_pass_from_stdin) > + { > + svn_io_stdin_readline(&password, pool); The above call needs to be wrapped in SVN_ERR(). > + } > + > SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); > > cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG);