object name: introduce ':/<oneline prefix>' notation
[gitweb.git] / builtin-archive.c
index 7544ad3ca1a69b7bd0a9026e03405003d002cf43..8ea6cb1efc4f988fb09051852f9e51fc88b5efd7 100644 (file)
@@ -2,7 +2,6 @@
  * Copyright (c) 2006 Franck Bui-Huu
  * Copyright (c) 2006 Rene Scharfe
  */
-#include <time.h>
 #include "cache.h"
 #include "builtin.h"
 #include "archive.h"
 #include "tree-walk.h"
 #include "exec_cmd.h"
 #include "pkt-line.h"
+#include "sideband.h"
 
 static const char archive_usage[] = \
 "git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
 
-struct archiver archivers[] = {
-       {
-               .name           = "tar",
-               .write_archive  = write_tar_archive,
-       },
-       {
-               .name           = "zip",
-               .write_archive  = write_zip_archive,
-               .parse_extra    = parse_extra_zip_args,
-       },
+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(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 (!prefixcmp(arg, "--exec=")) {
+                       if (exec_at)
+                               die("multiple --exec specified");
+                       exec = arg + 7;
+                       exec_at = i;
+                       break;
+               }
+       }
 
        url = xstrdup(remote);
-       pid = git_connect(fd, url, buf);
+       pid = git_connect(fd, url, exec);
        if (pid < 0)
                return pid;
 
-       for (i = 1; i < argc; i++)
+       for (i = 1; i < argc; i++) {
+               if (i == exec_at)
+                       continue;
                packet_write(fd[1], "argument %s\n", argv[i]);
+       }
        packet_flush(fd[1]);
 
        len = packet_read_line(fd[0], buf, sizeof(buf));
@@ -50,7 +62,7 @@ static int run_remote_archiver(const char *remote, int argc,
        if (buf[len-1] == '\n')
                buf[--len] = 0;
        if (strcmp(buf, "ACK")) {
-               if (len > 5 && !strncmp(buf, "NACK ", 5))
+               if (len > 5 && !prefixcmp(buf, "NACK "))
                        die("git-archive: NACK %s", buf + 5);
                die("git-archive: protocol error");
        }
@@ -60,9 +72,9 @@ static int run_remote_archiver(const char *remote, 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]);
+       close(fd[1]);
        rv |= finish_connect(pid);
 
        return !!rv;
@@ -74,7 +86,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;
                }
@@ -123,7 +138,6 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
                if (err || !S_ISDIR(mode))
                        die("current working directory is untracked");
 
-               free(tree);
                tree = parse_tree_indirect(tree_sha1);
        }
        ar_args->tree = tree;
@@ -131,17 +145,6 @@ 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];
@@ -163,11 +166,11 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar)
                        verbose = 1;
                        continue;
                }
-               if (!strncmp(arg, "--format=", 9)) {
+               if (!prefixcmp(arg, "--format=")) {
                        format = arg + 9;
                        continue;
                }
-               if (!strncmp(arg, "--prefix=", 9)) {
+               if (!prefixcmp(arg, "--prefix=")) {
                        base = arg + 9;
                        continue;
                }
@@ -194,7 +197,8 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar)
 
        if (extra_argc) {
                if (!ar->parse_extra)
-                       die("%s", default_parse_extra(ar, extra_argv));
+                       die("'%s' format does not handle %s",
+                           ar->name, extra_argv[0]);
                ar->args.extra = ar->parse_extra(extra_argc, extra_argv);
        }
        ar->args.verbose = verbose;
@@ -203,7 +207,7 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar)
        return i;
 }
 
-static const char *remote_request(int *ac, const char **av)
+static const char *extract_remote_arg(int *ac, const char **av)
 {
        int ix, iy, cnt = *ac;
        int no_more_options = 0;
@@ -214,7 +218,7 @@ static const char *remote_request(int *ac, const char **av)
                if (!strcmp(arg, "--"))
                        no_more_options = 1;
                if (!no_more_options) {
-                       if (!strncmp(arg, "--remote=", 9)) {
+                       if (!prefixcmp(arg, "--remote=")) {
                                if (remote)
                                        die("Multiple --remote specified");
                                remote = arg + 9;
@@ -240,11 +244,11 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
        int tree_idx;
        const char *remote = NULL;
 
-       remote = remote_request(&argc, argv);
+       remote = extract_remote_arg(&argc, argv);
        if (remote)
                return run_remote_archiver(remote, argc, argv);
 
-       setlinebuf(stderr);
+       setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
        memset(&ar, 0, sizeof(ar));
        tree_idx = parse_archive_args(argc, argv, &ar);