diff --git a/.gitignore b/.gitignore index a3f33d4209..90d6d7c667 100644 --- a/.gitignore +++ b/.gitignore @@ -119,6 +119,7 @@ git-unpack-objects git-update-index git-update-ref git-update-server-info +git-upload-archive git-upload-pack git-upload-tar git-var diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.txt new file mode 100644 index 0000000000..388bb53d29 --- /dev/null +++ b/Documentation/git-upload-archive.txt @@ -0,0 +1,37 @@ +git-upload-archive(1) +==================== + +NAME +---- +git-upload-archive - Send archive + + +SYNOPSIS +-------- +'git-upload-archive' + +DESCRIPTION +----------- +Invoked by 'git-archive --remote' and sends a generated archive to the +other end over the git protocol. + +This command is usually not invoked directly by the end user. The UI +for the protocol is on the 'git-archive' side, and the program pair +is meant to be used to get an archive from a remote repository. + +OPTIONS +------- +:: + The repository to get a tar archive from. + +Author +------ +Written by Franck Bui-Huu. + +Documentation +-------------- +Documentation by Junio C Hamano and the git-list . + +GIT +--- +Part of the gitlink:git[7] suite diff --git a/Makefile b/Makefile index 8f62ceffaf..4ac85fdc7b 100644 --- a/Makefile +++ b/Makefile @@ -293,6 +293,7 @@ BUILTIN_OBJS = \ builtin-unpack-objects.o \ builtin-update-index.o \ builtin-update-ref.o \ + builtin-upload-archive.o \ builtin-upload-tar.o \ builtin-verify-pack.o \ builtin-write-tree.o \ diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c new file mode 100644 index 0000000000..3bdb607e37 --- /dev/null +++ b/builtin-upload-archive.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006 Franck Bui-Huu + */ +#include +#include "cache.h" +#include "builtin.h" +#include "archive.h" +#include "pkt-line.h" + +static const char upload_archive_usage[] = + "git-upload-archive "; + + +int cmd_upload_archive(int argc, const char **argv, const char *prefix) +{ + struct archiver ar; + const char *sent_argv[MAX_ARGS]; + const char *arg_cmd = "argument "; + char *p, buf[4096]; + int treeish_idx; + int sent_argc; + int len; + + if (argc != 2) + usage(upload_archive_usage); + + if (strlen(argv[1]) > sizeof(buf)) + die("insanely long repository name"); + + strcpy(buf, argv[1]); /* enter-repo smudges its argument */ + + if (!enter_repo(buf, 0)) + die("not a git archive"); + + /* put received options in sent_argv[] */ + sent_argc = 1; + sent_argv[0] = "git-upload-archive"; + for (p = buf;;) { + /* This will die if not enough free space in buf */ + len = packet_read_line(0, p, (buf + sizeof buf) - p); + if (len == 0) + break; /* got a flush */ + if (sent_argc > MAX_ARGS - 2) + die("Too many options (>29)"); + + if (p[len-1] == '\n') { + p[--len] = 0; + } + if (len < strlen(arg_cmd) || + strncmp(arg_cmd, p, strlen(arg_cmd))) + die("'argument' token or flush expected"); + + len -= strlen(arg_cmd); + memmove(p, p + strlen(arg_cmd), len); + sent_argv[sent_argc++] = p; + p += len; + *p++ = 0; + } + sent_argv[sent_argc] = NULL; + + /* parse all options sent by the client */ + treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar); + + parse_treeish_arg(sent_argv + treeish_idx, &ar.args, prefix); + parse_pathspec_arg(sent_argv + treeish_idx + 1, &ar.args); + + packet_write(1, "ACK\n"); + packet_flush(1); + + return ar.write_archive(&ar.args); +} + diff --git a/builtin.h b/builtin.h index 50852cd6a9..6bfd2e79f5 100644 --- a/builtin.h +++ b/builtin.h @@ -57,6 +57,7 @@ extern int cmd_zip_tree(int argc, const char **argv, const char *prefix); extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix); extern int cmd_update_index(int argc, const char **argv, const char *prefix); extern int cmd_update_ref(int argc, const char **argv, const char *prefix); +extern int cmd_upload_archive(int argc, const char **argv, const char *prefix); extern int cmd_upload_tar(int argc, const char **argv, const char *prefix); extern int cmd_version(int argc, const char **argv, const char *prefix); extern int cmd_whatchanged(int argc, const char **argv, const char *prefix); diff --git a/daemon.c b/daemon.c index b14d8083bb..a2954a0451 100644 --- a/daemon.c +++ b/daemon.c @@ -325,7 +325,14 @@ static int upload_pack(void) return -1; } +static int upload_archive(void) +{ + execl_git_cmd("upload-archive", ".", NULL); + return -1; +} + static struct daemon_service daemon_service[] = { + { "upload-archive", "uploadarch", upload_archive, 0, 1 }, { "upload-pack", "uploadpack", upload_pack, 1, 1 }, }; diff --git a/git.c b/git.c index 8c64b2753f..bcf3fc8444 100644 --- a/git.c +++ b/git.c @@ -262,6 +262,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "unpack-objects", cmd_unpack_objects, RUN_SETUP }, { "update-index", cmd_update_index, RUN_SETUP }, { "update-ref", cmd_update_ref, RUN_SETUP }, + { "upload-archive", cmd_upload_archive }, { "upload-tar", cmd_upload_tar }, { "version", cmd_version }, { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },