Author: artagnon
Date: Sun Jul 25 19:21:02 2010
New Revision: 979094
URL: http://svn.apache.org/viewvc?rev=979094&view=rev
Log:
svnrdump: Add support for subcommands
* subversion/svnrdump/svnrdump.c
(svnrdump__cmd_table): A table of subcommands along with related
information.
(opt_baton_t): New struct for storing options to pass around and
dispatching subcommands.
(help, help_cmd): Replace the help function with a new help_cmd
function, effectively making "help" a subcommand.
(replay_range, replay_revisions): Rename function.
(dump_cmd, load_cmd): New functions to extract arguments from the
apr_getopt_t and opt_baton and dispatch calls to the corresponding
functions that do the real work. dump_cmd eventually calls
replay_revisions, while load_cmd is currently a noop.
(main): Replace local variables with fields in opt_baton where
appropriate. Add logic for reading and dispatching a
subcommand. Track changes made to other functions.
Modified:
subversion/trunk/subversion/svnrdump/svnrdump.c
Modified: subversion/trunk/subversion/svnrdump/svnrdump.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnrdump/svnrdump.c?rev=979094&r1=979093&r2=979094&view=diff
==============================================================================
--- subversion/trunk/subversion/svnrdump/svnrdump.c (original)
+++ subversion/trunk/subversion/svnrdump/svnrdump.c Sun Jul 25 19:21:02 2010
@@ -36,6 +36,8 @@
#include "dump_editor.h"
+static svn_opt_subcommand_t dump_cmd, load_cmd;
+
enum svn_svnrdump__longopt_t
{
opt_config_dir = SVN_OPT_FIRST_LONGOPT_ID,
@@ -46,6 +48,28 @@ enum svn_svnrdump__longopt_t
opt_version,
};
+static const svn_opt_subcommand_desc2_t svnrdump__cmd_table[] =
+ {
+ { "dump", dump_cmd, { "d" },
+ N_("usage: svnrdump dump URL [-r LOWER[:UPPER]]\n\n"
+ "Dump revisions LOWER to UPPER of repository at remote URL "
+ "to stdout in a 'dumpfile' portable format.\n"
+ "If omitted, LOWER defaults to zero and UPPER to the latest "
+ "latest revision.\n"),
+ { 0 } },
+ { "load", load_cmd, { "l" },
+ N_("usage: svnrdump load URL\n\n"
+ "Load a 'dumpfile' given on stdin to a repository "
+ "at remote URL.\n"
+ "## This feature is not yet available.\n"),
+ { 0 } },
+ { "help", 0, { "?", "h" },
+ N_("usage: svnrdump help [SUBCOMMAND...]\n\n"
+ "Describe the usage of this program or its subcommands.\n"),
+ { 0 } },
+ { NULL, NULL, { 0 }, NULL, { 0 } }
+ };
+
static const apr_getopt_option_t svnrdump__options[] =
{
{"revision", 'r', 1, N_("REV1[:REV2] range of revisions to dump")},
@@ -77,6 +101,14 @@ struct replay_baton {
svn_boolean_t quiet;
};
+typedef struct {
+ svn_ra_session_t *session;
+ const char *url;
+ svn_revnum_t start_revision;
+ svn_revnum_t end_revision;
+ svn_boolean_t quiet;
+} opt_baton_t;
+
static svn_error_t *
replay_revstart(svn_revnum_t revision,
void *replay_baton,
@@ -179,9 +211,9 @@ open_connection(svn_ra_session_t **sessi
}
static svn_error_t *
-replay_range(svn_ra_session_t *session, const char *url,
- svn_revnum_t start_revision, svn_revnum_t end_revision,
- svn_boolean_t quiet, apr_pool_t *pool)
+replay_revisions(svn_ra_session_t *session, const char *url,
+ svn_revnum_t start_revision, svn_revnum_t end_revision,
+ svn_boolean_t quiet, apr_pool_t *pool)
{
const svn_delta_editor_t *dump_editor;
struct replay_baton *replay_baton;
@@ -268,39 +300,12 @@ usage(const char *progname, apr_pool_t *
progname = ensure_appname(progname, pool);
SVN_ERR(svn_cmdline_fprintf(stderr, pool,
- _("Type '%s --help' for usage.\n"),
+ _("Type '%s help' for usage.\n"),
progname));
return SVN_NO_ERROR;
}
static svn_error_t *
-help(const char *progname, apr_pool_t *pool)
-{
- apr_size_t i;
-
- progname = ensure_appname(progname, pool);
-
- SVN_ERR(svn_cmdline_printf(
- pool,
- _("usage: %s URL [-r LOWER[:UPPER]]\n\n"
- "Dump the contents of repository at remote URL "
- "to stdout in a 'dumpfile' portable format.\n"
- "Dump revisions LOWER rev through UPPER rev.\n"
- "LOWER defaults to 0 and UPPER defaults to the "
- "highest possible revision if omitted.\n\n"
- "Valid options:\n"),
- progname));
-
- for (i = 0; svnrdump__options[i].name&& svnrdump__options[i].optch; i++)
- {
- const char *optstr;
- svn_opt_format_option(&optstr, svnrdump__options + i, TRUE, pool);
- SVN_ERR(svn_cmdline_fprintf(stdout, pool, " %s\n", optstr));
- }
- return svn_cmdline_fprintf(stdout, pool, "\n");
-}
-
-static svn_error_t *
version(const char *progname, apr_pool_t *pool)
{
progname = ensure_appname(progname, pool);
@@ -328,18 +333,46 @@ version(const char *progname, apr_pool_t
} \
while (0)
+static svn_error_t *
+dump_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ opt_baton_t *opt_baton = baton;
+ SVN_ERR(replay_revisions(opt_baton->session, opt_baton->url,
+ opt_baton->start_revision, opt_baton->end_revision,
+ opt_baton->quiet, pool));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+load_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ /* Not implemented yet */
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+help_cmd(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ const char *header =
+ _("general usage: svnrdump SUBCOMMAND URL [-r LOWER[:UPPER]]\n"
+ "Type 'svnrdump help<subcommand>' for help on a specific subcommand.\n\n"
+ "Available subcommands:\n");
+
+ SVN_ERR(svn_opt_print_help3(os, "svnrdump", FALSE, FALSE, NULL, header,
+ svnrdump__cmd_table, svnrdump__options, NULL,
+ NULL, pool));
+
+ return SVN_NO_ERROR;
+}
int
main(int argc, const char **argv)
{
- const char *url = NULL;
+ const svn_opt_subcommand_desc2_t *subcommand = NULL;
+ opt_baton_t *opt_baton;
char *revision_cut = NULL;
- svn_revnum_t start_revision = svn_opt_revision_unspecified;
- svn_revnum_t end_revision = svn_opt_revision_unspecified;
svn_revnum_t latest_revision = svn_opt_revision_unspecified;
- svn_boolean_t quiet = FALSE;
apr_pool_t *pool = NULL;
- svn_ra_session_t *session = NULL;
const char *config_dir = NULL;
const char *username = NULL;
const char *password = NULL;
@@ -351,6 +384,10 @@ main(int argc, const char **argv)
return EXIT_FAILURE;
pool = svn_pool_create(NULL);
+ opt_baton = apr_pcalloc(pool, sizeof(*opt_baton));
+ opt_baton->start_revision = svn_opt_revision_unspecified;
+ opt_baton->end_revision = svn_opt_revision_unspecified;
+ opt_baton->url = NULL;
SVNRDUMP_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
@@ -378,17 +415,17 @@ main(int argc, const char **argv)
revision_cut = strchr(opt_arg, ':');
if (revision_cut)
{
- start_revision = (svn_revnum_t)strtoul(opt_arg,
-&revision_cut, 10);
- end_revision = (svn_revnum_t)strtoul(revision_cut + 1,
- NULL, 10);
+ opt_baton->start_revision = (svn_revnum_t)strtoul(opt_arg,
+&revision_cut, 10);
+ opt_baton->end_revision = (svn_revnum_t)strtoul(revision_cut +
1,
+ NULL, 10);
}
else
- start_revision = (svn_revnum_t)strtoul(opt_arg, NULL, 10);
+ opt_baton->start_revision = (svn_revnum_t)strtoul(opt_arg, NULL,
10);
}
break;
case 'q':
- quiet = TRUE;
+ opt_baton->quiet = TRUE;
break;
case opt_config_dir:
config_dir = opt_arg;
@@ -398,7 +435,7 @@ main(int argc, const char **argv)
exit(EXIT_SUCCESS);
break;
case 'h':
- SVNRDUMP_ERR(help(argv[0], pool));
+ SVNRDUMP_ERR(help_cmd(os, opt_baton, pool));
exit(EXIT_SUCCESS);
break;
case opt_auth_username:
@@ -416,9 +453,16 @@ main(int argc, const char **argv)
}
}
- /* Only continue if the only not option argument is a url, to allow
- implementing 'svnrdump dump URL' like handling later without breaking
- backward compatibility */
+ subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table,
+ os->argv[os->ind++]);
+
+ if (subcommand&& strcmp(subcommand->name, "help") == 0)
+ {
+ SVNRDUMP_ERR(help_cmd(os, opt_baton, pool));
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Only continue if the only not option argument is a url */
if ((os->ind != os->argc-1)
|| !svn_path_is_url(os->argv[os->ind]))
{
@@ -426,13 +470,12 @@ main(int argc, const char **argv)
exit(EXIT_FAILURE);
}
- SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&url, os->argv[os->ind], pool));
-
- url = svn_uri_canonicalize(os->argv[os->ind], pool);
+ SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&(opt_baton->url), os->argv[os->ind],
pool));
+ opt_baton->url = svn_uri_canonicalize(os->argv[os->ind], pool);
- SVNRDUMP_ERR(open_connection(&session,
- url,
+ SVNRDUMP_ERR(open_connection(&(opt_baton->session),
+ opt_baton->url,
non_interactive,
username,
password,
@@ -440,20 +483,20 @@ main(int argc, const char **argv)
no_auth_cache,
pool));
- /* Have sane start_revision and end_revision defaults if unspecified */
- SVNRDUMP_ERR(svn_ra_get_latest_revnum(session,&latest_revision, pool));
- if (start_revision == svn_opt_revision_unspecified)
- start_revision = 0;
- if (end_revision == svn_opt_revision_unspecified)
- end_revision = latest_revision;
- if (end_revision> latest_revision)
+ /* Have sane opt_baton->start_revision and end_revision defaults if
unspecified */
+ SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session,&latest_revision,
pool));
+ if (opt_baton->start_revision == svn_opt_revision_unspecified)
+ opt_baton->start_revision = 0;
+ if (opt_baton->end_revision == svn_opt_revision_unspecified)
+ opt_baton->end_revision = latest_revision;
+ if (opt_baton->end_revision> latest_revision)
{
SVN_INT_ERR(svn_cmdline_fprintf(stderr, pool,
_("Revision %ld does not exist.\n"),
- end_revision));
+ opt_baton->end_revision));
exit(EXIT_FAILURE);
}
- if (end_revision< start_revision)
+ if (opt_baton->end_revision< opt_baton->start_revision)
{
SVN_INT_ERR(svn_cmdline_fprintf(stderr, pool,
_("LOWER cannot be greater "
@@ -461,8 +504,8 @@ main(int argc, const char **argv)
exit(EXIT_FAILURE);
}
- SVNRDUMP_ERR(replay_range(session, url, start_revision, end_revision,
- quiet, pool));
+ /* Dispatch the subcommand */
+ SVNRDUMP_ERR((*subcommand->cmd_func)(os, opt_baton, pool));
svn_pool_destroy(pool);