@matheusbsbs / matheus-bagliano / commits / 52e7787609
Fork 0

archive: use parseopt for local-only options

Replace the hand-rolled parsers that find and remove --remote and --exec by a parseopt parser that also handles --output. All three options only have a meaning if no remote server is used or on the local side. They must be rejected by upload-archive and should not be sent to the server by archive. We can't use a single parser for both remote and local side because the remote end possibly understands a different set of options than the local side. A local parser would then wrongly accuse options valid on the other side as being incorrect. This patch implements a very forgiving parser that understands only the three options mentioned above. All others are passed to the normal, complete parser in archive.c (running either locally in archive, or remotely in upload-archive). This normal parser definition contains dummy entries for the three options, in order for them to appear in the help screen. The parseopt parser allows multiple occurrences of --remote and --exec unlike the previous one; the one specified last wins. This looseness is acceptable, I think. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Mar 8, 2009 at 19:21 UTC 52e7787609d18af76a8c1befb0a06123fb7ce89e
2 files changed +40 -81
archive.c
+2 -16
@@ -239,19 +239,6 @@ static void parse_treeish_arg(const char **argv,
239 ar_args->time = archive_time;
240 }
241
242 -static void create_output_file(const char *output_file)
243 -{
244 - int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
245 - if (output_fd < 0)
246 - die("could not create archive file: %s ", output_file);
247 - if (output_fd != 1) {
248 - if (dup2(output_fd, 1) < 0)
249 - die("could not redirect output");
250 - else
251 - close(output_fd);
252 - }
253 -}
254 -
242 #define OPT__COMPR(s, v, h, p) \
243 { OPTION_SET_INT, (s), NULL, (v), NULL, (h), \
244 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, (p) }
@@ -306,13 +293,12 @@ static int parse_archive_args(int argc, const char **argv,
293 die("Unexpected option --remote");
294 if (exec)
295 die("Option --exec can only be used together with --remote");
296 + if (output)
297 + die("Unexpected option --output");
298
299 if (!base)
300 base = "";
301
313 - if (output)
314 - create_output_file(output);
315 -
302 if (list) {
303 for (i = 0; i < ARRAY_SIZE(archivers); i++)
304 printf("%s\n", archivers[i].name);
builtin-archive.c
+38 -65
@@ -5,44 +5,35 @@
5 #include "cache.h"
6 #include "builtin.h"
7 #include "archive.h"
8 +#include "parse-options.h"
9 #include "pkt-line.h"
10 #include "sideband.h"
11
11 -static int run_remote_archiver(const char *remote, int argc,
12 - const char **argv)
12 +static void create_output_file(const char *output_file)
13 +{
14 + int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
15 + if (output_fd < 0)
16 + die("could not create archive file: %s ", output_file);
17 + if (output_fd != 1) {
18 + if (dup2(output_fd, 1) < 0)
19 + die("could not redirect output");
20 + else
21 + close(output_fd);
22 + }
23 +}
24 +
25 +static int run_remote_archiver(int argc, const char **argv,
26 + const char *remote, const char *exec)
27 {
28 char *url, buf[LARGE_PACKET_MAX];
29 int fd[2], i, len, rv;
30 struct child_process *conn;
17 - const char *exec = "git-upload-archive";
18 - int exec_at = 0, exec_value_at = 0;
19 -
20 - for (i = 1; i < argc; i++) {
21 - const char *arg = argv[i];
22 - if (!prefixcmp(arg, "--exec=")) {
23 - if (exec_at)
24 - die("multiple --exec specified");
25 - exec = arg + 7;
26 - exec_at = i;
27 - } else if (!strcmp(arg, "--exec")) {
28 - if (exec_at)
29 - die("multiple --exec specified");
30 - if (i + 1 >= argc)
31 - die("option --exec requires a value");
32 - exec = argv[i + 1];
33 - exec_at = i;
34 - exec_value_at = ++i;
35 - }
36 - }
31
32 url = xstrdup(remote);
33 conn = git_connect(fd, url, exec, 0);
34
41 - for (i = 1; i < argc; i++) {
42 - if (i == exec_at || i == exec_value_at)
43 - continue;
35 + for (i = 1; i < argc; i++)
36 packet_write(fd[1], "argument %s\n", argv[i]);
45 - }
37 packet_flush(fd[1]);
38
39 len = packet_read_line(fd[0], buf, sizeof(buf));
@@ -69,51 +60,33 @@ static int run_remote_archiver(const char *remote, int argc,
60 return !!rv;
61 }
62
72 -static const char *extract_remote_arg(int *ac, const char **av)
73 -{
74 - int ix, iy, cnt = *ac;
75 - int no_more_options = 0;
76 - const char *remote = NULL;
77 -
78 - for (ix = iy = 1; ix < cnt; ix++) {
79 - const char *arg = av[ix];
80 - if (!strcmp(arg, "--"))
81 - no_more_options = 1;
82 - if (!no_more_options) {
83 - if (!prefixcmp(arg, "--remote=")) {
84 - if (remote)
85 - die("Multiple --remote specified");
86 - remote = arg + 9;
87 - continue;
88 - } else if (!strcmp(arg, "--remote")) {
89 - if (remote)
90 - die("Multiple --remote specified");
91 - if (++ix >= cnt)
92 - die("option --remote requires a value");
93 - remote = av[ix];
94 - continue;
95 - }
96 - if (arg[0] != '-')
97 - no_more_options = 1;
98 - }
99 - if (ix != iy)
100 - av[iy] = arg;
101 - iy++;
102 - }
103 - if (remote) {
104 - av[--cnt] = NULL;
105 - *ac = cnt;
106 - }
107 - return remote;
108 -}
63 +#define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \
64 + PARSE_OPT_KEEP_ARGV0 | \
65 + PARSE_OPT_KEEP_UNKNOWN | \
66 + PARSE_OPT_NO_INTERNAL_HELP )
67
68 int cmd_archive(int argc, const char **argv, const char *prefix)
69 {
70 + const char *exec = "git-upload-archive";
71 + const char *output = NULL;
72 const char *remote = NULL;
73 + struct option local_opts[] = {
74 + OPT_STRING(0, "output", &output, "file",
75 + "write the archive to this file"),
76 + OPT_STRING(0, "remote", &remote, "repo",
77 + "retrieve the archive from remote repository <repo>"),
78 + OPT_STRING(0, "exec", &exec, "cmd",
79 + "path to the remote git-upload-archive command"),
80 + OPT_END()
81 + };
82 +
83 + argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
84 +
85 + if (output)
86 + create_output_file(output);
87
114 - remote = extract_remote_arg(&argc, argv);
88 if (remote)
116 - return run_remote_archiver(remote, argc, argv);
89 + return run_remote_archiver(argc, argv, remote, exec);
90
91 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
92