X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=builtin-tar-tree.c;h=7663b9bd8e5f10ee45e34752f631d435687cf1b3;hb=5e3a620cd5f7baaf27198192a614271c6145ec3b;hp=6ada04ce3846ec9e973d79cd97e99b9fe84f17db;hpb=56d1398ad305498faf57d6e433f97ad393d7909e;p=git.git diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index 6ada04ce..7663b9bd 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -8,11 +8,13 @@ #include "strbuf.h" #include "tar.h" #include "builtin.h" +#include "pkt-line.h" #define RECORDSIZE (512) #define BLOCKSIZE (RECORDSIZE * 20) -static const char tar_tree_usage[] = "git-tar-tree [basedir]"; +static const char tar_tree_usage[] = +"git-tar-tree [--remote=] [basedir]"; static char block[BLOCKSIZE]; static unsigned long offset; @@ -166,8 +168,9 @@ static int get_path_prefix(const struct strbuf *path, int maxlen) int i = path->len; if (i > maxlen) i = maxlen; - while (i > 0 && path->buf[i] != '/') + do { i--; + } while (i > 0 && path->buf[i] != '/'); return i; } @@ -269,30 +272,25 @@ static void write_global_extended_header(const unsigned char *sha1) static void traverse_tree(struct tree_desc *tree, struct strbuf *path) { int pathlen = path->len; + struct name_entry entry; - while (tree->size) { - const char *name; - const unsigned char *sha1; - unsigned mode; + while (tree_entry(tree, &entry)) { void *eltbuf; char elttype[20]; unsigned long eltsize; - sha1 = tree_entry_extract(tree, &name, &mode); - update_tree_entry(tree); - - eltbuf = read_sha1_file(sha1, elttype, &eltsize); + eltbuf = read_sha1_file(entry.sha1, elttype, &eltsize); if (!eltbuf) - die("cannot read %s", sha1_to_hex(sha1)); + die("cannot read %s", sha1_to_hex(entry.sha1)); path->len = pathlen; - strbuf_append_string(path, name); - if (S_ISDIR(mode)) + strbuf_append_string(path, entry.path); + if (S_ISDIR(entry.mode)) strbuf_append_string(path, "/"); - write_entry(sha1, path, mode, eltbuf, eltsize); + write_entry(entry.sha1, path, entry.mode, eltbuf, eltsize); - if (S_ISDIR(mode)) { + if (S_ISDIR(entry.mode)) { struct tree_desc subtree; subtree.buf = eltbuf; subtree.size = eltsize; @@ -302,7 +300,7 @@ static void traverse_tree(struct tree_desc *tree, struct strbuf *path) } } -int cmd_tar_tree(int argc, const char **argv, char** envp) +static int generate_tar(int argc, const char **argv, char** envp) { unsigned char sha1[20], tree_sha1[20]; struct commit *commit; @@ -349,3 +347,58 @@ int cmd_tar_tree(int argc, const char **argv, char** envp) free(current_path.buf); return 0; } + +static const char *exec = "git-upload-tar"; + +static int remote_tar(int argc, const char **argv) +{ + int fd[2], ret, len; + pid_t pid; + char buf[1024]; + char *url; + + if (argc < 3 || 4 < argc) + usage(tar_tree_usage); + + /* --remote= */ + url = strdup(argv[1]+9); + pid = git_connect(fd, url, exec); + if (pid < 0) + return 1; + + packet_write(fd[1], "want %s\n", argv[2]); + if (argv[3]) + packet_write(fd[1], "base %s\n", argv[3]); + packet_flush(fd[1]); + + len = packet_read_line(fd[0], buf, sizeof(buf)); + if (!len) + die("git-tar-tree: expected ACK/NAK, got EOF"); + if (buf[len-1] == '\n') + buf[--len] = 0; + if (strcmp(buf, "ACK")) { + if (5 < len && !strncmp(buf, "NACK ", 5)) + die("git-tar-tree: NACK %s", buf + 5); + die("git-tar-tree: protocol error"); + } + /* expect a flush */ + len = packet_read_line(fd[0], buf, sizeof(buf)); + if (len) + die("git-tar-tree: expected a flush"); + + /* Now, start reading from fd[0] and spit it out to stdout */ + ret = copy_fd(fd[0], 1); + close(fd[0]); + + ret |= finish_connect(pid); + return !!ret; +} + +int cmd_tar_tree(int argc, const char **argv, char **envp) +{ + if (argc < 2) + usage(tar_tree_usage); + if (!strncmp("--remote=", argv[1], 9)) + return remote_tar(argc, argv); + return generate_tar(argc, argv, envp); +}