{"thread":{"id":"5484","subject":"[PATCH 2/2] Add git-upload-archive","startedAt":"2006-09-05T12:22:27Z","lastAt":"2006-09-05T12:22:27Z","messageCount":1,"participants":["Franck Bui-Huu"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"26357","messageId":"cda58cb80609050522o30b9a28n596121a29eb7d482@mail.gmail.com","threadId":"5484","inReplyTo":null,"subject":"[PATCH 2/2] Add git-upload-archive","fromName":"Franck Bui-Huu","fromEmail":"vagabon.xyz@gmail.com","sentAt":"2006-09-05T12:22:27Z","receivedAt":"2006-09-05T12:22:27Z","isPatch":true,"sender":{"key":"vagabon.xyz@gmail.com","avatar":null},"body":"This command implements the git archive protocol on the server\nside. This command is not intended to be used by the end user.\nUnderlying git-archive command line options are sent over the\nprotocol from \"git-archive --remote=...\", just like upload-tar\ncurrently does with \"git-tar-tree=...\".\n\nAs for \"git-archive\" command implementation, this new command\ndoes not execute any existing \"git-{tar,zip}-tree\" but rely\non the archive API defined by \"git-archive\" patch. Hence we\nget 2 good points:\n\n - \"git-archive\" and \"git-upload-archive\" share all option\n   parsing code.\n\n - All kind of git-upload-{tar,zip} could be removed.\n\nSigned-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com>\n---\n .gitignore               |    1\n Makefile                 |    1\n builtin-upload-archive.c |  102 ++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h                |    1\n daemon.c                 |   13 +++++-\n git.c                    |    1\n 6 files changed, 117 insertions(+), 2 deletions(-)\n\ndiff --git a/.gitignore b/.gitignore\nindex a3e7ca1..fda9bf2 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -119,6 +119,7 @@ git-unpack-objects\n git-update-index\n git-update-ref\n git-update-server-info\n+git-upload-archive\n git-upload-pack\n git-upload-tar\n git-var\ndiff --git a/Makefile b/Makefile\nindex 51ed4dd..461e1d6 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -305,6 +305,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-unpack-objects.o \\\n \tbuiltin-update-index.o \\\n \tbuiltin-update-ref.o \\\n+\tbuiltin-upload-archive.o \\\n \tbuiltin-upload-tar.o \\\n \tbuiltin-verify-pack.o \\\n \tbuiltin-write-tree.o \\\ndiff --git a/builtin-upload-archive.c b/builtin-upload-archive.c\nnew file mode 100644\nindex 0000000..5e389fc\n--- /dev/null\n+++ b/builtin-upload-archive.c\n@@ -0,0 +1,102 @@\n+/*\n+ * Copyright (c) 2006 Franck Bui-Huu\n+ */\n+#include <time.h>\n+#include \"cache.h\"\n+#include \"builtin.h\"\n+#include \"archive.h\"\n+#include \"pkt-line.h\"\n+\n+#define MAX_ARGS\t32\n+\n+static const char upload_archive_usage[] =\n+\t\"git-upload-archive --format=fmt <repo>\";\n+\n+static int NACK(const char *reason)\n+{\n+\tpacket_write(1, \"NACK %s\\n\", reason);\n+\tpacket_flush(1);\n+\treturn -1;\n+}\n+\n+int cmd_upload_archive(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct archiver_struct *ar;\n+\tconst char *sent_argv[MAX_ARGS];\n+\tconst char *arg_cmd = \"arguments \";\n+\tconst char *reason;\n+\tchar *p, buf[8192];\n+\tint treeish_idx;\n+\tint sent_argc;\n+\tint len;\n+\tint rv;\n+\n+\tconst char **pathspec;\n+\tstruct tree *tree;\n+\tconst unsigned char *commit_sha1;\n+\ttime_t archive_time;\n+\n+\tif (argc != 3)\n+\t\tusage(upload_archive_usage);\n+\n+\tif (strlen(argv[2]) > sizeof(buf)) {\n+\t\treason = \"insanely long repository name\";\n+\t\tgoto nack;\n+\t}\n+\tstrcpy(buf, argv[2]); /* enter-repo smudges its argument */\n+\n+\tif (!enter_repo(buf, 0)) {\n+\t\treason = \"not a git archive\";\n+\t\tgoto nack;\n+\t}\n+\n+\tlen = packet_read_line(0, buf, sizeof(buf));\n+\tif (len < strlen(arg_cmd) || strncmp(arg_cmd, buf, strlen(arg_cmd))) {\n+\t\treason = \"expected 'arguments' command\";\n+\t\tgoto nack;\n+\t}\n+\tif (buf[len-1] == '\\n')\n+\t\tbuf[--len] = 0;\n+\n+\t/* we can safely override 'arg_cmd' */\n+\tlen = packet_read_line(0, buf, strlen(arg_cmd));\n+\tif (len) {\n+\t\treason = \"flush expected\";\n+\t\tgoto nack;\n+\t}\n+\tp = buf + strlen(arg_cmd);\n+\n+\t/* put received line options in sent_argv[] */\n+\tsent_argv[0] = \"git-upload-archive\";\n+\tsent_argv[1] = argv[1]; /* --format=<fmt> */\n+\tsent_argc = 2;\n+\twhile (p) {\n+\t\tif (sent_argc > MAX_ARGS - 2) {\n+\t\t\treason = \"Too many options (>29)\";\n+\t\t\tgoto nack;\n+\t\t}\n+\t\tsent_argv[sent_argc++] = strsep(&p, \" \");\n+\t}\n+\tsent_argv[sent_argc] = NULL;\n+\n+\t/* parse all options sent by the client */\n+\ttreeish_idx = parse_archive_args(sent_argc, sent_argv, &ar, &reason);\n+\tif (treeish_idx < 0)\n+\t\tgoto nack;\n+\n+\trv = parse_treeish_arg(sent_argv + treeish_idx, &tree, &commit_sha1,\n+\t\t\t       &archive_time, prefix, &reason);\n+\tif (rv < 0)\n+\t\tgoto nack;\n+\n+\tpathspec = get_pathspec(ar->prefix, sent_argv + treeish_idx + 1);\n+\n+\tpacket_write(1, \"ACK\\n\");\n+\tpacket_flush(1);\n+\n+\treturn ar->write_archive(tree, commit_sha1, ar->prefix,\n+\t\t\t\t archive_time, pathspec);\n+nack:\n+\treturn NACK(reason);\n+}\n+\ndiff --git a/builtin.h b/builtin.h\nindex 2391afb..f3efb58 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -58,6 +58,7 @@ extern int cmd_zip_tree(int argc, const\n extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);\n extern int cmd_update_index(int argc, const char **argv, const char *prefix);\n extern int cmd_update_ref(int argc, const char **argv, const char *prefix);\n+extern int cmd_upload_archive(int argc, const char **argv, const char *prefix);\n extern int cmd_upload_tar(int argc, const char **argv, const char *prefix);\n extern int cmd_version(int argc, const char **argv, const char *prefix);\n extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);\ndiff --git a/daemon.c b/daemon.c\nindex a4a08f3..c09280f 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -324,12 +324,21 @@ static int upload_pack(void)\n \treturn -1;\n }\n\n-static int upload_tar(void)\n+static int upload_archive(const char *fmt)\n {\n-\texecl_git_cmd(\"upload-tar\", \".\", NULL);\n+\tchar buf[64];\n+\n+\tsnprintf(buf, sizeof(buf), \"--format=%s\", fmt);\n+\n+\texecl_git_cmd(\"upload-archive\", buf, \".\", NULL);\n \treturn -1;\n }\n\n+static int upload_tar(void)\n+{\n+\treturn upload_archive(\"tar\");\n+}\n+\n static struct daemon_service daemon_service[] = {\n \t{ \"upload-pack\", \"uploadpack\", upload_pack, 1, 1 },\n \t{ \"upload-tar\", \"uploadtar\", upload_tar, 0, 1 },\ndiff --git a/git.c b/git.c\nindex c62c5cf..315dc0b 100644\n--- a/git.c\n+++ b/git.c\n@@ -261,6 +261,7 @@ static void handle_internal_command(int\n \t\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n \t\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n \t\t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n+\t\t{ \"upload-archive\", cmd_upload_archive },\n \t\t{ \"upload-tar\", cmd_upload_tar },\n \t\t{ \"version\", cmd_version },\n \t\t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP | USE_PAGER },\n-- \n1.4.2.gbba4\n"}]}