The upload-file command allows a remote to request specific files by sha1.

Signed-off-by: Mark Thomas <mar...@efaref.net>
---
 .gitignore    |  1 +
 Makefile      |  2 ++
 daemon.c      |  6 +++++
 upload-file.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 96 insertions(+)
 create mode 100644 upload-file.c

diff --git a/.gitignore b/.gitignore
index 833ef3b..c2db9c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -165,6 +165,7 @@
 /git-update-ref
 /git-update-server-info
 /git-upload-archive
+/git-upload-file
 /git-upload-pack
 /git-var
 /git-verify-commit
diff --git a/Makefile b/Makefile
index 9ec6065..1b84322 100644
--- a/Makefile
+++ b/Makefile
@@ -597,6 +597,7 @@ PROGRAM_OBJS += sh-i18n--envsubst.o
 PROGRAM_OBJS += shell.o
 PROGRAM_OBJS += show-index.o
 PROGRAM_OBJS += upload-pack.o
+PROGRAM_OBJS += upload-file.o
 PROGRAM_OBJS += remote-testsvn.o
 
 # Binary suffix, set to .exe for Windows builds
@@ -668,6 +669,7 @@ BINDIR_PROGRAMS_NEED_X += git-upload-pack
 BINDIR_PROGRAMS_NEED_X += git-receive-pack
 BINDIR_PROGRAMS_NEED_X += git-upload-archive
 BINDIR_PROGRAMS_NEED_X += git-shell
+BINDIR_PROGRAMS_NEED_X += git-upload-file
 
 BINDIR_PROGRAMS_NO_X += git-cvsserver
 
diff --git a/daemon.c b/daemon.c
index 473e6b6..8b5b026 100644
--- a/daemon.c
+++ b/daemon.c
@@ -479,6 +479,11 @@ static int upload_pack(void)
        return run_service_command(argv);
 }
 
+static int upload_file(void)
+{
+       const char *argv[] = { "upload-file", ".", NULL };
+       return run_service_command(argv);
+}
 static int upload_archive(void)
 {
        static const char *argv[] = { "upload-archive", ".", NULL };
@@ -494,6 +499,7 @@ static int receive_pack(void)
 static struct daemon_service daemon_service[] = {
        { "upload-archive", "uploadarch", upload_archive, 0, 1 },
        { "upload-pack", "uploadpack", upload_pack, 1, 1 },
+       { "upload-file", "uploadfile", upload_file, 1, 1 },
        { "receive-pack", "receivepack", receive_pack, 0, 1 },
 };
 
diff --git a/upload-file.c b/upload-file.c
new file mode 100644
index 0000000..cb2bfe8
--- /dev/null
+++ b/upload-file.c
@@ -0,0 +1,87 @@
+
+#include "cache.h"
+#include "exec_cmd.h"
+#include "parse-options.h"
+#include "pkt-line.h"
+
+static const char * const upload_file_usage[] = {
+       N_("git upload-file [<options>] <dir>"),
+       NULL
+};
+
+
+static void upload_file(void)
+{
+       for (;;) {
+               char *line = packet_read_line(0, NULL);
+               const char *arg;
+               if (!line)
+                       break;
+
+               if (skip_prefix(line, "info ", &arg)) {
+                       unsigned char sha1[20];
+                       void *buffer;
+                       enum object_type type;
+                       unsigned long size;
+
+                       if (get_sha1_hex(arg, sha1))
+                               die("invalid sha: %s", arg);
+
+                       buffer = read_sha1_file(sha1, &type, &size);
+                       if (buffer) {
+                               packet_write_fmt(1, "found %s %d %ld\n", 
sha1_to_hex(sha1), type, size);
+                               free(buffer);
+                       } else {
+                               packet_write_fmt(1, "missing %s\n", 
sha1_to_hex(sha1));
+                       }
+               }
+
+               if (skip_prefix(line, "get ", &arg)) {
+                       unsigned char sha1[20];
+                       void *buffer;
+                       enum object_type type;
+                       unsigned long size;
+
+                       if (get_sha1_hex(arg, sha1))
+                               die("invalid sha: %s", arg);
+
+                       buffer = read_sha1_file(sha1, &type, &size);
+                       if (buffer) {
+                               packet_write_fmt(1, "found %s %d %ld\n", 
sha1_to_hex(sha1), type, size);
+                               write_or_die(1, buffer, size);
+                               free(buffer);
+                       } else {
+                               packet_write_fmt(1, "missing %s\n", 
sha1_to_hex(sha1));
+                       }
+                       
+               }
+
+               if (!strcmp(line, "end"))
+                       break;
+       }
+}
+
+int cmd_main(int argc, const char **argv)
+{
+       const char *dir;
+       struct option options[] = {
+               OPT_END()
+       };
+
+       packet_trace_identity("upload-file");
+
+       argc = parse_options(argc, argv, NULL, options, upload_file_usage, 0);
+
+       if (argc != 1)
+               usage_with_options(upload_file_usage, options);
+
+       setup_path();
+
+       dir = argv[0];
+
+       if (!enter_repo(dir, 0))
+               die("'%s' does not appear to be a git repository", dir);
+
+       upload_file();
+       return 0;
+}
-- 
2.7.4

Reply via email to