[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] Issue #812

From: Blair Zajac <blair_at_orcaware.com>
Date: 2002-07-25 21:30:49 CEST

Rob Siemborski wrote:
>
> On Thu, 25 Jul 2002, Blair Zajac wrote:
>
> > I started a patch to factor out the usage stuff for svnadmin and
> > svnlook, but it's way out of date, back in April revision 1642. If
> > somebody wants to pick it up where I stopped, I can send the diffs
> > out. I'm afraid they'll need a ton of integration into the current
> > tree.
>
> Since I started this whole thing, and it sounds simple enough (from a
> getting-to-know-the-code perspective), I'd be willing to take a look if
> you sent me the diffs.

Here you go. I don't have a log message yet for the work that I started.

The hardest part is that svn passes around a pointer to a large structure
specific for itself and its subcommands that I changed to a void * so that
it could be used by svnadmin and svnlook. There are also some static
functions for svn that needed to get moved into a public library and I
choose libsvn_subr.

The diff is large but a lot of it is just moving code around from one
file to another to get static functions into the library. I also
wouldn't try to apply it to the current tree, rather just copy what
was done and use the current tree.

Best,
Blair

-- 
Blair Zajac <blair@orcaware.com>
Web and OS performance plots - http://www.orcaware.com/orca/

Index: ./subversion/include/svn_getopt.h
===================================================================
--- ./subversion/include/svn_getopt.h
+++ ./subversion/include/svn_getopt.h Fri Mar 15 13:21:34 2002
@@ -0,0 +1,281 @@
+/*
+ * svn_getopt.h: command line processing and usage utilities
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+#ifndef SVN_GETOPT_H
+#define SVN_GETOPT_H
+
+/*** Includes. ***/
+#include "apr_getopt.h"
+
+#include "svn_error.h"
+
+/*** Defines. ***/
+
+/* This is the maximum number of aliases a command can have. */
+#define SVN_CL__MAX_ALIASES 3
+
+/* This is the maximum number of options accepted by a single command.
+ Each value in the array is a unique enum which is the 2nd field in
+ the apr_getopt_option_t. */
+#define SVN_CL__MAX_OPTS 15
+
+
+/*** Command dispatch. ***/
+
+/* All client command functions conform to this prototype. ARGS
+ * contains the list of non command line options passed to the
+ * program. Most of the time ARGS will be a list of filenames and
+ * directories, a-la CVS (which really only becomes useful if you pass
+ * it into svn_cl__args_to_target_array() to convert ARGS to an APR
+ * array of svn_stringbuf_t * targets). To enable different programs
+ * to do common command line preprocessing for multiple command
+ * functions before calling the appropriate command function, OPT_DATA
+ * is a void * that can be used to pass arbitrary data in.
+ */
+struct svn_getopt_t;
+typedef svn_error_t *(svn_cl__cmd_proc_t) (struct svn_getopt_t *args,
+ void *opt_data,
+ apr_pool_t *pool);
+
+
+/* One element of the command dispatch table. The caller creates a
+ table of these for each command that the program supports. */
+typedef struct svn_cl__cmd_desc_t
+{
+ /* The full name of this command. */
+ const char *name;
+
+ /* The function this command invokes. */
+ svn_cl__cmd_proc_t *cmd_func;
+
+ /* A list of alias names for this command. */
+ const char *aliases[SVN_CL__MAX_ALIASES+1];
+
+ /* A brief string describing this command, for usage messages. */
+ const char *help;
+
+ /* A list of options accepted by this command. Each value in the
+ array is a unique enum (the 2nd field in apr_getopt_option_t). */
+ int valid_options[SVN_CL__MAX_OPTS];
+} svn_cl__cmd_desc_t;
+
+typedef struct svn_getopt_t {
+ apr_getopt_t *options;
+ const apr_getopt_option_t *option_table;
+ const svn_cl__cmd_desc_t *command_table;
+ int num_received_opts;
+ int received_opts[SVN_CL__MAX_OPTS];
+ const char* received_args[SVN_CL__MAX_OPTS];
+ const svn_cl__cmd_desc_t *subcommand;
+} svn_getopt_t;
+
+/*** Functions. ***/
+
+/* Initialize the arguments for parsing. This should be used in place
+ of apr_getopt_init(). */
+apr_status_t
+svn_getopt_init(svn_getopt_t **os, apr_pool_t *pool,
+ int argc, const char * const *argv,
+ const apr_getopt_option_t *option_table,
+ const svn_cl__cmd_desc_t *command_table);
+
+svn_error_t *
+svn_cl__help (svn_getopt_t *os, void *help_info_, apr_pool_t *pool);
+
+/* Given a command name COMMAND_NAME and a table of command dispatch
+ functions (svn_cl__cmd_desc_t[]), COMMAND_TABLE, and a pool POOL,
+ print the usage of the command. This function is also used by
+ subcommands that need to print a usage message. */
+void
+svn_cl__print_subcommand_help (const char *command_name,
+ const svn_getopt_t *os,
+ apr_pool_t *pool);
+
+/* Given a command name COMMAND_NAME and a table of command dispatch
+ functions (svn_cl__cmd_desc_t[]), COMMAND_TABLE, return a pointer
+ to the svn_cl__cmd_desc_t whose name matches COMMAND_NAME or NULL if
+ none mathces. COMMAND_NAME may be an alias. */
+const svn_cl__cmd_desc_t *
+svn_cl__get_canonical_command (const char *command_name,
+ const svn_cl__cmd_desc_t *command_table);
+
+/* Create a targets array and add all the remaining arguments
+ to it. We also process arguments passed in the --target file, if
+ specified, just as if they were passed on the command line. */
+apr_array_header_t *
+svn_cl__args_to_target_array (const svn_getopt_t *os,
+ apr_array_header_t *cmd_targets,
+ apr_pool_t *pool);
+
+/* Print the canonical command name for CMD, all its aliases,
+ and if HELP is set, print the help string for the command too. */
+void
+svn_cl__print_command_info (const svn_cl__cmd_desc_t *cmd_desc,
+ const svn_getopt_t *os,
+ svn_boolean_t help,
+ apr_pool_t *pool,
+ FILE *stream);
+
+/* Look up CODE in OPTION_TABLE. If any option in the table has this
+ enum code, return a pointer to the option. Else return NULL. */
+const apr_getopt_option_t *
+svn_cl__get_option_from_enum (int code,
+ const apr_getopt_option_t *option_table);
+
+
+
+/*** Miscellaneous utility commands ***/
+
+/* Parse all of the arguments from the command line args passed in by
+ the user. Put them into ARGS. */
+svn_error_t *
+svn_cl__parse_all_args (apr_array_header_t **args,
+ const svn_getopt_t *os,
+ const char *subcommand,
+ apr_pool_t *pool);
+
+/* Parse a given number of non-target arguments from the command line
+ args passed in by the user. Put them into the passed in ARGS
+ array. */
+svn_error_t *
+svn_cl__parse_num_args (apr_array_header_t **args,
+ const svn_getopt_t *os,
+ const char *subcommand,
+ int num_args,
+ apr_pool_t *pool);
+
+/* Print an option OPT nicely into a STRING allocated in POOL. If DOC
+ is set, include generic documentation string of option.*/
+void
+svn_cl__format_option (char **string,
+ const apr_getopt_option_t *opt,
+ svn_boolean_t doc,
+ apr_pool_t *pool);
+
+/* Create a SVN string from the char* and add it to the array. */
+void
+array_push_svn_stringbuf (apr_array_header_t *array,
+ const char *str,
+ apr_pool_t *pool);
+
+#if 0
+
+/* Look up CODE in OPTION_TABLE. If any option in the table has this
+ enum code, return a pointer to the option. Else return NULL. */
+const apr_getopt_option_t *
+svn_cl__get_option_from_enum (int code,
+ const apr_getopt_option_t *option_table);
+
+
+void svn_cl__push_implicit_dot_target (apr_array_header_t *targets,
+ apr_pool_t *pool);
+
+
+void
+svn_cl__subcommand_help (const char *subcommand,
+ apr_pool_t *pool);
+
+
+/*** Command-line output functions -- printing to the user. ***/
+
+/* Print a hash that maps property names (char *) to property values
+ (svn_stringbuf_t *). */
+void svn_cl__print_prop_hash (apr_hash_t *prop_hash, apr_pool_t *pool);
+
+/* Print out the property names in a hash that maps property names (char *)
+ to property values (svn_stringbuf_t *). */
+void svn_cl__print_prop_names (apr_hash_t *prop_hash, apr_pool_t *pool);
+
+/* Returns an editor that prints out events in an update or checkout. */
+svn_error_t *
+svn_cl__get_trace_update_editor (const svn_delta_edit_fns_t **editor,
+ void **edit_baton,
+ svn_stringbuf_t *initial_path,
+ apr_pool_t *pool);
+
+/* Returns an editor that prints out events in a commit. */
+svn_error_t *
+svn_cl__get_trace_commit_editor (const svn_delta_edit_fns_t **editor,
+ void **edit_baton,
+ svn_stringbuf_t *initial_path,
+ apr_pool_t *pool);
+
+
+/* Search for a text editor command in standard environment variables,
+ and invoke it to edit CONTENTS (using a temporary file based on
+ working copy directory BASE_DIR). Return the new contents in
+ EDITED_CONTENTS, or set EDITED_CONTENTS to NULL if no edit was
+ performed. Use POOL for all allocations. */
+svn_error_t *
+svn_cl__edit_externally (svn_stringbuf_t **edited_contents,
+ svn_stringbuf_t *base_dir,
+ const svn_string_t *contents,
+ apr_pool_t *pool);
+
+
+/* Our implementation of the 'auth info callback' routine,
+ as defined in svn_client.h. This callback is passed to any
+ libsvn_client routine that needs to authenticate against a
+ repository. */
+
+/* Display PROMPT to the user, and read a reply back from stdin,
+ allocated in POOL and returned in *RESULT. If HIDE is set, the
+ reply will not be echoed to the screen. BATON is ignored (but
+ required by the definition of svn_client_auth_info_callback_t.) */
+svn_error_t *
+svn_cl__prompt_user (char **result,
+ const char *prompt,
+ svn_boolean_t hide,
+ void *baton,
+ apr_pool_t *pool);
+
+/* Helper for subcommands: given parsed OPT_STATE arguments from the
+ command-line, put auth info into a structure to pass to libsvn_client. */
+svn_client_auth_baton_t *
+svn_cl__make_auth_baton (svn_cl__opt_state_t *opt_state,
+ apr_pool_t *pool);
+
+/* Fills in the first four characters of STR_STATUS with status code
+ characters, based on TEXT_STATUS, PROP_STATUS, LOCKED, and COPIED.*/
+void
+svn_cl__generate_status_codes (char *str_status,
+ enum svn_wc_status_kind text_status,
+ enum svn_wc_status_kind prop_status,
+ svn_boolean_t locked,
+ svn_boolean_t copied);
+
+
+/*** Notification functions to display results on the terminal. */
+
+void svn_cl__notify_func (void *baton,
+ svn_wc_notify_action_t action,
+ const char *path);
+void *svn_cl__make_notify_baton (apr_pool_t *pool);
+
+#endif
+
+#endif /* SVN_GETOPT_H */
+
+/*
+ * local variables:
+ * eval: (load-file "../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: ./subversion/libsvn_subr/svn_getopt.c
===================================================================
--- ./subversion/libsvn_subr/svn_getopt.c
+++ ./subversion/libsvn_subr/svn_getopt.c Fri Mar 15 13:21:54 2002
@@ -0,0 +1,546 @@
+/*
+ * svn_getopt.c: command line processing and usage utility functions
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+
+#include "svn_getopt.h"
+#include "svn_path.h"
+#include "svn_string.h"
+#include "svn_wc.h"
+#include "svn_version.h"
+
+#define DEFAULT_ARRAY_SIZE 5
+
+/* Return TRUE iff subcommand COMMAND has OPTION_CODE listed within
+ it. Else return FALSE. */
+static svn_boolean_t
+subcommand_takes_option (const svn_cl__cmd_desc_t *command,
+ int option_code)
+{
+ int i;
+
+ for (i = 0; i < SVN_CL__MAX_OPTS; i++)
+ {
+ if (command->valid_options[i] == option_code)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static svn_error_t *
+print_version_info (apr_pool_t *pool)
+{
+ void *ra_baton;
+ svn_stringbuf_t *descriptions;
+ static const char info[] =
+ "Copyright (C) 2000-2002 CollabNet.\n"
+ "Subversion is open source software, see http://subversion.tigris.org/\n";
+
+ printf ("Subversion Client, version %s\n", SVN_VERSION);
+ printf (" compiled %s, %s\n\n", __DATE__, __TIME__);
+ printf ("%s\n", info);
+
+ printf ("The following repository access (RA) modules are available:\n\n");
+
+ /* Get a hash full of all available RA libraries. */
+ SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
+
+ /* Get a descriptive list of them. */
+ SVN_ERR (svn_ra_print_ra_libraries (&descriptions, ra_baton, pool));
+
+ printf ("%s\n", descriptions->data);
+
+ return SVN_NO_ERROR;
+}
+
+
+/* Print a generic (non-command-specific) usage message. */
+static void
+svn_cl__print_generic_help (svn_getopt_t *os, apr_pool_t *pool, FILE *stream)
+{
+ static const char usage[] =
+ "usage: svn <subcommand> [options] [args]\n"
+ "Type \"svn help <subcommand>\" for help on a specific subcommand.\n"
+ "\n"
+ "Most subcommands take file and/or directory arguments, recursing\n"
+ "on the directories. If no arguments are supplied to such a\n"
+ "command, it will recurse on the current directory (inclusive) by\n"
+ "default.\n"
+ "\n"
+ "Available subcommands:\n";
+
+ static const char info[] =
+ "Subversion is a tool for revision control.\n"
+ "For additional information, see http://subversion.tigris.org\n";
+
+ int i = 0;
+
+ fprintf (stream, "%s", usage);
+
+ if (os)
+ {
+ const svn_cl__cmd_desc_t *command_table = os->command_table;
+ while (command_table[i].name)
+ {
+ fprintf (stream, " ");
+ svn_cl__print_command_info (command_table + i, os, FALSE, pool, stream);
+ fprintf (stream, "\n");
+ i++;
+ }
+ }
+
+ fprintf (stream, "\n");
+ fprintf (stream, "%s\n", info);
+}
+
+
+/* Print either generic help, or command-specific help for each
+ * command in os->args. OPT_STATE is only examined for the
+ * '--version' switch. If OS is null then generic help will always be
+ * printed.
+ *
+ * Unlike all the other command routines, ``help'' has its own
+ * option processing.
+ */
+typedef struct help_info_t {
+ apr_array_header_t *cmd_targets;
+ int version;
+} help_info_t;
+
+svn_error_t *
+svn_cl__help (svn_getopt_t *os,
+ void *help_info_,
+ apr_pool_t *pool)
+{
+ help_info_t *help_info = (help_info_t *)help_info_;
+ apr_array_header_t *targets = NULL;
+ int i;
+
+ if (os)
+ targets = svn_cl__args_to_target_array (os,
+ help_info ? help_info->cmd_targets : NULL,
+ pool);
+
+ if (targets && targets->nelts) /* help on subcommand(s) requested */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ svn_stringbuf_t *this = (((svn_stringbuf_t **) (targets)->elts))[i];
+ svn_cl__print_subcommand_help (this->data, os, pool);
+ }
+ else if (help_info && help_info->version) /* just -v or --version */
+ SVN_ERR (print_version_info (pool));
+ else if (os && !targets->nelts) /* `-h', `--help', or `help' */
+ svn_cl__print_generic_help (os, pool, stdout);
+ else /* unknown option or cmd */
+ svn_cl__print_generic_help (os, pool, stderr);
+
+ return SVN_NO_ERROR;
+}
+
+
+/* Initialize the arguments for parsing. This should be used in place
+ of apr_getopt_init(). */
+apr_status_t
+svn_getopt_init(svn_getopt_t **os, apr_pool_t *pool,
+ int argc, const char * const *argv,
+ const apr_getopt_option_t *option_table,
+ const svn_cl__cmd_desc_t *command_table)
+{
+ apr_status_t apr_err;
+ const char *first_arg;
+ int i;
+
+ *os = apr_palloc(pool, sizeof(**os));
+ (*os)->option_table = option_table;
+ (*os)->command_table = command_table;
+ (*os)->num_received_opts = 0;
+ (*os)->received_args[0] = 0;
+ (*os)->received_opts[0] = 0;
+
+ apr_err = apr_getopt_init (&((*os)->options), pool, argc, argv);
+ if (apr_err != APR_SUCCESS) {
+ return apr_err;
+ }
+
+ /* Parse the options. */
+ (*os)->options->interleave = 1;
+ while (1)
+ {
+ int opt_id;
+ const char *opt_arg;
+
+ /* Parse the next option. */
+ apr_err = apr_getopt_long ((*os)->options, option_table,
+ &opt_id, &opt_arg);
+ if (APR_STATUS_IS_EOF (apr_err))
+ break;
+ else if (! APR_STATUS_IS_SUCCESS (apr_err))
+ {
+ svn_cl__help (NULL, NULL, pool);
+ return EXIT_FAILURE;
+ }
+
+ /* Stash the option code in an array before parsing it. */
+ (*os)->received_args[(*os)->num_received_opts] = opt_arg;
+ (*os)->received_opts[(*os)->num_received_opts] = opt_id;
+ ((*os)->num_received_opts)++;
+ }
+
+ /* Check if there are any remaining arguments on the command line. */
+ if ((*os)->options->ind >= (*os)->options->argc) {
+ fprintf (stderr, "subcommand argument required\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Look for a subcommand in the first argument. */
+ first_arg = (*os)->options->argv[(*os)->options->ind++];
+ (*os)->subcommand = svn_cl__get_canonical_command (first_arg,
+ command_table);
+ if ((*os)->subcommand == NULL)
+ {
+ /* FIXME: should we print "unknown foo" ?? seems ok */
+ fprintf (stderr, "unknown command: %s\n", first_arg);
+ svn_cl__help (NULL, NULL, pool);
+ return EXIT_FAILURE;
+ }
+
+ /* Check if this subcommand wasn't passed any inappropriate
+ options. */
+ for (i=0; i<(*os)->num_received_opts; i++)
+ if (! subcommand_takes_option ((*os)->subcommand, (*os)->received_opts[i]))
+ {
+ char *optstr;
+ const apr_getopt_option_t *badopt =
+ svn_cl__get_option_from_enum ((*os)->received_opts[i], option_table);
+ svn_cl__format_option (&optstr, badopt, FALSE, pool);
+ fprintf (stderr,
+ "\nError: subcommand '%s' doesn't accept option '%s'\n\n",
+ (*os)->subcommand->name, optstr);
+ svn_cl__print_subcommand_help ((*os)->subcommand->name, *os, pool);
+ return EXIT_FAILURE;
+ }
+
+ return APR_SUCCESS;
+}
+
+
+/* Given a command name COMMAND_NAME and a table of command dispatch
+ functions (svn_cl__cmd_desc_t[]), COMMAND_TABLE, return a pointer
+ to the svn_cl__cmd_desc_t whose name matches COMMAND_NAME or NULL
+ if none mathces. COMMAND_NAME may be an alias. */
+const svn_cl__cmd_desc_t *
+svn_cl__get_canonical_command (const char *command_name,
+ const svn_cl__cmd_desc_t *command_table)
+{
+ int i = 0;
+
+ if (command_name == NULL)
+ return NULL;
+
+ while (command_table[i].name) {
+ int j;
+ if (strcmp (command_name, command_table[i].name) == 0)
+ return command_table + i;
+ for (j = 0;
+ (j < SVN_CL__MAX_ALIASES) && command_table[i].aliases[j];
+ j++)
+ if (strcmp (command_name, command_table[i].aliases[j]) == 0)
+ return command_table + i;
+
+ i++;
+ }
+
+ /* If we get here, there was no matching command name or alias. */
+ return NULL;
+}
+
+/* Create a targets array and add all the remaining arguments
+ to it. We also process arguments passed in the --target file, if
+ specified, just as if they were passed on the command line. */
+apr_array_header_t *
+svn_cl__args_to_target_array (const svn_getopt_t *os,
+ apr_array_header_t *cmd_targets,
+ apr_pool_t *pool)
+{
+ apr_getopt_t *options = os->options;
+ apr_array_header_t *targets =
+ apr_array_make (pool, DEFAULT_ARRAY_SIZE, sizeof (svn_stringbuf_t *));
+
+ /* Command line args take precendence. */
+ for (; options->ind < options->argc; options->ind++)
+ {
+ svn_stringbuf_t *target = svn_stringbuf_create (options->argv[options->ind],
+ pool);
+ svn_string_t tstr;
+
+ /* If this path looks like it would work as a URL in one of the
+ currently available RA libraries, we add it unconditionally
+ to the target array. */
+ tstr.data = target->data;
+ tstr.len = target->len;
+ if (! svn_path_is_url (&tstr))
+ {
+ const char *basename = svn_path_basename (target->data, pool);
+
+ /* If this target is a Subversion administrative directory,
+ skip it. TODO: Perhaps this check should not call the
+ target a SVN admin dir unless svn_wc_check_wc passes on
+ the target, too? */
+ if (! strcmp (basename, SVN_WC_ADM_DIR_NAME))
+ continue;
+ }
+ else
+ {
+ svn_path_canonicalize (target);
+ }
+ (*((svn_stringbuf_t **) apr_array_push (targets))) = target;
+ }
+
+ /* Now args from --targets, if any */
+ if (NULL != cmd_targets)
+ apr_array_cat(targets, cmd_targets);
+
+ /* kff todo: need to remove redundancies from targets before
+ passing it to the cmd_func. */
+
+ return targets;
+}
+
+/* Given a command name COMMAND_NAME and a table of command dispatch
+ functions (svn_cl__cmd_desc_t[]), COMMAND_TABLE, and a pool POOL,
+ print the usage of the command. This function is also used by
+ subcommands that need to print a usage message. */
+void
+svn_cl__print_subcommand_help (const char* command_name,
+ const svn_getopt_t *os,
+ apr_pool_t *pool)
+{
+ const svn_cl__cmd_desc_t *cmd =
+ svn_cl__get_canonical_command (command_name, os->command_table);
+
+ if (cmd)
+ svn_cl__print_command_info (cmd, os, TRUE, pool, stdout);
+ else
+ fprintf (stderr, "\"%s\": unknown command.\n\n", command_name);
+}
+
+
+/* Print an option OPT nicely into a STRING allocated in POOL. If DOC
+ is set, include generic documentation string of option.*/
+void
+svn_cl__format_option (char **string,
+ const apr_getopt_option_t *opt,
+ svn_boolean_t doc,
+ apr_pool_t *pool)
+{
+ char *opts;
+
+ if (opt == NULL)
+ *string = apr_psprintf (pool, "?");
+
+ if (opt->optch <= 255)
+ opts = apr_psprintf (pool, "-%c [--%s]", opt->optch, opt->name);
+ else
+ opts = apr_psprintf (pool, "--%s", opt->name);
+
+ if (opt->has_arg)
+ opts = apr_pstrcat (pool, opts, " arg", NULL);
+
+ if (doc)
+ opts = apr_pstrcat (pool, opts, ":\t", opt->description, NULL);
+
+ *string = opts;
+}
+
+/* Print the canonical command name for CMD, all its aliases,
+ and if HELP is set, print the help string for the command too. */
+void
+svn_cl__print_command_info (const svn_cl__cmd_desc_t *cmd_desc,
+ const svn_getopt_t *os,
+ svn_boolean_t help,
+ apr_pool_t *pool,
+ FILE *stream)
+{
+ const apr_getopt_option_t *option_table = os->option_table;
+ const svn_cl__cmd_desc_t *command_table = os->command_table;
+ const svn_cl__cmd_desc_t *canonical_cmd
+ = svn_cl__get_canonical_command (cmd_desc->name, command_table);
+ svn_boolean_t first_time;
+ int i;
+
+ /* Print the canonical command name. */
+ fputs (canonical_cmd->name, stream);
+
+ /* Print the list of aliases. */
+ first_time = TRUE;
+ for (i = 0; i < SVN_CL__MAX_ALIASES; i++)
+ {
+ if (canonical_cmd->aliases[i] == NULL)
+ break;
+
+ if (first_time) {
+ fprintf (stream, " (");
+ first_time = FALSE;
+ }
+ else
+ fprintf (stream, ", ");
+
+ fprintf (stream, "%s", canonical_cmd->aliases[i]);
+ }
+
+ if (! first_time)
+ fprintf (stream, ")");
+
+ if (help)
+ {
+ const apr_getopt_option_t *option;
+ svn_boolean_t have_options = FALSE;
+
+ fprintf (stream, ": %s", canonical_cmd->help);
+
+ /* Loop over all valid option codes attached to the subcommand */
+ for (i = 0; i < SVN_CL__MAX_OPTS; i++)
+ {
+ if (canonical_cmd->valid_options[i])
+ {
+ if (have_options == FALSE)
+ {
+ fprintf (stream, "\nValid options:\n");
+ have_options = TRUE;
+ }
+
+ /* convert each option code into an option */
+ option =
+ svn_cl__get_option_from_enum (canonical_cmd->valid_options[i],
+ option_table);
+
+ /* print the option's docstring */
+ if (option)
+ {
+ char *optstr;
+ svn_cl__format_option (&optstr, option, TRUE, pool);
+ fprintf (stream, " %s\n", optstr);
+ }
+ }
+ }
+
+ if (have_options)
+ fprintf (stream, "\n");
+ }
+}
+
+const apr_getopt_option_t *
+svn_cl__get_option_from_enum (int code,
+ const apr_getopt_option_t *option_table)
+{
+ int i;
+ const apr_getopt_option_t *opt = NULL;
+
+ for (i = 0; i < SVN_CL__MAX_OPTS; i++)
+ {
+ if (option_table[i].optch == code)
+ {
+ opt = &(option_table[i]);
+ break;
+ }
+ }
+
+ return opt;
+}
+
+/* Create a SVN string from the char* and add it to the array. */
+void
+array_push_svn_stringbuf (apr_array_header_t *array,
+ const char *str,
+ apr_pool_t *pool)
+{
+ (*((svn_stringbuf_t **) apr_array_push (array)))
+ = svn_stringbuf_create (str, pool);
+}
+
+/* Parse all of the arguments from the command line args passed in by
+ the user. Put them into ARGS. */
+svn_error_t *
+svn_cl__parse_all_args (apr_array_header_t **args,
+ const svn_getopt_t *os,
+ const char *subcommand,
+ apr_pool_t *pool)
+{
+ apr_getopt_t *options = os->options;
+
+ *args = apr_array_make (pool,
+ DEFAULT_ARRAY_SIZE,
+ sizeof (svn_stringbuf_t *));
+
+ if (options->ind >= options->argc)
+ {
+ svn_cl__print_subcommand_help (subcommand, os, pool);
+ return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
+ }
+
+ while (options->ind < options->argc)
+ {
+ array_push_svn_stringbuf (*args,
+ options->argv[options->ind++],
+ pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Parse a given number of non-target arguments from the command line
+ args passed in by the user. Put them into the passed in ARGS
+ array. */
+svn_error_t *
+svn_cl__parse_num_args (apr_array_header_t **args,
+ const svn_getopt_t *os,
+ const char *subcommand,
+ int num_args,
+ apr_pool_t *pool)
+{
+ apr_getopt_t *options = os->options;
+ int i;
+
+ *args = apr_array_make (pool,
+ DEFAULT_ARRAY_SIZE,
+ sizeof (svn_stringbuf_t *));
+
+ /* loop for num_args and add each arg to the args array */
+ for (i = 0; i < num_args; i++)
+ {
+ if (options->ind >= options->argc)
+ {
+ svn_cl__print_subcommand_help (subcommand, os, pool);
+ return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR,
+ 0, 0, pool, "");
+ }
+ array_push_svn_stringbuf (*args,
+ options->argv[options->ind++],
+ pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+/* --------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: ./subversion/clients/cmdline/merge-cmd.c
===================================================================
--- ./subversion/clients/cmdline/merge-cmd.c
+++ ./subversion/clients/cmdline/merge-cmd.c Thu Apr 4 17:17:13 2002
@@ -35,10 +35,11 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__merge (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__merge (svn_getopt_t *os,
+ void *opt_state_,
                apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *options;
   apr_array_header_t *targets;
   apr_array_header_t *condensed_targets;
@@ -47,7 +48,7 @@
 
   options = svn_cl__stringlist_to_array (opt_state->extensions, pool);
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
   svn_cl__push_implicit_dot_target (targets, pool);
   SVN_ERR (svn_path_remove_redundancies (&condensed_targets,
                                          targets,
Index: ./subversion/clients/cmdline/cl.h
===================================================================
--- ./subversion/clients/cmdline/cl.h
+++ ./subversion/clients/cmdline/cl.h Thu Apr 4 16:13:23 2002
@@ -25,8 +25,8 @@
 
 /*** Includes. ***/
 #include <apr_tables.h>
-#include <apr_getopt.h>
 
+#include "svn_getopt.h"
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_string.h"
@@ -84,7 +84,6 @@
   svn_boolean_t verbose;
   svn_boolean_t very_verbose;
   svn_boolean_t update;
- apr_array_header_t *args;
   /* TODO fixme. This still doesn't handle binary data from a file! */
   svn_stringbuf_t *filedata;
   svn_boolean_t help;
@@ -97,25 +96,6 @@
   apr_array_header_t *targets;
 } svn_cl__opt_state_t;
 
-
-/* All client command procedures conform to this prototype. OPT_STATE
- * likewise should hold the result of processing the options. OS is a
- * list of filenames and directories, a-la CVS (which really only
- * becomes useful if you pass it into svn_cl__args_to_target_array()
- * to convert OS to an APR arra of svn_stringbuf_t * targets).
- *
- * TARGETS is normalized by main before being passed to any command
- * (with the exception of svn_cl__help, which will oftentime be passed
- * an empty array of targets. That is, all duplicates are removed, and
- * all paths are made relative to the working copy root directory). */
-typedef svn_error_t *(svn_cl__cmd_proc_t) (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- apr_pool_t *pool);
-
-
-
-
-
 /* Declare all the command procedures */
 svn_cl__cmd_proc_t
   svn_cl__add,
@@ -125,7 +105,6 @@
   svn_cl__copy,
   svn_cl__delete,
   svn_cl__diff,
- svn_cl__help,
   svn_cl__import,
   svn_cl__log,
   svn_cl__merge,
@@ -143,11 +122,6 @@
   svn_cl__update;
 
 
-/* Print a generic (non-command-specific) usage message. */
-void
-svn_cl__print_generic_help (apr_pool_t *pool, FILE *stream);
-
-
 /* Print out commit information found in COMMIT_INFO to the console. */
 void
 svn_cl__print_commit_info (svn_client_commit_info_t *commit_info);
@@ -155,25 +129,10 @@
 
 /*** Miscellaneous utility commands ***/
 
-/* Look up CODE in OPTION_TABLE. If any option in the table has this
- enum code, return a pointer to the option. Else return NULL. */
-const apr_getopt_option_t *
-svn_cl__get_option_from_enum (int code,
- const apr_getopt_option_t *option_table);
-
-
 void svn_cl__push_svn_string (apr_array_header_t *array,
                               const char *str,
                               apr_pool_t *pool);
 
-/* Subcommands call this to pull any args left into the array of targets.
- This includes any extra args passed in the file specified by
- --targets. */
-apr_array_header_t*
-svn_cl__args_to_target_array (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- apr_pool_t *pool);
-
 /* Splits a list of whitespace-separated values into an apr_array_header_t */
 apr_array_header_t*
 svn_cl__stringlist_to_array (svn_stringbuf_t *buffer, apr_pool_t *pool);
@@ -185,23 +144,6 @@
 void svn_cl__push_implicit_dot_target (apr_array_header_t *targets,
                                        apr_pool_t *pool);
 
-svn_error_t *
-svn_cl__parse_num_args (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- const char *subcommand,
- int num_args,
- apr_pool_t *pool);
-
-svn_error_t *
-svn_cl__parse_all_args (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- const char *subcommand,
- apr_pool_t *pool);
-
-void
-svn_cl__subcommand_help (const char *subcommand,
- apr_pool_t *pool);
-
 
 /*** Command-line output functions -- printing to the user. ***/
 
@@ -342,4 +284,3 @@
  * eval: (load-file "../../../tools/dev/svn-dev.el")
  * end:
  */
-
Index: ./subversion/clients/cmdline/checkout-cmd.c
===================================================================
--- ./subversion/clients/cmdline/checkout-cmd.c
+++ ./subversion/clients/cmdline/checkout-cmd.c Fri Mar 8 09:11:18 2002
@@ -34,16 +34,18 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__checkout (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__checkout (svn_getopt_t *os,
+ void *opt_state_,
                   apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
+ apr_array_header_t *args;
   const svn_delta_editor_t *trace_editor;
   void *trace_edit_baton;
   int i;
   svn_client_auth_baton_t *auth_baton;
   
- SVN_ERR (svn_cl__parse_all_args (os, opt_state, "checkout", pool));
+ SVN_ERR (svn_cl__parse_all_args (&args, os, "checkout", pool));
   
   /* Put commandline auth info into a baton for libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
@@ -88,11 +90,11 @@
     (args->nelts == 1) or (args->nelts > 1). -Fitz
 
    */
- for (i = 0; i < opt_state->args->nelts; i++)
+ for (i = 0; i < args->nelts; i++)
     {
       svn_stringbuf_t *local_dir;
       svn_stringbuf_t *repos_url
- = ((svn_stringbuf_t **) (opt_state->args->elts))[0];
+ = ((svn_stringbuf_t **) (args->elts))[0];
 
       /* Canonicalize the URL. */
       /* ### um. this function isn't really designed for URLs... */
Index: ./subversion/clients/cmdline/propdel-cmd.c
===================================================================
--- ./subversion/clients/cmdline/propdel-cmd.c
+++ ./subversion/clients/cmdline/propdel-cmd.c Thu Apr 4 17:10:06 2002
@@ -34,21 +34,23 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__propdel (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__propdel (svn_getopt_t *os,
+ void *opt_state_,
                  apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
+ apr_array_header_t *args;
   svn_stringbuf_t *pname;
   apr_array_header_t *targets;
   int i;
 
- SVN_ERR (svn_cl__parse_num_args (os, opt_state, "propdel", 1, pool));
+ SVN_ERR (svn_cl__parse_num_args (&args, os, "propdel", 1, pool));
 
   /* Get the property's name. */
- pname = ((svn_stringbuf_t **) (opt_state->args->elts))[0];
+ pname = ((svn_stringbuf_t **) (args->elts))[0];
 
   /* Suck up all the remaining arguments into a targets array */
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Add "." if user passed 0 file arguments */
   svn_cl__push_implicit_dot_target (targets, pool);
Index: ./subversion/clients/cmdline/move-cmd.c
===================================================================
--- ./subversion/clients/cmdline/move-cmd.c
+++ ./subversion/clients/cmdline/move-cmd.c Thu Apr 4 16:13:23 2002
@@ -35,20 +35,21 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__move (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__move (svn_getopt_t *os,
+ void *opt_state_,
               apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_stringbuf_t *src_path, *dst_path;
   svn_client_auth_baton_t *auth_baton = NULL;
   svn_client_commit_info_t *commit_info = NULL;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   if (targets->nelts != 2)
     {
- svn_cl__subcommand_help ("move", pool);
+ svn_cl__print_subcommand_help ("move", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/mkdir-cmd.c
===================================================================
--- ./subversion/clients/cmdline/mkdir-cmd.c
+++ ./subversion/clients/cmdline/mkdir-cmd.c Thu Apr 4 16:13:23 2002
@@ -35,16 +35,17 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__mkdir (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__mkdir (svn_getopt_t *os,
+ void *opt_state_,
                apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_client_auth_baton_t *auth_baton = NULL;
   int i;
   svn_client_commit_info_t *commit_info = NULL;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Build an authentication object to give to libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
@@ -66,7 +67,7 @@
     }
   else
     {
- svn_cl__subcommand_help ("mkdir", pool);
+ svn_cl__print_subcommand_help ("mkdir", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/revert-cmd.c
===================================================================
--- ./subversion/clients/cmdline/revert-cmd.c
+++ ./subversion/clients/cmdline/revert-cmd.c Thu Mar 14 16:24:20 2002
@@ -33,15 +33,16 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__revert (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__revert (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   int i;
   svn_boolean_t recursive = opt_state->recursive;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Revert has no implicit dot-target `.', so don't you put that code
      here! */
@@ -59,7 +60,7 @@
       }
   else
     {
- svn_cl__subcommand_help ("revert", pool);
+ svn_cl__print_subcommand_help ("revert", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
   
Index: ./subversion/clients/cmdline/diff-cmd.c
===================================================================
--- ./subversion/clients/cmdline/diff-cmd.c
+++ ./subversion/clients/cmdline/diff-cmd.c Tue Mar 12 18:08:15 2002
@@ -36,10 +36,11 @@
 
 /* An svn_cl__cmd_proc_t to handle the 'diff' command. */
 svn_error_t *
-svn_cl__diff (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__diff (svn_getopt_t *os,
+ void *opt_state_,
               apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *options;
   apr_array_header_t *targets;
   apr_array_header_t *condensed_targets;
@@ -50,7 +51,7 @@
 
   options = svn_cl__stringlist_to_array (opt_state->extensions, pool);
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
   svn_cl__push_implicit_dot_target (targets, pool);
   SVN_ERR (svn_path_remove_redundancies (&condensed_targets,
                                          targets,
Index: ./subversion/clients/cmdline/copy-cmd.c
===================================================================
--- ./subversion/clients/cmdline/copy-cmd.c
+++ ./subversion/clients/cmdline/copy-cmd.c Thu Apr 4 16:52:24 2002
@@ -35,10 +35,11 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__copy (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__copy (svn_getopt_t *os,
+ void *opt_state_,
               apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_stringbuf_t *src_path, *dst_path;
   svn_string_t path_str;
@@ -48,10 +49,10 @@
   svn_boolean_t src_is_url, dst_is_url;
   svn_client_commit_info_t *commit_info = NULL;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
   if (targets->nelts != 2)
     {
- svn_cl__subcommand_help ("copy", pool);
+ svn_cl__print_subcommand_help ("copy", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/util.c
===================================================================
--- ./subversion/clients/cmdline/util.c
+++ ./subversion/clients/cmdline/util.c Thu Apr 4 16:13:24 2002
@@ -45,18 +45,6 @@
 
 #define DEFAULT_ARRAY_SIZE 5
 
-/* Hmm. This should probably find its way into libsvn_subr -Fitz */
-/* Create a SVN string from the char* and add it to the array */
-static void
-array_push_svn_stringbuf (apr_array_header_t *array,
- const char *str,
- apr_pool_t *pool)
-{
- (*((svn_stringbuf_t **) apr_array_push (array)))
- = svn_stringbuf_create (str, pool);
-}
-
-
 /* Some commands take an implicit "." string argument when invoked
  * with no arguments. Those commands make use of this function to
  * add "." to the target array if the user passes no args */
@@ -69,112 +57,6 @@
   assert (targets->nelts);
 }
 
-/* Parse a given number of non-target arguments from the
- * command line args passed in by the user. Put them
- * into the opt_state args array */
-svn_error_t *
-svn_cl__parse_num_args (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- const char *subcommand,
- int num_args,
- apr_pool_t *pool)
-{
- int i;
-
- opt_state->args = apr_array_make (pool, DEFAULT_ARRAY_SIZE,
- sizeof (svn_stringbuf_t *));
-
- /* loop for num_args and add each arg to the args array */
- for (i = 0; i < num_args; i++)
- {
- if (os->ind >= os->argc)
- {
- svn_cl__subcommand_help (subcommand, pool);
- return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR,
- 0, 0, pool, "");
- }
- array_push_svn_stringbuf (opt_state->args, os->argv[os->ind++], pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Parse all of the arguments from the command line args
- * passed in by the user. Put them into the opt_state
- * args array */
-svn_error_t *
-svn_cl__parse_all_args (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- const char *subcommand,
- apr_pool_t *pool)
-{
- opt_state->args = apr_array_make (pool, DEFAULT_ARRAY_SIZE,
- sizeof (svn_stringbuf_t *));
-
- if (os->ind >= os->argc)
- {
- svn_cl__subcommand_help (subcommand, pool);
- return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
- }
-
- while (os->ind < os->argc)
- {
- array_push_svn_stringbuf (opt_state->args, os->argv[os->ind++], pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Create a targets array and add all the remaining arguments
- * to it. We also process arguments passed in the --target file, if
- * specified, just as if they were passed on the command line. */
-apr_array_header_t*
-svn_cl__args_to_target_array (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- apr_pool_t *pool)
-{
- apr_array_header_t *targets =
- apr_array_make (pool, DEFAULT_ARRAY_SIZE, sizeof (svn_stringbuf_t *));
-
- /* Command line args take precendence. */
- for (; os->ind < os->argc; os->ind++)
- {
- svn_stringbuf_t *target = svn_stringbuf_create (os->argv[os->ind], pool);
- svn_string_t tstr;
-
- /* If this path looks like it would work as a URL in one of the
- currently available RA libraries, we add it unconditionally
- to the target array. */
- tstr.data = target->data;
- tstr.len = target->len;
- if (! svn_path_is_url (&tstr))
- {
- const char *basename = svn_path_basename (target->data, pool);
-
- /* If this target is a Subversion administrative directory,
- skip it. TODO: Perhaps this check should not call the
- target a SVN admin dir unless svn_wc_check_wc passes on
- the target, too? */
- if (! strcmp (basename, SVN_WC_ADM_DIR_NAME))
- continue;
- }
- else
- {
- svn_path_canonicalize (target);
- }
- (*((svn_stringbuf_t **) apr_array_push (targets))) = target;
- }
-
- /* Now args from --targets, if any */
- if (NULL != opt_state->targets)
- apr_array_cat(targets, opt_state->targets);
-
- /* kff todo: need to remove redundancies from targets before
- passing it to the cmd_func. */
-
- return targets;
-}
-
 /* Convert a whitespace separated list of items into an apr_array_header_t */
 apr_array_header_t*
 svn_cl__stringlist_to_array(svn_stringbuf_t *buffer, apr_pool_t *pool)
Index: ./subversion/clients/cmdline/propget-cmd.c
===================================================================
--- ./subversion/clients/cmdline/propget-cmd.c
+++ ./subversion/clients/cmdline/propget-cmd.c Thu Mar 14 16:23:41 2002
@@ -34,22 +34,23 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__propget (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__propget (svn_getopt_t *os,
+ void *opt_state_,
                  apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
+ apr_array_header_t *args;
   svn_stringbuf_t *propname;
   apr_array_header_t *targets;
   int i;
 
   /* PROPNAME is first argument */
- SVN_ERR (svn_cl__parse_num_args (os, opt_state,
- "propget", 1, pool));
+ SVN_ERR (svn_cl__parse_num_args (&args, os, "propget", 1, pool));
 
- propname = ((svn_stringbuf_t **) (opt_state->args->elts))[0];
+ propname = ((svn_stringbuf_t **) (args->elts))[0];
 
   /* suck up all the remaining arguments into a targets array */
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Add "." if user passed 0 file arguments */
   svn_cl__push_implicit_dot_target(targets, pool);
Index: ./subversion/clients/cmdline/log-cmd.c
===================================================================
--- ./subversion/clients/cmdline/log-cmd.c
+++ ./subversion/clients/cmdline/log-cmd.c Tue Mar 12 18:08:48 2002
@@ -166,15 +166,16 @@
 
 
 svn_error_t *
-svn_cl__log (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__log (svn_getopt_t *os,
+ void *opt_state_,
              apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_client_auth_baton_t *auth_baton;
   struct log_message_receiver_baton lb;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Build an authentication object to give to libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
Index: ./subversion/clients/cmdline/update-cmd.c
===================================================================
--- ./subversion/clients/cmdline/update-cmd.c
+++ ./subversion/clients/cmdline/update-cmd.c Thu Mar 14 16:25:20 2002
@@ -34,16 +34,17 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__update (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__update (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   apr_array_header_t *condensed_targets;
   int i;
   svn_client_auth_baton_t *auth_baton;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Build an authentication baton to give to libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
Index: ./subversion/clients/cmdline/cleanup-cmd.c
===================================================================
--- ./subversion/clients/cmdline/cleanup-cmd.c
+++ ./subversion/clients/cmdline/cleanup-cmd.c Tue Mar 12 18:06:36 2002
@@ -33,14 +33,15 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__cleanup (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__cleanup (svn_getopt_t *os,
+ void *opt_state_,
                  apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   int i;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Add "." if user passed 0 arguments */
   svn_cl__push_implicit_dot_target(targets, pool);
@@ -54,7 +55,7 @@
       }
   else
     {
- svn_cl__subcommand_help ("cleanup", pool);
+ svn_cl__print_subcommand_help ("cleanup", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/add-cmd.c
===================================================================
--- ./subversion/clients/cmdline/add-cmd.c
+++ ./subversion/clients/cmdline/add-cmd.c Tue Mar 12 18:07:20 2002
@@ -36,16 +36,17 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__add (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__add (svn_getopt_t *os,
+ void *opt_state_,
              apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   svn_error_t *err;
   apr_array_header_t *targets;
   int i;
   svn_boolean_t recursive = opt_state->recursive;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   if (targets->nelts)
     {
@@ -76,7 +77,7 @@
     }
   else
     {
- svn_cl__subcommand_help ("add", pool);
+ svn_cl__print_subcommand_help ("add", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/help-cmd.c
===================================================================
--- ./subversion/clients/cmdline/help-cmd.c
+++ ./subversion/clients/cmdline/.svn/empty-file Fri Mar 15 10:09:05 2002
@@ -1,103 +0,0 @@
-/*
- * help-cmd.c -- Provide help
- *
- * ====================================================================
- * Copyright (c) 2000-2002 CollabNet. All rights reserved.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://subversion.tigris.org/license-1.html.
- * If newer versions of this license are posted there, you may use a
- * newer version instead, at your option.
- *
- * This software consists of voluntary contributions made by many
- * individuals. For exact contribution history, see the revision
- * history and logs, available at http://subversion.tigris.org/.
- * ====================================================================
- */
-
-/* ==================================================================== */
-
-
-
-/*** Includes. ***/
-
-#include "svn_client.h"
-#include "svn_string.h"
-#include "svn_error.h"
-#include "svn_version.h"
-#include "cl.h"
-
-
-/*** Code. ***/
-
-static svn_error_t *
-print_version_info (apr_pool_t *pool)
-{
- void *ra_baton;
- svn_stringbuf_t *descriptions;
- static const char info[] =
- "Copyright (C) 2000-2002 CollabNet.\n"
- "Subversion is open source software, see http://subversion.tigris.org/\n";
-
- printf ("Subversion Client, version %s\n", SVN_VERSION);
- printf (" compiled %s, %s\n\n", __DATE__, __TIME__);
- printf ("%s\n", info);
-
- printf ("The following repository access (RA) modules are available:\n\n");
-
- /* Get a hash full of all available RA libraries. */
- SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
-
- /* Get a descriptive list of them. */
- SVN_ERR (svn_ra_print_ra_libraries (&descriptions, ra_baton, pool));
-
- printf ("%s\n", descriptions->data);
-
- return SVN_NO_ERROR;
-}
-
-
-
-/* Print either generic help, or command-specific help for each
- * command in os->args. OPT_STATE is only examined for the
- * '--version' switch. If OS is null then generic help will always be
- * printed.
- *
- * Unlike all the other command routines, ``help'' has its own
- * option processing.
- */
-svn_error_t *
-svn_cl__help (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
- apr_pool_t *pool)
-{
- apr_array_header_t *targets = NULL;
- int i;
-
- if (os)
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
-
- if (targets && targets->nelts) /* help on subcommand(s) requested */
- for (i = 0; i < targets->nelts; i++)
- {
- svn_stringbuf_t *this = (((svn_stringbuf_t **) (targets)->elts))[i];
- svn_cl__subcommand_help (this->data, pool);
- }
- else if (opt_state && opt_state->version) /* just -v or --version */
- SVN_ERR (print_version_info (pool));
- else if (os && !targets->nelts) /* `-h', `--help', or `help' */
- svn_cl__print_generic_help (pool, stdout);
- else /* unknown option or cmd */
- svn_cl__print_generic_help (pool, stderr);
-
- return SVN_NO_ERROR;
-}
-
-
-
-/*
- * local variables:
- * eval: (load-file "../../../tools/dev/svn-dev.el")
- * end:
- */
Index: ./subversion/clients/cmdline/commit-cmd.c
===================================================================
--- ./subversion/clients/cmdline/commit-cmd.c
+++ ./subversion/clients/cmdline/commit-cmd.c Thu Apr 4 16:50:40 2002
@@ -40,10 +40,11 @@
 
 
 svn_error_t *
-svn_cl__commit (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__commit (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   apr_array_header_t *condensed_targets;
   svn_stringbuf_t *base_dir;
@@ -51,7 +52,7 @@
   svn_client_commit_info_t *commit_info = NULL;
   svn_revnum_t revnum;
     
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Build an authentication object to give to libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
Index: ./subversion/clients/cmdline/propset-cmd.c
===================================================================
--- ./subversion/clients/cmdline/propset-cmd.c
+++ ./subversion/clients/cmdline/propset-cmd.c Thu Mar 14 16:24:10 2002
@@ -34,10 +34,12 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__propset (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__propset (svn_getopt_t *os,
+ void *opt_state_,
                  apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
+ apr_array_header_t *args;
   svn_stringbuf_t *propname;
   const svn_string_t *propval = NULL;
   apr_array_header_t *targets;
@@ -50,18 +52,18 @@
   }
   /* PROPNAME and PROPVAL expected as first 2 arguments if filedata
      was NULL */
- SVN_ERR (svn_cl__parse_num_args (os, opt_state,
- "propset", num_args_wanted, pool));
+ SVN_ERR (svn_cl__parse_num_args (&args, os, "propset",
+ num_args_wanted, pool));
 
- propname = ((svn_stringbuf_t **) (opt_state->args->elts))[0];
+ propname = ((svn_stringbuf_t **) (args->elts))[0];
   if (num_args_wanted == 2)
     {
- svn_stringbuf_t *buf = ((svn_stringbuf_t **) (opt_state->args->elts))[1];
+ svn_stringbuf_t *buf = ((svn_stringbuf_t **) (args->elts))[1];
       propval = svn_string_create_from_buf (buf, pool);
     }
 
   /* suck up all the remaining arguments into a targets array */
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Add "." if user passed 0 file arguments */
   svn_cl__push_implicit_dot_target(targets, pool);
Index: ./subversion/clients/cmdline/switch-cmd.c
===================================================================
--- ./subversion/clients/cmdline/switch-cmd.c
+++ ./subversion/clients/cmdline/switch-cmd.c Thu Mar 14 16:25:07 2002
@@ -35,10 +35,11 @@
 
 
 svn_error_t *
-svn_cl__switch (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__switch (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_stringbuf_t *target = NULL, *switch_url = NULL;
   svn_string_t str;
@@ -59,10 +60,10 @@
   /* This command should discover (or derive) exactly two cmdline
      arguments: a local path to update ("target"), and a new url to
      switch to ("switch_url"). */
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
   if (targets->nelts == 0)
     {
- svn_cl__subcommand_help ("switch", pool);
+ svn_cl__print_subcommand_help ("switch", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
   if (targets->nelts == 1)
Index: ./subversion/clients/cmdline/delete-cmd.c
===================================================================
--- ./subversion/clients/cmdline/delete-cmd.c
+++ ./subversion/clients/cmdline/delete-cmd.c Thu Apr 4 16:13:24 2002
@@ -35,16 +35,17 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__delete (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__delete (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_client_auth_baton_t *auth_baton = NULL;
   int i;
   svn_client_commit_info_t *commit_info = NULL;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Build an authentication object to give to libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
@@ -67,7 +68,7 @@
     }
   else
     {
- svn_cl__subcommand_help ("delete", pool);
+ svn_cl__print_subcommand_help ("delete", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/import-cmd.c
===================================================================
--- ./subversion/clients/cmdline/import-cmd.c
+++ ./subversion/clients/cmdline/import-cmd.c Thu Apr 4 16:13:24 2002
@@ -34,10 +34,11 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__import (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__import (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   svn_stringbuf_t *path;
   svn_stringbuf_t *url;
@@ -81,7 +82,7 @@
    * ### kff todo: review above behaviors.
    */
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Get a repository url. */
   if (targets->nelts < 1)
Index: ./subversion/clients/cmdline/proplist-cmd.c
===================================================================
--- ./subversion/clients/cmdline/proplist-cmd.c
+++ ./subversion/clients/cmdline/proplist-cmd.c Thu Mar 14 16:23:51 2002
@@ -34,14 +34,15 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__proplist (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__proplist (svn_getopt_t *os,
+ void *opt_state_,
                   apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_array_header_t *targets;
   int i;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Add "." if user passed 0 arguments */
   svn_cl__push_implicit_dot_target(targets, pool);
Index: ./subversion/clients/cmdline/resolve-cmd.c
===================================================================
--- ./subversion/clients/cmdline/resolve-cmd.c
+++ ./subversion/clients/cmdline/resolve-cmd.c Thu Mar 14 16:35:03 2002
@@ -36,15 +36,16 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__resolve (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__resolve (svn_getopt_t *os,
+ void *opt_state_,
                  apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   svn_error_t *err;
   apr_array_header_t *targets;
   int i;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   if (targets->nelts)
     {
@@ -70,7 +71,7 @@
     }
   else
     {
- svn_cl__subcommand_help ("resolve", pool);
+ svn_cl__print_subcommand_help ("resolve", os, pool);
       return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
     }
 
Index: ./subversion/clients/cmdline/status-cmd.c
===================================================================
--- ./subversion/clients/cmdline/status-cmd.c
+++ ./subversion/clients/cmdline/status-cmd.c Thu Mar 14 16:24:56 2002
@@ -34,17 +34,18 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__status (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__status (svn_getopt_t *os,
+ void *opt_state_,
                 apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
   apr_hash_t *statushash;
   apr_array_header_t *targets;
   int i;
   svn_client_auth_baton_t *auth_baton;
   svn_revnum_t youngest = SVN_INVALID_REVNUM;
 
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Build an authentication object to give to libsvn_client. */
   auth_baton = svn_cl__make_auth_baton (opt_state, pool);
Index: ./subversion/clients/cmdline/main.c
===================================================================
--- ./subversion/clients/cmdline/main.c
+++ ./subversion/clients/cmdline/main.c Wed Mar 20 17:01:23 2002
@@ -72,41 +72,9 @@
     {0, 0, 0}
   };
 
-
-/* The maximum number of options that can be accepted by a subcommand;
- this is simply the number of unique switches that exist in the
- table above. */
-#define SVN_CL__MAX_OPTS sizeof(svn_cl__options)/sizeof(svn_cl__options[0])
-
-
 
 /*** Command dispatch. ***/
 
-/* The maximum number of aliases a subcommand can have. */
-#define SVN_CL__MAX_ALIASES 3
-
-
-/* One element of the command dispatch table. */
-typedef struct svn_cl__cmd_desc_t
-{
- /* The full name of this command. */
- const char *name;
-
- /* The function this command invokes. */
- svn_cl__cmd_proc_t *cmd_func;
-
- /* A list of alias names for this command. */
- const char *aliases[SVN_CL__MAX_ALIASES];
-
- /* A brief string describing this command, for usage messages. */
- const char *help;
-
- /* A list of options accepted by this command. Each value in the
- array is a unique enum (the 2nd field in apr_getopt_option_t) */
- int valid_options[SVN_CL__MAX_OPTS];
-
-} svn_cl__cmd_desc_t;
-
 
 
 /* Our array of available subcommands.
@@ -119,14 +87,14 @@
     "Put files and directories under revision control, scheduling\n"
     "them for addition to repository. They will be added in next commit.\n"
     "usage: svn add [OPTIONS] [TARGETS]\n",
- {svn_cl__targets_opt, svn_cl__recursive_opt} },
+ {svn_cl__recursive_opt, svn_cl__recursive_opt, 0} },
 
- { "checkout", svn_cl__checkout, {"co"},
+ { "checkout", svn_cl__checkout, {"co", 0},
     "Check out a working copy from a repository.\n"
     "usage: svn checkout REPOS_URL\n",
     {'d', 'r', 'D', 'q', 'n',
      svn_cl__auth_username_opt, svn_cl__auth_password_opt,
- svn_cl__xml_file_opt } },
+ svn_cl__xml_file_opt, 0} },
 
   { "cleanup", svn_cl__cleanup, {0},
     "Recursively clean up the working copy, removing locks, resuming\n"
@@ -134,16 +102,16 @@
     "usage: svn cleanup [TARGETS]\n",
     {0} },
   
- { "commit", svn_cl__commit, {"ci"},
+ { "commit", svn_cl__commit, {"ci", 0},
     "Send changes from your working copy to the repository.\n"
     "usage: svn commit [TARGETS]\n\n"
     " Be sure to use one of -m or -F to send a log message;\n"
     " the -r switch is only for use with --xml-file.\n",
     {'m', 'F', 'q', svn_cl__targets_opt,
      svn_cl__force_opt, svn_cl__auth_username_opt, svn_cl__auth_password_opt,
- svn_cl__xml_file_opt, 'r'} },
+ svn_cl__xml_file_opt, 'r', 0} },
   
- { "copy", svn_cl__copy, {"cp"},
+ { "copy", svn_cl__copy, {"cp", 0},
     "Duplicate something in working copy or repos, remembering history.\n"
     "usage: svn copy SRC DST.\n\n"
     " SRC and DST can each be either a working copy (WC) path or URL:\n"
@@ -151,9 +119,9 @@
     " WC -> URL: immediately commit a copy of WC to URL\n"
     " URL -> WC: check out URL into WC, schedule for addition\n"
     " URL -> URL: complete server-side copy; used to branch & tag\n",
- {'m', 'F', 'r', svn_cl__auth_username_opt, svn_cl__auth_password_opt} },
+ {'m', 'F', 'r', svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
   
- { "delete", svn_cl__delete, {"del", "remove", "rm"},
+ { "delete", svn_cl__delete, {"del", "remove", "rm", 0},
     "Remove files and directories from version control.\n"
     "usage: svn delete [TARGET | URL]\n\n"
     " If run on a working-copy TARGET, item is scheduled for deletion\n"
@@ -161,19 +129,19 @@
     " if --force is passed.) If run on URL, item is deleted from\n"
     " repository via an immediate commit.\n",
     {svn_cl__force_opt, 'm', 'F', svn_cl__targets_opt,
- svn_cl__auth_username_opt, svn_cl__auth_password_opt} },
+ svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
   
- { "diff", svn_cl__diff, {"di"},
+ { "diff", svn_cl__diff, {"di", 0},
     "Display local changes in the working copy, or changes between the\n"
     "working copy and the repository if a revision is given.\n"
     "usage: svn diff [-r REV1[:REV2]] [TARGETS]\n",
     {'r', 'D', 'x', 'n',
- svn_cl__auth_username_opt, svn_cl__auth_password_opt} },
-
- { "help", svn_cl__help, {"?", "h"},
+ svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
+
+ { "help", svn_cl__help, {"?", "h", 0},
     "Display this usage message.\n"
     "usage: svn help [SUBCOMMAND1 [SUBCOMMAND2] ...]\n",
- {svn_cl__version_opt} },
+ {svn_cl__version_opt, 0} },
   /* We need to support "--help", "-?", and all that good stuff, of
      course. But those options, since unknown, will result in the
      help message being printed out anyway, so there's no need to
@@ -187,7 +155,7 @@
     " directly. Otherwise, create NEW_ENTRY underneath REPOS_URL and\n"
     " begin copy there. (-r is only needed if importing to --xml-file)\n",
     {'F', 'm', 'q', svn_cl__auth_username_opt, svn_cl__auth_password_opt,
- svn_cl__xml_file_opt, 'r'} },
+ svn_cl__xml_file_opt, 'r', 0} },
   
   { "log", svn_cl__log, {0},
     "Show the log messages for a set of revision(s) and/or file(s).\n"
@@ -205,62 +173,62 @@
     "\n"
     " svn log http://www.example.com/repo/project foo.c bar.c\n",
     {'r', 'D', 'v', svn_cl__targets_opt, svn_cl__auth_username_opt,
- svn_cl__auth_password_opt} },
+ svn_cl__auth_password_opt, 0} },
   
   { "merge", svn_cl__merge, {0},
     "Merge changes in the working copy. IMPLEMENTATION INCOMPLETE.\n"
     "usage: svn merge [-r REV1[:REV2]] [TARGETS]\n",
     {'r', 'D', 'x', 'n',
- svn_cl__auth_username_opt, svn_cl__auth_password_opt} },
+ svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
   
   { "mkdir", svn_cl__mkdir, {0},
     "Create a new directory under revision control.\n"
     "usage: mkdir [NEW_DIR | REPOS_URL].\n\n"
     " Either create NEW_DIR in working copy scheduled for addition,\n"
     " or create REPOS_URL via immediate commit.\n",
- {'m', 'F', svn_cl__auth_username_opt, svn_cl__auth_password_opt} },
+ {'m', 'F', svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
 
- { "move", svn_cl__move, {"mv", "rename", "ren"},
+ { "move", svn_cl__move, {"mv", "rename", "ren", 0},
     "Move/rename something in working copy or repository.\n"
     "usage: move SRC DST.\n\n"
     " NOTE: this command is equivalent to a 'copy' and 'delete'.\n\n"
     " SRC and DST can both be working copy (WC) paths or URLs:\n"
     " WC -> WC: move and schedule for addition (with history)\n"
     " URL -> URL: complete server-side rename.\n",
- {'m', 'F', 'r', svn_cl__auth_username_opt, svn_cl__auth_password_opt} },
+ {'m', 'F', 'r', svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
   
- { "propdel", svn_cl__propdel, {"pdel"},
+ { "propdel", svn_cl__propdel, {"pdel", 0},
     "Remove property PROPNAME on files and directories.\n"
     "usage: propdel PROPNAME [TARGETS]\n",
- {'q', svn_cl__recursive_opt} },
+ {'q', svn_cl__recursive_opt, 0} },
   
- { "propedit", svn_cl__propedit, {"pedit", "pe"},
+ { "propedit", svn_cl__propedit, {"pedit", "pe", 0},
     "Edit property PROPNAME with $EDITOR on targets.\n"
     "usage: propedit PROPNAME [TARGETS]\n",
     {0} },
   
- { "propget", svn_cl__propget, {"pget", "pg"},
+ { "propget", svn_cl__propget, {"pget", "pg", 0},
     "Print value of property PROPNAME on files or directories.\n"
     "usage: propget PROPNAME [TARGETS]\n",
- {svn_cl__recursive_opt} },
+ {svn_cl__recursive_opt, 0} },
   
- { "proplist", svn_cl__proplist, {"plist", "pl"},
+ { "proplist", svn_cl__proplist, {"plist", "pl", 0},
     "List all properties attached to files or directories.\n"
     "usage: proplist [TARGETS]\n",
- {'v', svn_cl__recursive_opt} },
+ {'v', svn_cl__recursive_opt, 0} },
   
- { "propset", svn_cl__propset, {"pset", "ps"},
+ { "propset", svn_cl__propset, {"pset", "ps", 0},
     "Set property PROPNAME to PROPVAL on files or directories.\n"
     "usage: propset PROPNAME PROPVAL [TARGETS]\n\n"
     " Use -F (instead of PROPVAL) to get the value from a file.\n",
- {'F', 'q', svn_cl__targets_opt, svn_cl__recursive_opt} },
+ {'F', 'q', svn_cl__targets_opt, svn_cl__recursive_opt, 0} },
   
   { "revert", svn_cl__revert, {0},
     "Restore pristine working copy file (undo all local edits)\n"
     "usage: revert TARGET1 [TARGET2 [TARGET3 ... ]]\n\n"
- " Note: this routine does not require network access, and \n"
+ " Note: this routine does not require network access, and\n"
     " resolves any conflicted states.\n",
- {svn_cl__targets_opt, svn_cl__recursive_opt} },
+ {svn_cl__targets_opt, svn_cl__recursive_opt, 0} },
 
   { "resolve", svn_cl__resolve, {0},
     "Remove 'conflicted' state on working copy files or directories.\n"
@@ -268,9 +236,9 @@
     " Note: this routine does not semantically resolve conflict markers;\n"
     " it merely removes conflict-related artifact files and allows TARGET\n"
     " to be committed again.\n",
- {svn_cl__targets_opt} },
-
- { "status", svn_cl__status, {"stat", "st"},
+ {svn_cl__targets_opt, 0} },
+
+ { "status", svn_cl__status, {"stat", "st", 0},
     "Print the status of working copy files and directories.\n"
     "usage: svn status [TARGETS]\n\n"
     " With no args, print only locally modified files (no network access).\n"
@@ -282,256 +250,28 @@
     " _ * 965 970 sussman ./build.conf\n"
     " M 965 687 joe ./buildcheck.sh\n",
     { 'u', 'v', 'n', 'q',
- svn_cl__auth_username_opt, svn_cl__auth_password_opt } },
+ svn_cl__auth_username_opt, svn_cl__auth_password_opt, 0} },
   
- { "switch", svn_cl__switch, {"sw"},
+ { "switch", svn_cl__switch, {"sw", 0},
     "Update working copy to mirror a new URL\n"
     "usage: switch [TARGET] REPOS_URL\n\n" /* ### should args be reversed? */
     " Note: this is the way to move a working copy to a new branch.\n",
- {'r', 'n', svn_cl__force_opt} },
+ {'r', 'n', svn_cl__force_opt, 0} },
  
- { "update", svn_cl__update, {"up"},
+ { "update", svn_cl__update, {"up", 0},
     "Bring changes from the repository into the working copy.\n"
     "usage: update [TARGETS]\n\n"
     " If no revision given, bring working copy up-to-date with HEAD rev.\n"
     " Else synchronize working copy to revision given by -r or -D.\n",
     {'r', 'D', 'n', svn_cl__auth_username_opt,
- svn_cl__auth_password_opt, svn_cl__xml_file_opt} },
+ svn_cl__auth_password_opt, svn_cl__xml_file_opt, 0} },
 
   { NULL, NULL, {0}, NULL, {0} }
 };
 
-
-
-
-/* Return the entry in svn_cl__cmd_table whose name matches CMD_NAME,
- * or NULL if none. CMD_NAME may be an alias. */
-static const svn_cl__cmd_desc_t *
-svn_cl__get_canonical_command (const char *cmd_name)
-{
- int i = 0;
-
- if (cmd_name == NULL)
- return NULL;
-
- while (svn_cl__cmd_table[i].name) {
- int j;
- if (strcmp (cmd_name, svn_cl__cmd_table[i].name) == 0)
- return svn_cl__cmd_table + i;
- for (j = 0;
- (j < SVN_CL__MAX_ALIASES) && svn_cl__cmd_table[i].aliases[j];
- j++)
- if (strcmp (cmd_name, svn_cl__cmd_table[i].aliases[j]) == 0)
- return svn_cl__cmd_table + i;
-
- i++;
- }
-
- /* If we get here, there was no matching command name or alias. */
- return NULL;
-}
-
-
-
 
 /*** 'help' processing ***/
 
-/* Print an option OPT nicely into a STRING allocated in POOL. If DOC
- is set, include generic documentation string of option.*/
-static void
-format_option (char **string,
- const apr_getopt_option_t *opt,
- svn_boolean_t doc,
- apr_pool_t *pool)
-{
- char *opts;
-
- if (opt == NULL)
- *string = apr_psprintf (pool, "?");
-
- if (opt->optch <= 255)
- opts = apr_psprintf (pool, "-%c [--%s]", opt->optch, opt->name);
- else
- opts = apr_psprintf (pool, "--%s", opt->name);
-
- if (opt->has_arg)
- opts = apr_pstrcat (pool, opts, " arg", NULL);
-
- if (doc)
- opts = apr_pstrcat (pool, opts, ":\t", opt->description, NULL);
-
- *string = opts;
-}
-
-
-
-const apr_getopt_option_t *
-svn_cl__get_option_from_enum (int code,
- const apr_getopt_option_t *option_table)
-{
- int i;
- const apr_getopt_option_t *opt = NULL;
-
- for (i = 0; i < SVN_CL__MAX_OPTS; i++)
- {
- if (option_table[i].optch == code)
- {
- opt = &(option_table[i]);
- break;
- }
- }
-
- return opt;
-}
-
-
-/* Return TRUE iff subcommand COMMAND has OPTION_CODE listed within
- it. Else return FALSE. */
-static svn_boolean_t
-subcommand_takes_option (const svn_cl__cmd_desc_t *command,
- int option_code)
-{
- int i;
-
- for (i = 0; i < SVN_CL__MAX_OPTS; i++)
- {
- if (command->valid_options[i] == option_code)
- return TRUE;
- }
- return FALSE;
-}
-
-
-/* Print the canonical command name for CMD, all its aliases,
- and if HELP is set, print the help string for the command too. */
-static void
-print_command_info (const svn_cl__cmd_desc_t *cmd_desc,
- svn_boolean_t help,
- apr_pool_t *pool,
- FILE *stream)
-{
- const svn_cl__cmd_desc_t *canonical_cmd
- = svn_cl__get_canonical_command (cmd_desc->name);
- svn_boolean_t first_time;
- int i;
-
- /* Print the canonical command name. */
- fputs (canonical_cmd->name, stream);
-
- /* Print the list of aliases. */
- first_time = TRUE;
- for (i = 0; i < SVN_CL__MAX_ALIASES; i++)
- {
- if (canonical_cmd->aliases[i] == NULL)
- break;
-
- if (first_time) {
- fprintf (stream, " (");
- first_time = FALSE;
- }
- else
- fprintf (stream, ", ");
-
- fprintf (stream, "%s", canonical_cmd->aliases[i]);
- }
-
- if (! first_time)
- fprintf (stream, ")");
-
- if (help)
- {
- const apr_getopt_option_t *option;
- svn_boolean_t have_options = FALSE;
-
- fprintf (stream, ": %s", canonical_cmd->help);
-
- /* Loop over all valid option codes attached to the subcommand */
- for (i = 0; i < SVN_CL__MAX_OPTS; i++)
- {
- if (canonical_cmd->valid_options[i])
- {
- if (have_options == FALSE)
- {
- fprintf (stream, "\nValid options:\n");
- have_options = TRUE;
- }
-
- /* convert each option code into an option */
- option =
- svn_cl__get_option_from_enum (canonical_cmd->valid_options[i],
- svn_cl__options);
-
- /* print the option's docstring */
- if (option)
- {
- char *optstr;
- format_option (&optstr, option, TRUE, pool);
- fprintf (stream, " %s\n", optstr);
- }
- }
- }
-
- if (have_options)
- fprintf (stream, "\n");
- }
-}
-
-
-
-/* Print a generic (non-command-specific) usage message. */
-void
-svn_cl__print_generic_help (apr_pool_t *pool, FILE *stream)
-{
- static const char usage[] =
- "usage: svn <subcommand> [options] [args]\n"
- "Type \"svn help <subcommand>\" for help on a specific subcommand.\n"
- "\n"
- "Most subcommands take file and/or directory arguments, recursing\n"
- "on the directories. If no arguments are supplied to such a\n"
- "command, it will recurse on the current directory (inclusive) by\n"
- "default.\n"
- "\n"
- "Available subcommands:\n";
-
- static const char info[] =
- "Subversion is a tool for revision control.\n"
- "For additional information, see http://subversion.tigris.org\n";
-
- int i = 0;
-
- fprintf (stream, "%s", usage);
- while (svn_cl__cmd_table[i].name)
- {
- fprintf (stream, " ");
- print_command_info (svn_cl__cmd_table + i, FALSE, pool, stream);
- fprintf (stream, "\n");
- i++;
- }
-
- fprintf (stream, "\n");
- fprintf (stream, "%s\n", info);
-
-}
-
-
-/* Helper function that will print the usage test of a subcommand
- * given the subcommand name as a char*. This function is also
- * used by subcommands that need to print a usage message */
-
-void
-svn_cl__subcommand_help (const char* subcommand,
- apr_pool_t *pool)
-{
- const svn_cl__cmd_desc_t *cmd =
- svn_cl__get_canonical_command (subcommand);
-
- if (cmd)
- print_command_info (cmd, TRUE, pool, stdout);
- else
- fprintf (stderr, "\"%s\": unknown command.\n\n", subcommand);
-}
-
-
 
 /*** Parsing "X:Y"-style arguments. ***/
 
@@ -771,18 +511,13 @@
 main (int argc, const char * const *argv)
 {
   int ret;
- apr_status_t apr_err;
   svn_error_t *err;
   apr_pool_t *pool;
- int opt_id;
- const char *opt_arg;
- apr_getopt_t *os;
+ svn_getopt_t *os;
   svn_cl__opt_state_t opt_state;
- int received_opts[SVN_CL__MAX_OPTS];
- int i, num_opts = 0;
- const svn_cl__cmd_desc_t *subcommand = NULL;
   svn_boolean_t log_under_version_control = FALSE;
   svn_boolean_t log_is_pathname = FALSE;
+ int i;
 
   /* FIXME: This is a first step towards support for localization in
      `svn'. In real life, this call would be
@@ -797,11 +532,10 @@
      the default locale at program startup.) */
   setlocale (LC_ALL, "C");
 
-
   apr_initialize ();
   pool = svn_pool_create (NULL);
- memset (&opt_state, 0, sizeof (opt_state));
 
+ memset (&opt_state, 0, sizeof (opt_state));
   opt_state.start_revision.kind = svn_client_revision_unspecified;
   opt_state.end_revision.kind = svn_client_revision_unspecified;
   
@@ -814,24 +548,18 @@
     }
 
   /* Else, parse options. */
- apr_getopt_init (&os, pool, argc, argv);
- os->interleave = 1;
- while (1)
- {
- /* Parse the next option. */
- apr_err = apr_getopt_long (os, svn_cl__options, &opt_id, &opt_arg);
- if (APR_STATUS_IS_EOF (apr_err))
- break;
- else if (! APR_STATUS_IS_SUCCESS (apr_err))
- {
- svn_cl__help (NULL, NULL, pool);
- svn_pool_destroy (pool);
- return EXIT_FAILURE;
- }
+ if (APR_SUCCESS != svn_getopt_init (&os, pool, argc, argv, svn_cl__options, svn_cl__cmd_table))
+ {
+ svn_cl__help (NULL, NULL, pool);
+ svn_pool_destroy (pool);
+ return EXIT_FAILURE;
+ }
 
- /* Stash the option code in an array before parsing it. */
- received_opts[num_opts] = opt_id;
- num_opts++;
+ /* Handle specific command line option issues. */
+ for (i=0; i<os->num_received_opts; ++i)
+ {
+ const int opt_id = os->received_opts[i];
+ const char *opt_arg = os->received_args[i];
 
       switch (opt_id) {
       case 'm':
@@ -998,53 +726,22 @@
      just typos/mistakes. Whatever the case, the subcommand to
      actually run is svn_cl__help(). */
   if (opt_state.help)
- subcommand = svn_cl__get_canonical_command ("help");
+ os->subcommand = svn_cl__get_canonical_command ("help", svn_cl__cmd_table);
 
   /* If we're not running the `help' subcommand, then look for a
      subcommand in the first argument. */
- if (subcommand == NULL)
+ if (os->subcommand == NULL)
     {
- if (os->ind >= os->argc)
+ if (os->options->ind >= os->options->argc)
         {
           fprintf (stderr, "subcommand argument required\n");
           svn_cl__help (NULL, NULL, pool);
           svn_pool_destroy (pool);
           return EXIT_FAILURE;
         }
- else
- {
- const char *first_arg = os->argv[os->ind++];
- subcommand = svn_cl__get_canonical_command (first_arg);
- if (subcommand == NULL)
- {
- /* FIXME: should we print "unknown foo" ?? seems ok */
- fprintf (stderr, "unknown command: %s\n", first_arg);
- svn_cl__help (NULL, NULL, pool);
- svn_pool_destroy (pool);
- return EXIT_FAILURE;
- }
- }
     }
 
- /* If we made it this far, then we definitely have the subcommand,
- so call it. But first check that it wasn't passed any
- inappropriate options. */
- for (i = 0; i < num_opts; i++)
- if (! subcommand_takes_option (subcommand, received_opts[i]))
- {
- char *optstr;
- const apr_getopt_option_t *badopt =
- svn_cl__get_option_from_enum (received_opts[i], svn_cl__options);
- format_option (&optstr, badopt, FALSE, pool);
- fprintf (stderr,
- "\nError: subcommand '%s' doesn't accept option '%s'\n\n",
- subcommand->name, optstr);
- svn_cl__subcommand_help (subcommand->name, pool);
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
- }
-
- if (subcommand->cmd_func == svn_cl__commit)
+ if (os->subcommand->cmd_func == svn_cl__commit)
     {
       /* If the log message file is under revision control, that's
          probably not what the user intended. */
@@ -1076,7 +773,7 @@
         }
     }
 
- err = (*subcommand->cmd_func) (os, &opt_state, pool);
+ err = (*os->subcommand->cmd_func) (os, &opt_state, pool);
   if (err)
     {
       if (err->apr_err != SVN_ERR_CL_ARG_PARSING_ERROR)
Index: ./subversion/clients/cmdline/propedit-cmd.c
===================================================================
--- ./subversion/clients/cmdline/propedit-cmd.c
+++ ./subversion/clients/cmdline/propedit-cmd.c Thu Mar 14 16:22:22 2002
@@ -34,22 +34,24 @@
 /*** Code. ***/
 
 svn_error_t *
-svn_cl__propedit (apr_getopt_t *os,
- svn_cl__opt_state_t *opt_state,
+svn_cl__propedit (svn_getopt_t *os,
+ void *opt_state_,
                   apr_pool_t *pool)
 {
+ svn_cl__opt_state_t *opt_state = (svn_cl__opt_state_t *)opt_state_;
+ apr_array_header_t *args;
   svn_stringbuf_t *propname;
   apr_array_header_t *targets;
   int i;
 
   /* Validate the input. */
- SVN_ERR (svn_cl__parse_num_args (os, opt_state, "propedit", 1, pool));
+ SVN_ERR (svn_cl__parse_num_args (&args, os, "propedit", 1, pool));
 
   /* Get the property's name. */
- propname = ((svn_stringbuf_t **) (opt_state->args->elts))[0];
+ propname = ((svn_stringbuf_t **) (args->elts))[0];
 
   /* Suck up all the remaining arguments into a targets array */
- targets = svn_cl__args_to_target_array (os, opt_state, pool);
+ targets = svn_cl__args_to_target_array (os, opt_state->targets, pool);
 
   /* Add "." if user passed 0 file arguments */
   svn_cl__push_implicit_dot_target (targets, pool);

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Jul 25 21:32:45 2002

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.