| /* |
| * Copyright (c) 2006 Franck Bui-Huu |
| * Copyright (c) 2006 Rene Scharfe |
| */ |
| #include "cache.h" |
| #include "builtin.h" |
| #include "archive.h" |
| #include "pkt-line.h" |
| #include "sideband.h" |
| |
| static int run_remote_archiver(const char *remote, int argc, |
| const char **argv) |
| { |
| char *url, buf[LARGE_PACKET_MAX]; |
| int fd[2], i, len, rv; |
| struct child_process *conn; |
| const char *exec = "git-upload-archive"; |
| int exec_at = 0, exec_value_at = 0; |
| |
| for (i = 1; i < argc; i++) { |
| const char *arg = argv[i]; |
| if (!prefixcmp(arg, "--exec=")) { |
| if (exec_at) |
| die("multiple --exec specified"); |
| exec = arg + 7; |
| exec_at = i; |
| } else if (!strcmp(arg, "--exec")) { |
| if (exec_at) |
| die("multiple --exec specified"); |
| if (i + 1 >= argc) |
| die("option --exec requires a value"); |
| exec = argv[i + 1]; |
| exec_at = i; |
| exec_value_at = ++i; |
| } |
| } |
| |
| url = xstrdup(remote); |
| conn = git_connect(fd, url, exec, 0); |
| |
| for (i = 1; i < argc; i++) { |
| if (i == exec_at || i == exec_value_at) |
| continue; |
| packet_write(fd[1], "argument %s\n", argv[i]); |
| } |
| packet_flush(fd[1]); |
| |
| len = packet_read_line(fd[0], buf, sizeof(buf)); |
| if (!len) |
| die("git archive: expected ACK/NAK, got EOF"); |
| if (buf[len-1] == '\n') |
| buf[--len] = 0; |
| if (strcmp(buf, "ACK")) { |
| if (len > 5 && !prefixcmp(buf, "NACK ")) |
| die("git archive: NACK %s", buf + 5); |
| die("git archive: protocol error"); |
| } |
| |
| len = packet_read_line(fd[0], buf, sizeof(buf)); |
| if (len) |
| die("git archive: expected a flush"); |
| |
| /* Now, start reading from fd[0] and spit it out to stdout */ |
| rv = recv_sideband("archive", fd[0], 1, 2); |
| close(fd[0]); |
| close(fd[1]); |
| rv |= finish_connect(conn); |
| |
| return !!rv; |
| } |
| |
| 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 (!prefixcmp(arg, "--remote=")) { |
| if (remote) |
| die("Multiple --remote specified"); |
| remote = arg + 9; |
| continue; |
| } else if (!strcmp(arg, "--remote")) { |
| if (remote) |
| die("Multiple --remote specified"); |
| if (++ix >= cnt) |
| die("option --remote requires a value"); |
| remote = av[ix]; |
| 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) |
| { |
| const char *remote = NULL; |
| |
| remote = extract_remote_arg(&argc, argv); |
| if (remote) |
| return run_remote_archiver(remote, argc, argv); |
| |
| setvbuf(stderr, NULL, _IOLBF, BUFSIZ); |
| |
| return write_archive(argc, argv, prefix, 1); |
| } |