4dd2716c0f8cd41425ecc51f85a7dbdd0511c41b
   1/*
   2 * Copyright (c) 2006 Franck Bui-Huu
   3 * Copyright (c) 2006 Rene Scharfe
   4 */
   5#include "cache.h"
   6#include "builtin.h"
   7#include "archive.h"
   8#include "pkt-line.h"
   9#include "sideband.h"
  10
  11static int run_remote_archiver(const char *remote, int argc,
  12                               const char **argv)
  13{
  14        char *url, buf[LARGE_PACKET_MAX];
  15        int fd[2], i, len, rv;
  16        struct child_process *conn;
  17        const char *exec = "git-upload-archive";
  18        int exec_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                        break;
  28                }
  29        }
  30
  31        url = xstrdup(remote);
  32        conn = git_connect(fd, url, exec, 0);
  33
  34        for (i = 1; i < argc; i++) {
  35                if (i == exec_at)
  36                        continue;
  37                packet_write(fd[1], "argument %s\n", argv[i]);
  38        }
  39        packet_flush(fd[1]);
  40
  41        len = packet_read_line(fd[0], buf, sizeof(buf));
  42        if (!len)
  43                die("git-archive: expected ACK/NAK, got EOF");
  44        if (buf[len-1] == '\n')
  45                buf[--len] = 0;
  46        if (strcmp(buf, "ACK")) {
  47                if (len > 5 && !prefixcmp(buf, "NACK "))
  48                        die("git-archive: NACK %s", buf + 5);
  49                die("git-archive: protocol error");
  50        }
  51
  52        len = packet_read_line(fd[0], buf, sizeof(buf));
  53        if (len)
  54                die("git-archive: expected a flush");
  55
  56        /* Now, start reading from fd[0] and spit it out to stdout */
  57        rv = recv_sideband("archive", fd[0], 1, 2);
  58        close(fd[0]);
  59        close(fd[1]);
  60        rv |= finish_connect(conn);
  61
  62        return !!rv;
  63}
  64
  65static const char *extract_remote_arg(int *ac, const char **av)
  66{
  67        int ix, iy, cnt = *ac;
  68        int no_more_options = 0;
  69        const char *remote = NULL;
  70
  71        for (ix = iy = 1; ix < cnt; ix++) {
  72                const char *arg = av[ix];
  73                if (!strcmp(arg, "--"))
  74                        no_more_options = 1;
  75                if (!no_more_options) {
  76                        if (!prefixcmp(arg, "--remote=")) {
  77                                if (remote)
  78                                        die("Multiple --remote specified");
  79                                remote = arg + 9;
  80                                continue;
  81                        }
  82                        if (arg[0] != '-')
  83                                no_more_options = 1;
  84                }
  85                if (ix != iy)
  86                        av[iy] = arg;
  87                iy++;
  88        }
  89        if (remote) {
  90                av[--cnt] = NULL;
  91                *ac = cnt;
  92        }
  93        return remote;
  94}
  95
  96int cmd_archive(int argc, const char **argv, const char *prefix)
  97{
  98        const char *remote = NULL;
  99
 100        remote = extract_remote_arg(&argc, argv);
 101        if (remote)
 102                return run_remote_archiver(remote, argc, argv);
 103
 104        setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 105
 106        return write_archive(argc, argv, prefix, 1);
 107}