Skip to content

Commit 52e7787

Browse files
René Scharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 49b6180 commit 52e7787

File tree

2 files changed

+40
-81
lines changed

2 files changed

+40
-81
lines changed

archive.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -239,19 +239,6 @@ static void parse_treeish_arg(const char **argv,
239239
ar_args->time = archive_time;
240240
}
241241

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-
255242
#define OPT__COMPR(s, v, h, p) \
256243
{ OPTION_SET_INT, (s), NULL, (v), NULL, (h), \
257244
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, (p) }
@@ -306,13 +293,12 @@ static int parse_archive_args(int argc, const char **argv,
306293
die("Unexpected option --remote");
307294
if (exec)
308295
die("Option --exec can only be used together with --remote");
296+
if (output)
297+
die("Unexpected option --output");
309298

310299
if (!base)
311300
base = "";
312301

313-
if (output)
314-
create_output_file(output);
315-
316302
if (list) {
317303
for (i = 0; i < ARRAY_SIZE(archivers); i++)
318304
printf("%s\n", archivers[i].name);

builtin-archive.c

Lines changed: 38 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,35 @@
55
#include "cache.h"
66
#include "builtin.h"
77
#include "archive.h"
8+
#include "parse-options.h"
89
#include "pkt-line.h"
910
#include "sideband.h"
1011

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)
1327
{
1428
char *url, buf[LARGE_PACKET_MAX];
1529
int fd[2], i, len, rv;
1630
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-
}
3731

3832
url = xstrdup(remote);
3933
conn = git_connect(fd, url, exec, 0);
4034

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++)
4436
packet_write(fd[1], "argument %s\n", argv[i]);
45-
}
4637
packet_flush(fd[1]);
4738

4839
len = packet_read_line(fd[0], buf, sizeof(buf));
@@ -69,51 +60,33 @@ static int run_remote_archiver(const char *remote, int argc,
6960
return !!rv;
7061
}
7162

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 )
10967

11068
int cmd_archive(int argc, const char **argv, const char *prefix)
11169
{
70+
const char *exec = "git-upload-archive";
71+
const char *output = NULL;
11272
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);
11387

114-
remote = extract_remote_arg(&argc, argv);
11588
if (remote)
116-
return run_remote_archiver(remote, argc, argv);
89+
return run_remote_archiver(argc, argv, remote, exec);
11790

11891
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
11992

0 commit comments

Comments
 (0)