aboutsummaryrefslogtreecommitdiff
path: root/subversion/svnbench/svnbench.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svnbench/svnbench.c')
-rw-r--r--subversion/svnbench/svnbench.c167
1 files changed, 115 insertions, 52 deletions
diff --git a/subversion/svnbench/svnbench.c b/subversion/svnbench/svnbench.c
index bd67e0b35752..80a872842b6f 100644
--- a/subversion/svnbench/svnbench.c
+++ b/subversion/svnbench/svnbench.c
@@ -30,8 +30,6 @@
#include <string.h>
#include <assert.h>
-#include <apr_signal.h>
-
#include "svn_cmdline.h"
#include "svn_dirent_uri.h"
#include "svn_pools.h"
@@ -42,6 +40,8 @@
#include "private/svn_opt_private.h"
#include "private/svn_cmdline_private.h"
+#include "private/svn_string_private.h"
+#include "private/svn_utf_private.h"
#include "svn_private_config.h"
@@ -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,
@@ -68,7 +69,8 @@ typedef enum svn_cl__longopt_t {
opt_with_no_revprops,
opt_trust_server_cert,
opt_trust_server_cert_failures,
- opt_changelist
+ opt_changelist,
+ opt_search
} svn_cl__longopt_t;
@@ -111,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,
@@ -165,6 +169,8 @@ const apr_getopt_option_t svn_cl__options[] =
N_("use/display additional information from merge\n"
" "
"history")},
+ {"search", opt_search, 1,
+ N_("use ARG as search pattern (glob syntax)")},
/* Long-opt Aliases
*
@@ -194,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
};
@@ -257,7 +264,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" If locked, the letter 'O'. (Use 'svn info URL' to see details)\n"
" Size (in bytes)\n"
" Date and time of the last commit\n"),
- {'r', 'v', 'q', 'R', opt_depth} },
+ {'r', 'v', 'q', 'R', opt_depth, opt_search} },
{ "null-log", svn_cl__null_log, {0}, N_
("Fetch the log messages for a set of revision(s) and/or path(s).\n"
@@ -326,25 +333,42 @@ check_lib_versions(void)
}
-/* A flag to see if we've been cancelled by the client or not. */
-static volatile sig_atomic_t cancelled = FALSE;
+/* Baton for ra_progress_func() callback. */
+typedef struct ra_progress_baton_t
+{
+ apr_off_t bytes_transferred;
+} ra_progress_baton_t;
-/* A signal handler to support cancellation. */
+/* Implements svn_ra_progress_notify_func_t. */
static void
-signal_handler(int signum)
+ra_progress_func(apr_off_t progress,
+ apr_off_t total,
+ void *baton,
+ apr_pool_t *pool)
{
- apr_signal(signum, SIG_IGN);
- cancelled = TRUE;
+ ra_progress_baton_t *b = baton;
+ b->bytes_transferred = progress;
}
/* Our cancellation callback. */
-svn_error_t *
-svn_cl__check_cancel(void *baton)
+svn_cancel_func_t svn_cl__check_cancel = NULL;
+
+/* Add a --search argument to OPT_STATE.
+ * These options start a new search pattern group. */
+static void
+add_search_pattern_group(svn_cl__opt_state_t *opt_state,
+ const char *pattern,
+ apr_pool_t *result_pool)
{
- if (cancelled)
- return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal"));
- else
- return SVN_NO_ERROR;
+ apr_array_header_t *group = NULL;
+
+ if (opt_state->search_patterns == NULL)
+ opt_state->search_patterns = apr_array_make(result_pool, 1,
+ sizeof(apr_array_header_t *));
+
+ group = apr_array_make(result_pool, 1, sizeof(const char *));
+ APR_ARRAY_PUSH(group, const char *) = pattern;
+ APR_ARRAY_PUSH(opt_state->search_patterns, apr_array_header_t *) = group;
}
@@ -371,9 +395,16 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
svn_config_t *cfg_config;
svn_boolean_t descend = TRUE;
svn_boolean_t use_notifier = TRUE;
+ 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));
+ /* Init the temporary buffer. */
+ svn_membuf__create(&buf, 0, pool);
+
/* Check library versions */
SVN_ERR(check_lib_versions());
@@ -534,10 +565,10 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
opt_arg, pool) != 0)
{
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_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Syntax error in revision argument '%s'"),
+ utf8_opt_arg);
}
break;
case 'v':
@@ -599,6 +630,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
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;
@@ -656,6 +690,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
case 'g':
opt_state.use_merge_history = TRUE;
break;
+ case opt_search:
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ SVN_ERR(svn_utf__xfrm(&utf8_opt_arg, utf8_opt_arg,
+ strlen(utf8_opt_arg), TRUE, TRUE, &buf));
+ add_search_pattern_group(&opt_state,
+ apr_pstrdup(pool, utf8_opt_arg),
+ pool);
+ break;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
@@ -713,18 +755,18 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
}
else
{
- const char *first_arg = os->argv[os->ind++];
+ const char *first_arg;
+
+ SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++],
+ pool));
subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table,
first_arg);
if (subcommand == NULL)
{
- const char *first_arg_utf8;
- SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8,
- first_arg, pool));
svn_error_clear
(svn_cmdline_fprintf(stderr, pool,
_("Unknown subcommand: '%s'\n"),
- first_arg_utf8));
+ first_arg));
SVN_ERR(svn_cl__help(NULL, NULL, pool));
*exit_code = EXIT_FAILURE;
return SVN_NO_ERROR;
@@ -755,9 +797,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
if (subcommand->name[0] == '-')
SVN_ERR(svn_cl__help(NULL, NULL, pool));
else
- svn_error_clear
- (svn_cmdline_fprintf
- (stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n"
+ svn_error_clear(
+ svn_cmdline_fprintf(
+ stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n"
"Type 'svnbench help %s' for usage.\n"),
subcommand->name, optstr, subcommand->name));
*exit_code = EXIT_FAILURE;
@@ -808,6 +850,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
"--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)
@@ -885,31 +935,15 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
pool));
}
+ /* Get password from stdin if necessary */
+ if (read_pass_from_stdin)
+ {
+ SVN_ERR(svn_cmdline__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;
- apr_signal(SIGINT, signal_handler);
-#ifdef SIGBREAK
- /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */
- apr_signal(SIGBREAK, signal_handler);
-#endif
-#ifdef SIGHUP
- apr_signal(SIGHUP, signal_handler);
-#endif
-#ifdef SIGTERM
- apr_signal(SIGTERM, signal_handler);
-#endif
-
-#ifdef SIGPIPE
- /* Disable SIGPIPE generation for the platforms that have it. */
- apr_signal(SIGPIPE, SIG_IGN);
-#endif
-
-#ifdef SIGXFSZ
- /* Disable SIGXFSZ generation for the platforms that have it, otherwise
- * working with large files when compiled against an APR that doesn't have
- * large file support will crash the program, which is uncool. */
- apr_signal(SIGXFSZ, SIG_IGN);
-#endif
/* Set up Authentication stuff. */
SVN_ERR(svn_cmdline_create_auth_baton2(
@@ -938,8 +972,17 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
ctx->conflict_func2 = NULL;
ctx->conflict_baton2 = NULL;
+ if (!opt_state.quiet)
+ {
+ ctx->progress_func = ra_progress_func;
+ ctx->progress_baton = &ra_progress_baton;
+ }
+
/* And now we finally run the subcommand. */
+ start_time = apr_time_now();
err = (*subcommand->cmd_func)(os, &command_baton, pool);
+ time_taken = apr_time_now() - start_time;
+
if (err)
{
/* For argument-related problems, suggest using the 'help'
@@ -968,6 +1011,23 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
return err;
}
+ else if ((subcommand->cmd_func != svn_cl__help) && !opt_state.quiet)
+ {
+ /* This formatting lines up nicely with the output of our sub-commands
+ * and gives musec resolution while not overflowing for 30 years. */
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("%15.6f seconds taken\n"),
+ time_taken / 1.0e6));
+
+ /* Report how many bytes transferred over network if RA layer provided
+ this information. */
+ if (ra_progress_baton.bytes_transferred > 0)
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("%15s bytes transferred over network\n"),
+ svn__i64toa_sep(
+ ra_progress_baton.bytes_transferred, ',',
+ pool)));
+ }
return SVN_NO_ERROR;
}
@@ -1001,5 +1061,8 @@ main(int argc, const char *argv[])
}
svn_pool_destroy(pool);
+
+ svn_cmdline__cancellation_exit();
+
return exit_code;
}