summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--builtin-tar-tree.c61
-rw-r--r--builtin-upload-tar.c74
-rw-r--r--builtin.h4
-rw-r--r--git.c2
5 files changed, 143 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index fc5f98b..14873fa 100644
--- a/Makefile
+++ b/Makefile
@@ -170,9 +170,10 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X \
git-count-objects$X git-diff$X git-push$X \
git-grep$X git-rev-list$X git-check-ref-format$X \
git-init-db$X git-ls-files$X git-ls-tree$X \
- git-tar-tree$X git-read-tree$X git-commit-tree$X \
+ git-read-tree$X git-commit-tree$X \
git-apply$X git-show-branch$X git-diff-files$X \
- git-diff-index$X git-diff-stages$X git-diff-tree$X
+ git-diff-index$X git-diff-stages$X git-diff-tree$X \
+ git-tar-tree$X git-upload-tar$X
# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@@ -222,9 +223,10 @@ BUILTIN_OBJS = \
builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
builtin-grep.o builtin-rev-list.o builtin-check-ref-format.o \
builtin-init-db.o builtin-ls-files.o builtin-ls-tree.o \
- builtin-tar-tree.o builtin-read-tree.o builtin-commit-tree.o \
+ builtin-read-tree.o builtin-commit-tree.o \
builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
- builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o
+ builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
+ builtin-tar-tree.o builtin-upload-tar.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index 6ada04c..2d5e06f 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 <key> [basedir]";
+static const char tar_tree_usage[] =
+"git-tar-tree [--remote=<repo>] <ent> [basedir]";
static char block[BLOCKSIZE];
static unsigned long offset;
@@ -302,7 +304,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 +351,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=<repo> */
+ 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);
+}
diff --git a/builtin-upload-tar.c b/builtin-upload-tar.c
new file mode 100644
index 0000000..d4fa7b5
--- /dev/null
+++ b/builtin-upload-tar.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2006 Junio C Hamano
+ */
+#include "cache.h"
+#include "pkt-line.h"
+#include "exec_cmd.h"
+#include "builtin.h"
+
+static const char upload_tar_usage[] = "git-upload-tar <repo>";
+
+static int nak(const char *reason)
+{
+ packet_write(1, "NACK %s\n", reason);
+ packet_flush(1);
+ return 1;
+}
+
+int cmd_upload_tar(int argc, const char **argv, char **envp)
+{
+ int len;
+ const char *dir = argv[1];
+ char buf[8192];
+ unsigned char sha1[20];
+ char *base = NULL;
+ char hex[41];
+ int ac;
+ const char *av[4];
+
+ if (argc != 2)
+ usage(upload_tar_usage);
+ if (strlen(dir) < sizeof(buf)-1)
+ strcpy(buf, dir); /* enter-repo smudges its argument */
+ else
+ packet_write(1, "NACK insanely long repository name %s\n", dir);
+ if (!enter_repo(buf, 0)) {
+ packet_write(1, "NACK not a git archive %s\n", dir);
+ packet_flush(1);
+ return 1;
+ }
+
+ len = packet_read_line(0, buf, sizeof(buf));
+ if (len < 5 || strncmp("want ", buf, 5))
+ return nak("expected want");
+ if (buf[len-1] == '\n')
+ buf[--len] = 0;
+ if (get_sha1(buf + 5, sha1))
+ return nak("expected sha1");
+ strcpy(hex, sha1_to_hex(sha1));
+
+ len = packet_read_line(0, buf, sizeof(buf));
+ if (len) {
+ if (len < 5 || strncmp("base ", buf, 5))
+ return nak("expected (optional) base");
+ if (buf[len-1] == '\n')
+ buf[--len] = 0;
+ base = strdup(buf + 5);
+ len = packet_read_line(0, buf, sizeof(buf));
+ }
+ if (len)
+ return nak("expected flush");
+
+ packet_write(1, "ACK\n");
+ packet_flush(1);
+
+ ac = 0;
+ av[ac++] = "tar-tree";
+ av[ac++] = hex;
+ if (base)
+ av[ac++] = base;
+ av[ac++] = NULL;
+ execv_git_cmd(av);
+ /* should it return that is an error */
+ return 1;
+}
diff --git a/builtin.h b/builtin.h
index 7620984..2249c5f 100644
--- a/builtin.h
+++ b/builtin.h
@@ -27,9 +27,10 @@ extern int cmd_grep(int argc, const char **argv, char **envp);
extern int cmd_rev_list(int argc, const char **argv, char **envp);
extern int cmd_check_ref_format(int argc, const char **argv, char **envp);
extern int cmd_init_db(int argc, const char **argv, char **envp);
+extern int cmd_tar_tree(int argc, const char **argv, char **envp);
+extern int cmd_upload_tar(int argc, const char **argv, char **envp);
extern int cmd_ls_files(int argc, const char **argv, char **envp);
extern int cmd_ls_tree(int argc, const char **argv, char **envp);
-extern int cmd_tar_tree(int argc, const char **argv, char **envp);
extern int cmd_read_tree(int argc, const char **argv, char **envp);
extern int cmd_commit_tree(int argc, const char **argv, char **envp);
extern int cmd_apply(int argc, const char **argv, char **envp);
@@ -39,5 +40,4 @@ extern int cmd_diff_index(int argc, const char **argv, char **envp);
extern int cmd_diff_stages(int argc, const char **argv, char **envp);
extern int cmd_diff_tree(int argc, const char **argv, char **envp);
-
#endif
diff --git a/git.c b/git.c
index 8749748..38e8461 100644
--- a/git.c
+++ b/git.c
@@ -52,6 +52,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "grep", cmd_grep },
{ "rev-list", cmd_rev_list },
{ "init-db", cmd_init_db },
+ { "tar-tree", cmd_tar_tree },
+ { "upload-tar", cmd_upload_tar },
{ "check-ref-format", cmd_check_ref_format },
{ "ls-files", cmd_ls_files },
{ "ls-tree", cmd_ls_tree },