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

Re: Tabular command processing sans AutoOpts

From: Karl Fogel <kfogel_at_galois.collab.net>
Date: 2000-11-12 20:09:59 CET

Bruce,

I'd feel a little funny about adding lots of C stub files to the
command-line client source directory, without knowing more about why.

Could you post a ChangeLog entry, or whatever, describing the change
in more detail? Specifically, is it necessary to have all these stub
files present from the start, even those that aren't being used, or
could we instead just add them as they're needed? Are they
automatically generated from the table or something? (Hmm --
maintenance and comprehensibility issues.)

A detail: the names `tOptions', `t_cmd_desc', and `t_cl_cmd_proc'
would need to have the "svn_cl__" prefix, for the reasons described in
the top-level HACKING file.

Sorry, I'm not meaning to make this Pick On Bruce Day -- some sort of
command table looks like the right way to go, I just don't understand
the motivation behind all parts of this patch (I'd also like to hear
what some others think, as my only other experience with a command
table like this is in CVS).

Thanks,
-Karl

Bruce Korb <bkorb@cruzio.com> writes:
> This is a multi-part message in MIME format.
> --------------64FF6D299D8F06934F95CB18
> Content-Type: text/plain; charset=us-ascii
> Content-Transfer-Encoding: 7bit
>
>
> This patch will make the command line client become table driven.
> The option processing remains the (slightly) renamed parse_options
> procedure (svn_cl__parse_options), though we all know this method
> won't scale. :-) This patch will also add a bazillion stubs:
>
> diff -u -r1.7 Makefile.am
> --- Makefile.am 2000/10/26 20:02:16 1.7
> +++ Makefile.am 2000/11/12 20:45:36
> @@ -1,7 +1,11 @@
> ## Makefile.in is generated from this by automake.
>
> noinst_PROGRAMS = svn
> -svn_SOURCES = main.c status.c trace.c
> +svn_SOURCES = main.c status.c trace.c \
> + ad-cmd.c an-cmd.c ap-cmd.c br-cmd.c ci-cmd.c co-cmd.c cp-cmd.c \
> + cv-cmd.c df-cmd.c im-cmd.c lo-cmd.c me-cmd.c mv-cmd.c pg-cmd.c \
> + ps-cmd.c rd-cmd.c rm-cmd.c rp-cmd.c st-cmd.c sy-cmd.c tg-cmd.c \
> + up-cmd.c
>
> that were all mechanically generated. The implemented commands were
> patched with the working code from main.c. "make check" passes.
> --------------64FF6D299D8F06934F95CB18
> Content-Type: application/octet-stream;
> name="clcmd.tgz"
> Content-Transfer-Encoding: base64
> Content-Disposition: attachment;
> filename="clcmd.tgz"
>
> H4sIABkTDzoCA+2d/W+bSBrH++tG90fMdXVdp/KmeXESaav+QGySoHNsH+B0o7sTi2Eco8WA
> ADvnW+3/fs8M4JfYTa+rrqH2d6S2BoZnnnlmeOb5dJjB8T0epO9s90dn7B45r/6MdHJ8fNFo
> sFeMnVyenyz/K1Pj8uyCscvT47OL48YpZWQn9Lvxih2/2kKaJKkdM/ZqEE8c/kK+JHZe7WB6
> 9/aAvWWsaH/2IzMmgymPEy8M6KzLnHA8tgOXcsmMyTRgXsKGMecsCYfpkx1zyhPNYu9xlHKX
> DWasGfq+Pejw9EjeIv/SueslaewNJqmUHLhsknDmBSRlEjtcnhl4gR3P2DCMx0mdPXnpiIWx
> /DecpFLMOHS9oefYQkidibIjHo+9VJQcxeHUc+lHOrJT+ouTIN8Pn7zgkTQMXE/clGTVpRvH
> PP1JHpwcPdMuYeGwUMsJXcpKnYTFPLVJXSHXHoTTpVpLKZSCMPUcXqcsZCGfBAo5i5JlFVfV
> olId3/bGPM5MdbquChW5ZJZCFaqrS/31z9KGZRUtRLmhMxmTm7CLtntHzRJShpiN7ZTHnu0n
> C/PLdhOSlyuS1e/siHW4J28UGQJ7zNkvv8z7yw8/kNZLl0hhO5hlJRW6UA0yoaEofMYGXHQk
> qkrIeOCGMXUqukLKjMOUs8xOacJc0nLK3ULKkK5nlpl34rybsSTijuhjdK8nel8seleQ9bMk
> mVdl/jRoBuvp3XutpbbY1cOi81PFFIOuUqWUTov+PDD1556uGoa8tasz7a7X1uiuj4quKx1T
> U4060zrNdr+ldW7q7Kpvsk7XZG3tTjMpm9mtM/NWLW6TUha3su41u1P15i0dKldaWzMfZLnX
> mtmhMtk1FaiwnqKbWrPfVnTW6+u9rqFKMYquspZmNNuKdqe2jhipQUUz9V7tmMy4VdrtpXoJ
> QVSZLumis2a3Y+oaqdrVs3pdqaSwctVWsxIpY0vT1aYpqrb41SRzkZ7tOjN6alMTP9SfVaqY
> oj/UqQQpimQb6j/6lJEysJZyp9xQPWufMRE1RrOvq3dC9e61FGT0rwxTM/umym663ZYhqmCo
> +r3WVI33rN01pPX6hlqnUkxFKCDEkOnocq7MVd/QpCG1jqnqer9nat3OIbvtfiQrkR0Uur0l
> Ld7tyGqTebr6gxAs7CEbpJ612a0qTUc2ltZThEkMsmLTXMoqdCCjmkv1ZR31pq3dqJ2mWmgl
> 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
> --------------64FF6D299D8F06934F95CB18
> Content-Type: text/plain; charset=iso-8859-1;
> name="DIFF"
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: inline;
> filename="DIFF"
>
> Index: Makefile.am
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> RCS file: /cvs/subversion/subversion/client/Makefile.am,v
> retrieving revision 1.7
> diff -u -r1.7 Makefile.am
> --- Makefile.am 2000/10/26 20:02:16 1.7
> +++ Makefile.am 2000/11/12 20:45:36
> @@ -1,7 +1,11 @@
> ## Makefile.in is generated from this by automake.
> =
>
> noinst_PROGRAMS =3D svn
> -svn_SOURCES =3D main.c status.c trace.c
> +svn_SOURCES =3D main.c status.c trace.c \
> + ad-cmd.c an-cmd.c ap-cmd.c br-cmd.c ci-cmd.c co-cmd.c cp-cmd.c \
> + cv-cmd.c df-cmd.c im-cmd.c lo-cmd.c me-cmd.c mv-cmd.c pg-cmd.c \
> + ps-cmd.c rd-cmd.c rm-cmd.c rp-cmd.c st-cmd.c sy-cmd.c tg-cmd.c \
> + up-cmd.c
> =
>
> ## Flags needed when compiling:
> INCLUDES =3D -I. -I../include -I../../apr/include -I../../expat-lite
> Index: cl.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> RCS file: /cvs/subversion/subversion/client/cl.h,v
> retrieving revision 1.8
> diff -u -r1.8 cl.h
> --- cl.h 2000/11/12 18:08:55 1.8
> +++ cl.h 2000/11/12 20:45:37
> @@ -58,7 +58,72 @@
> #include "svn_wc.h"
> #include "svn_string.h"
> =
>
> +/* All client command procedures conform to this prototype */
> +typedef svn_error_t * (t_cl_cmd_proc) (int argc, char** argv, apr_pool_t=
> *);
> =
>
> +/* Structure type for the command dispatch table.
> + tOptions is a place-holder */
> +typedef void tOptions;
> +
> +typedef struct {
> + const char *cmd_name;
> + size_t name_len;
> + svn_boolean_t fork_first;
> + t_cl_cmd_proc *cmd_func;
> + tOptions* cmd_opts;
> +} t_cmd_desc;
> +
> +typedef enum {
> + NULL_COMMAND =3D 0,
> + ADD_COMMAND,
> + ANNOTATE_COMMAND,
> + APPLY_COMMAND,
> + BRANCH_COMMAND,
> + COMMIT_COMMAND,
> + CHECKOUT_COMMAND,
> + COPY_COMMAND,
> + CONVERT_COMMAND,
> + DIFF_COMMAND,
> + IMPORT_COMMAND,
> + LOG_COMMAND,
> + MERGE_COMMAND,
> + RENAME_COMMAND,
> + PROPGET_COMMAND,
> + PROPSET_COMMAND,
> + RDIFF_COMMAND,
> + DELETE_COMMAND,
> + REPO_COMMAND,
> + STATUS_COMMAND,
> + SYNC_COMMAND,
> + TAG_COMMAND,
> + UPDATE_COMMAND
> +} te_command;
> +
> +t_cl_cmd_proc
> + svn_cl__add,
> + svn_cl__annotate,
> + svn_cl__apply,
> + svn_cl__branch,
> + svn_cl__commit,
> + svn_cl__checkout,
> + svn_cl__copy,
> + svn_cl__convert,
> + svn_cl__diff,
> + svn_cl__help,
> + svn_cl__import,
> + svn_cl__log,
> + svn_cl__merge,
> + svn_cl__rename,
> + svn_cl__propget,
> + svn_cl__propset,
> + svn_cl__rdiff,
> + svn_cl__delete,
> + svn_cl__repo,
> + svn_cl__status,
> + svn_cl__sync,
> + svn_cl__tag,
> + svn_cl__update;
> +
> =0C
> /* Print PATH's status line using STATUS. */
> void svn_cl__print_status (svn_string_t *path, svn_wc_status_t *status);=
>
> @@ -75,6 +140,17 @@
> svn_string_t *initial_path,
> apr_pool_t *pool);
> =
>
> +/* Until there is something else, this is it */
> +void
> +svn_cl__parse_options (int argc,
> + char **argv,
> + te_command command,
> + svn_string_t **xml_file,
> + svn_string_t **target, /* dest_dir or file to ad=
> d */
> + svn_revnum_t *revision, /* ancestral or new */
> + svn_string_t **ancestor_path,
> + svn_boolean_t *force,
> + apr_pool_t *pool);
> #endif /* SVN_CL_H */
> =
>
> =0C
> Index: main.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> RCS file: /cvs/subversion/subversion/client/main.c,v
> retrieving revision 1.20
> diff -u -r1.20 main.c
> --- main.c 2000/11/12 18:06:15 1.20
> +++ main.c 2000/11/12 20:45:37
> @@ -65,24 +65,66 @@
> =0C
> /*** kff todo: this trace editor will get moved to its own file ***/
> =
>
> -
> -enum command =
>
> -{ checkout_command =3D 1,
> - update_command,
> - add_command,
> - delete_command,
> - commit_command,
> - status_command
> +static t_cmd_desc cmd_table[] =3D {
> + { "ad", 2, TRUE, svn_cl__add, NULL },
> + { "add", 3, TRUE, svn_cl__add, NULL },
> + { "an", 2, TRUE, svn_cl__annotate, NULL },
> + { "ann", 3, TRUE, svn_cl__annotate, NULL },
> + { "annotate", 8, TRUE, svn_cl__annotate, NULL },
> + { "ap", 2, TRUE, svn_cl__apply, NULL },
> + { "apply", 5, TRUE, svn_cl__apply, NULL },
> + { "branch", 6, TRUE, svn_cl__branch, NULL },
> + { "checkout", 8, TRUE, svn_cl__checkout, NULL },
> + { "ci", 2, TRUE, svn_cl__commit, NULL },
> + { "co", 2, TRUE, svn_cl__checkout, NULL },
> + { "commit", 6, TRUE, svn_cl__commit, NULL },
> + { "convert", 7, TRUE, svn_cl__convert, NULL },
> + { "copy", 4, TRUE, svn_cl__copy, NULL },
> + { "cp", 2, TRUE, svn_cl__copy, NULL },
> + { "cv", 2, TRUE, svn_cl__convert, NULL },
> + { "del", 3, TRUE, svn_cl__delete, NULL },
> + { "delete", 6, TRUE, svn_cl__delete, NULL },
> + { "di", 2, TRUE, svn_cl__diff, NULL },
> + { "dif", 3, TRUE, svn_cl__diff, NULL },
> + { "diff", 4, TRUE, svn_cl__diff, NULL },
> + { "help", 4, FALSE, svn_cl__help, NULL },
> + { "im", 2, TRUE, svn_cl__import, NULL },
> + { "imp", 3, TRUE, svn_cl__import, NULL },
> + { "import", 6, TRUE, svn_cl__import, NULL },
> + { "lo", 2, TRUE, svn_cl__log, NULL },
> + { "log", 3, TRUE, svn_cl__log, NULL },
> + { "me", 2, TRUE, svn_cl__merge, NULL },
> + { "merge", 5, TRUE, svn_cl__merge, NULL },
> + { "mv", 2, TRUE, svn_cl__rename, NULL },
> + { "new", 3, TRUE, svn_cl__add, NULL },
> + { "pg", 2, TRUE, svn_cl__propget, NULL },
> + { "pget", 4, TRUE, svn_cl__propget, NULL },
> + { "propget", 7, TRUE, svn_cl__propget, NULL },
> + { "propset", 7, TRUE, svn_cl__propset, NULL },
> + { "ps", 2, TRUE, svn_cl__propset, NULL },
> + { "pset", 4, TRUE, svn_cl__propset, NULL },
> + { "rdiff", 5, TRUE, svn_cl__rdiff, NULL },
> + { "rename", 6, TRUE, svn_cl__rename, NULL },
> + { "repo", 4, TRUE, svn_cl__repo, NULL },
> + { "rm", 2, TRUE, svn_cl__delete, NULL },
> + { "st", 2, TRUE, svn_cl__status, NULL },
> + { "stat", 4, TRUE, svn_cl__status, NULL },
> + { "status", 6, TRUE, svn_cl__status, NULL },
> + { "sy", 2, TRUE, svn_cl__sync, NULL },
> + { "sync", 4, TRUE, svn_cl__sync, NULL },
> + { "tag", 3, TRUE, svn_cl__tag, NULL },
> + { "up", 2, TRUE, svn_cl__update, NULL },
> + { "update", 6, TRUE, svn_cl__update, NULL }
> };
> =
>
> =
>
> +
> =0C
> /*** Code. ***/
> =
>
> static void
> parse_command_options (int argc,
> char **argv,
> - int i,
> char *progname,
> svn_string_t **xml_file,
> svn_string_t **target,
> @@ -91,7 +133,9 @@
> svn_boolean_t *force,
> apr_pool_t *pool)
> {
> - for (; i < argc; i++)
> + int i;
> +
> + for (i =3D 0; i < argc; i++)
> {
> if (strcmp (argv[i], "--xml-file") =3D=3D 0)
> {
> @@ -148,10 +192,10 @@
> /* We'll want an off-the-shelf option parsing system soon... too bad
> GNU getopt is out for copyright reasons (?). In the meantime,
> reinvent the wheel: */ =
>
> -static void
> -parse_options (int argc,
> +void
> +svn_cl__parse_options (int argc,
> char **argv,
> - enum command *command,
> + te_command command,
> svn_string_t **xml_file,
> svn_string_t **target, /* dest_dir or file to add */
> svn_revnum_t *revision, /* ancestral or new */
> @@ -162,170 +206,140 @@
> char *s =3D argv[0]; /* svn progname */
> int i;
> =
>
> - for (i =3D 1; i < argc; i++)
> - {
> - /* todo: do the cvs synonym thing eventually */
> - if (strcmp (argv[i], "checkout") =3D=3D 0)
> - {
> - *command =3D checkout_command;
> - goto do_command_opts;
> - }
> - else if (strcmp (argv[i], "update") =3D=3D 0)
> - {
> - *command =3D update_command;
> - goto do_command_opts;
> - }
> - else if (strcmp (argv[i], "add") =3D=3D 0)
> - {
> - *command =3D add_command;
> - goto do_command_opts;
> - }
> - else if (strcmp (argv[i], "delete") =3D=3D 0)
> - {
> - *command =3D delete_command;
> - goto do_command_opts;
> - }
> - else if (strcmp (argv[i], "commit") =3D=3D 0)
> - {
> - *command =3D commit_command;
> - goto do_command_opts;
> - }
> - else if (strcmp (argv[i], "status") =3D=3D 0)
> - {
> - *command =3D status_command;
> - goto do_command_opts;
> - }
> - else
> - {
> - fprintf (stderr, "%s: unknown or untimely argument \"%s\"\n",
> - s, argv[i]);
> - exit (1);
> - }
> - }
> -
> - do_command_opts:
> - parse_command_options (argc, argv, ++i, s,
> + /* Skip the program and subcommand names. Parse the rest. */
> + parse_command_options (argc-2, argv+2, s,
> xml_file, target, revision, ancestor_path, forc=
> e,
> pool);
> =
>
> /* Sanity checks: make sure we got what we needed. */
> - if (! *command)
> - {
> - fprintf (stderr, "%s: no command given\n", s);
> - exit (1);
> - }
> - if ((! *xml_file) && ((*command !=3D add_command)
> - && (*command !=3D status_command)
> - && (*command !=3D delete_command)))
> + /* Any command may have an xml_file, but ADD, STATUS and DELETE
> + *must* have the xml_file option */
> + if ((! *xml_file)
> + && (command !=3D ADD_COMMAND)
> + && (command !=3D STATUS_COMMAND)
> + && (command !=3D DELETE_COMMAND))
> {
> fprintf (stderr, "%s: need \"--xml-file FILE.XML\"\n", s);
> exit (1);
> }
> - if (*force && (*command !=3D delete_command))
> + if (*force && (command !=3D DELETE_COMMAND))
> {
> fprintf (stderr, "%s: \"--force\" meaningless except for delete\n"=
> , s);
> exit (1);
> }
> - if (((*command =3D=3D commit_command) && (*revision =3D=3D SVN_INVALID=
> _REVNUM))
> - || ((*command =3D=3D update_command) && (*revision =3D=3D SVN_INVA=
> LID_REVNUM)))
> + /* COMMIT and UPDATE must have a valid revision */
> + if ((*revision =3D=3D SVN_INVALID_REVNUM)
> + && ( (command =3D=3D COMMIT_COMMAND)
> + || (command =3D=3D UPDATE_COMMAND)))
> {
> fprintf (stderr, "%s: please use \"--revision VER\" "
> "to specify target revision\n", s);
> exit (1);
> }
> - if (((*command =3D=3D checkout_command) =
>
> - || (*command =3D=3D update_command)
> - || (*command =3D=3D commit_command)
> - || (*command =3D=3D status_command))
> - && (*target =3D=3D NULL))
> + /* CHECKOUT, UPDATE, COMMIT and STATUS have a default target */
> + if ((*target =3D=3D NULL)
> + && ( (command =3D=3D CHECKOUT_COMMAND) =
>
> + || (command =3D=3D UPDATE_COMMAND)
> + || (command =3D=3D COMMIT_COMMAND)
> + || (command =3D=3D STATUS_COMMAND)))
> *target =3D svn_string_create (".", pool);
> }
> =
>
> =
>
> +svn_error_t *
> +svn_cl__help (int argc, char **argv, apr_pool_t* pool)
> +{
> + static const char zUsage[] =3D
> + "What command do you need help with?\n"
> + "You must type the command you need help with along with the `--help=
> '\n"
> + "command line option. Choose from the following commands:\n\n";
> +
> + int ix =3D 0;
> + t_cmd_desc* pCD =3D cmd_table;
> +
> + fputs( zUsage, stdout );
> +
> + for (;;)
> + {
> + printf( " %-8s", (pCD++)->cmd_name );
> + if (++ix >=3D sizeof( cmd_table ) / sizeof( cmd_table[0] ))
> + break;
> + if ((ix % 7) =3D=3D 0)
> + fputc( '\n', stdout );
> + }
> +
> + fputc( '\n', stdout );
> + return NULL;
> +}
> +
> +
> +static t_cmd_desc*
> +get_cmd_table_entry (char* pz_cmd)
> +{
> + int hi =3D (sizeof( cmd_table )/sizeof( cmd_table[0] )) - 1;
> + int lo =3D 0;
> + int av, cmp;
> +
> + if (pz_cmd =3D=3D NULL)
> + {
> + fputs( "svn error: no command name provided\n", stderr );
> + (void)svn_cl__help( 0, NULL, NULL );
> + return NULL;
> + }
> +
> + /* Regardless of the option chosen, the user gets --help :-) */
> + if (*pz_cmd =3D=3D '-')
> + {
> + (void)svn_cl__help( 0, NULL, NULL );
> + return NULL;
> + }
> +
> + for (;;)
> + {
> + av =3D (hi + lo) / 2;
> + cmp =3D strcmp (pz_cmd, cmd_table[av].cmd_name);
> +
> + if (cmp =3D=3D 0)
> + break;
> +
> + if (cmp > 0)
> + lo =3D av + 1;
> + else
> + hi =3D av - 1;
> +
> + if (hi < lo)
> + {
> + fprintf (stderr, "svn error: `%s' is an unknown command\n", p=
> z_cmd);
> + (void)svn_cl__help( 0, NULL, NULL );
> + return NULL;
> + }
> + }
> +
> + return cmd_table + av;
> +}
> +
> +
> int
> main (int argc, char **argv)
> {
> + t_cmd_desc* p_cmd =3D get_cmd_table_entry (argv[1]);
> svn_error_t *err;
> apr_pool_t *pool;
> - svn_revnum_t revision =3D SVN_INVALID_REVNUM;
> - svn_string_t *xml_file =3D NULL;
> - svn_string_t *target =3D NULL;
> - svn_string_t *ancestor_path =3D NULL;
> - svn_boolean_t force =3D 0;
> - enum command command =3D 0;
> - const svn_delta_edit_fns_t *trace_editor;
> - void *trace_edit_baton;
> =
>
> + if (p_cmd =3D=3D NULL)
> + return EXIT_FAILURE;
> +
> apr_initialize ();
> pool =3D svn_pool_create (NULL);
> -
> - parse_options (argc, argv, &command,
> - &xml_file, &target, &revision, &ancestor_path, &force,
> - pool);
> - =
>
> - switch (command)
> - {
> - /* kff todo: can combine checkout and update cases w/ flag */
> - case checkout_command:
> - {
> - err =3D svn_cl__get_trace_editor (&trace_editor,
> - &trace_edit_baton,
> - target,
> - pool);
> - if (err)
> - goto handle_error;
> - }
> - err =3D svn_client_checkout (NULL, NULL,
> - trace_editor,
> - trace_edit_baton,
> - target, xml_file,
> - ancestor_path, revision, pool);
> - break;
> - case update_command:
> - {
> - err =3D svn_cl__get_trace_editor (&trace_editor,
> - &trace_edit_baton,
> - target,
> - pool);
> - if (err)
> - goto handle_error;
> - }
> - err =3D svn_client_update (NULL, NULL,
> - trace_editor, trace_edit_baton,
> - target, xml_file, revision, pool);
> - break;
> - case add_command:
> - err =3D svn_client_add (target, pool);
> - break;
> - case delete_command:
> - err =3D svn_client_delete (target, force, pool);
> - break;
> - case commit_command:
> - err =3D svn_client_commit (target, xml_file, revision, pool);
> - break;
> - case status_command:
> - {
> - apr_hash_t *statushash;
> - err =3D svn_client_status (&statushash, target, pool);
> - if (! err) =
>
> - svn_cl__print_status_list (statushash, pool);
> - break;
> - }
> - default:
> - fprintf (stderr, "no command given");
> - exit (1);
> - }
> =
>
> - handle_error:
> + err =3D (*p_cmd->cmd_func) (argc, argv, pool);
> if (err)
> svn_handle_error (err, stdout, 0);
> =
>
> apr_destroy_pool (pool);
> =
>
> - return 0;
> + return EXIT_SUCCESS;
> }
> -
> -
> =0C
> /* =
>
> * local variables:
>
> --------------64FF6D299D8F06934F95CB18--
Received on Sat Oct 21 14:36:14 2006

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.