X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=builtin-archive.c;h=391cf43911a16ec49862c18b7dd4f1f094d49de8;hb=43853554542700e0d129ce853a3d4b16740035d4;hp=c6423b9c48b4d84269343e30c790d5c82dc9cd83;hpb=efd8696cd7ccfa5042ef710e89fe0d10efdcd085;p=git.git diff --git a/builtin-archive.c b/builtin-archive.c index c6423b9c4..391cf4391 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -2,7 +2,6 @@ * Copyright (c) 2006 Franck Bui-Huu * Copyright (c) 2006 Rene Scharfe */ -#include #include "cache.h" #include "builtin.h" #include "archive.h" @@ -10,30 +9,48 @@ #include "tree-walk.h" #include "exec_cmd.h" #include "pkt-line.h" +#include "sideband.h" static const char archive_usage[] = \ -"git-archive --format= [--prefix=/] [] [path...]"; +"git-archive --format= [--prefix=/] [--verbose] [] [path...]"; -struct archiver archivers[] = { - { .name = "tar", .write_archive = write_tar_archive }, +static struct archiver_desc +{ + const char *name; + write_archive_fn_t write_archive; + parse_extra_args_fn_t parse_extra; +} archivers[] = { + { "tar", write_tar_archive, NULL }, + { "zip", write_zip_archive, parse_extra_zip_args }, }; -static int run_remote_archiver(struct archiver *ar, int argc, +static int run_remote_archiver(const char *remote, int argc, const char **argv) { - char *url, buf[1024]; + char *url, buf[LARGE_PACKET_MAX]; int fd[2], i, len, rv; pid_t pid; + const char *exec = "git-upload-archive"; + int exec_at = 0; - sprintf(buf, "git-upload-archive"); + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (!strncmp("--exec=", arg, 7)) { + if (exec_at) + die("multiple --exec specified"); + exec = arg + 7; + exec_at = i; + break; + } + } - url = xstrdup(ar->remote); - pid = git_connect(fd, url, buf); + url = xstrdup(remote); + pid = git_connect(fd, url, exec); if (pid < 0) return pid; for (i = 1; i < argc; i++) { - if (!strncmp(argv[i], "--remote=", 9)) + if (i == exec_at) continue; packet_write(fd[1], "argument %s\n", argv[i]); } @@ -55,8 +72,7 @@ static int run_remote_archiver(struct archiver *ar, int argc, die("git-archive: expected a flush"); /* Now, start reading from fd[0] and spit it out to stdout */ - rv = copy_fd(fd[0], 1); - + rv = recv_sideband("archive", fd[0], 1, 2); close(fd[0]); rv |= finish_connect(pid); @@ -69,7 +85,10 @@ static int init_archiver(const char *name, struct archiver *ar) for (i = 0; i < ARRAY_SIZE(archivers); i++) { if (!strcmp(name, archivers[i].name)) { - memcpy(ar, &archivers[i], sizeof(struct archiver)); + memset(ar, 0, sizeof(*ar)); + ar->name = archivers[i].name; + ar->write_archive = archivers[i].write_archive; + ar->parse_extra = archivers[i].parse_extra; rv = 0; break; } @@ -126,32 +145,25 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args, ar_args->time = archive_time; } -static const char *default_parse_extra(struct archiver *ar, - const char **argv) -{ - static char msg[64]; - - snprintf(msg, sizeof(msg) - 4, "'%s' format does not handle %s", - ar->name, *argv); - - return strcat(msg, "..."); -} - int parse_archive_args(int argc, const char **argv, struct archiver *ar) { const char *extra_argv[MAX_EXTRA_ARGS]; int extra_argc = 0; const char *format = NULL; /* might want to default to "tar" */ - const char *remote = NULL; const char *base = ""; - int list = 0; + int verbose = 0; int i; for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) { - list = 1; + for (i = 0; i < ARRAY_SIZE(archivers); i++) + printf("%s\n", archivers[i].name); + exit(0); + } + if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) { + verbose = 1; continue; } if (!strncmp(arg, "--format=", 9)) { @@ -162,10 +174,6 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar) base = arg + 9; continue; } - if (!strncmp(arg, "--remote=", 9)) { - remote = arg + 9; - continue; - } if (!strcmp(arg, "--")) { i++; break; @@ -179,44 +187,71 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar) break; } - if (list) { - if (!remote) { - for (i = 0; i < ARRAY_SIZE(archivers); i++) - printf("%s\n", archivers[i].name); - exit(0); - } - die("--list and --remote are mutually exclusive"); - } - - if (argc - i < 1) + /* We need at least one parameter -- tree-ish */ + if (argc - 1 < i) usage(archive_usage); if (!format) die("You must specify an archive format"); if (init_archiver(format, ar) < 0) die("Unknown archive format '%s'", format); - if (extra_argc && !remote) { - if (!ar->parse_extra) { - die("%s", default_parse_extra(ar, extra_argv)); - } + if (extra_argc) { + if (!ar->parse_extra) + die("'%s' format does not handle %s", + ar->name, extra_argv[0]); ar->args.extra = ar->parse_extra(extra_argc, extra_argv); } - ar->remote = remote; + ar->args.verbose = verbose; ar->args.base = base; return i; } +static const char *extract_remote_arg(int *ac, const char **av) +{ + int ix, iy, cnt = *ac; + int no_more_options = 0; + const char *remote = NULL; + + for (ix = iy = 1; ix < cnt; ix++) { + const char *arg = av[ix]; + if (!strcmp(arg, "--")) + no_more_options = 1; + if (!no_more_options) { + if (!strncmp(arg, "--remote=", 9)) { + if (remote) + die("Multiple --remote specified"); + remote = arg + 9; + continue; + } + if (arg[0] != '-') + no_more_options = 1; + } + if (ix != iy) + av[iy] = arg; + iy++; + } + if (remote) { + av[--cnt] = NULL; + *ac = cnt; + } + return remote; +} + int cmd_archive(int argc, const char **argv, const char *prefix) { struct archiver ar; int tree_idx; + const char *remote = NULL; - tree_idx = parse_archive_args(argc, argv, &ar); + remote = extract_remote_arg(&argc, argv); + if (remote) + return run_remote_archiver(remote, argc, argv); - if (ar.remote) - return run_remote_archiver(&ar, argc, argv); + setvbuf(stderr, NULL, _IOLBF, BUFSIZ); + memset(&ar, 0, sizeof(ar)); + tree_idx = parse_archive_args(argc, argv, &ar); if (prefix == NULL) prefix = setup_git_directory();