Merge branch 'jk/upload-pack-keepalive'
[gitweb.git] / upload-pack.c
index fb9be2a93767904a312f50b5403bc7d7441482e8..a6c54e06bb4c4725ace576740912cbb6133e291e 100644 (file)
@@ -10,6 +10,7 @@
 #include "revision.h"
 #include "list-objects.h"
 #include "run-command.h"
+#include "connect.h"
 #include "sigchain.h"
 #include "version.h"
 #include "string-list.h"
@@ -69,87 +70,28 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
        return sz;
 }
 
-static FILE *pack_pipe = NULL;
-static void show_commit(struct commit *commit, void *data)
-{
-       if (commit->object.flags & BOUNDARY)
-               fputc('-', pack_pipe);
-       if (fputs(sha1_to_hex(commit->object.sha1), pack_pipe) < 0)
-               die("broken output pipe");
-       fputc('\n', pack_pipe);
-       fflush(pack_pipe);
-       free(commit->buffer);
-       commit->buffer = NULL;
-}
-
-static void show_object(struct object *obj,
-                       const struct name_path *path, const char *component,
-                       void *cb_data)
-{
-       show_object_with_name(pack_pipe, obj, path, component);
-}
-
-static void show_edge(struct commit *commit)
-{
-       fprintf(pack_pipe, "-%s\n", sha1_to_hex(commit->object.sha1));
-}
-
-static int do_rev_list(int in, int out, void *user_data)
-{
-       int i;
-       struct rev_info revs;
-
-       pack_pipe = xfdopen(out, "w");
-       init_revisions(&revs, NULL);
-       revs.tag_objects = 1;
-       revs.tree_objects = 1;
-       revs.blob_objects = 1;
-       if (use_thin_pack)
-               revs.edge_hint = 1;
-
-       for (i = 0; i < want_obj.nr; i++) {
-               struct object *o = want_obj.objects[i].item;
-               /* why??? */
-               o->flags &= ~UNINTERESTING;
-               add_pending_object(&revs, o, NULL);
-       }
-       for (i = 0; i < have_obj.nr; i++) {
-               struct object *o = have_obj.objects[i].item;
-               o->flags |= UNINTERESTING;
-               add_pending_object(&revs, o, NULL);
-       }
-       setup_revisions(0, NULL, &revs, NULL);
-       if (prepare_revision_walk(&revs))
-               die("revision walk setup failed");
-       mark_edges_uninteresting(revs.commits, &revs, show_edge);
-       if (use_thin_pack)
-               for (i = 0; i < extra_edge_obj.nr; i++)
-                       fprintf(pack_pipe, "-%s\n", sha1_to_hex(
-                                       extra_edge_obj.objects[i].item->sha1));
-       traverse_commit_list(&revs, show_commit, show_object, NULL);
-       fflush(pack_pipe);
-       fclose(pack_pipe);
-       return 0;
-}
-
 static void create_pack_file(void)
 {
-       struct async rev_list;
        struct child_process pack_objects;
        char data[8193], progress[128];
        char abort_msg[] = "aborting due to possible repository "
                "corruption on the remote side.";
        int buffered = -1;
        ssize_t sz;
-       const char *argv[10];
-       int arg = 0;
+       const char *argv[12];
+       int i, arg = 0;
+       FILE *pipe_fd;
+       char *shallow_file = NULL;
 
-       argv[arg++] = "pack-objects";
-       if (!shallow_nr) {
-               argv[arg++] = "--revs";
-               if (use_thin_pack)
-                       argv[arg++] = "--thin";
+       if (shallow_nr) {
+               shallow_file = setup_temporary_shallow();
+               argv[arg++] = "--shallow-file";
+               argv[arg++] = shallow_file;
        }
+       argv[arg++] = "pack-objects";
+       argv[arg++] = "--revs";
+       if (use_thin_pack)
+               argv[arg++] = "--thin";
 
        argv[arg++] = "--stdout";
        if (!no_progress)
@@ -170,29 +112,21 @@ static void create_pack_file(void)
        if (start_command(&pack_objects))
                die("git upload-pack: unable to fork git-pack-objects");
 
-       if (shallow_nr) {
-               memset(&rev_list, 0, sizeof(rev_list));
-               rev_list.proc = do_rev_list;
-               rev_list.out = pack_objects.in;
-               if (start_async(&rev_list))
-                       die("git upload-pack: unable to fork git-rev-list");
-       }
-       else {
-               FILE *pipe_fd = xfdopen(pack_objects.in, "w");
-               int i;
-
-               for (i = 0; i < want_obj.nr; i++)
-                       fprintf(pipe_fd, "%s\n",
-                               sha1_to_hex(want_obj.objects[i].item->sha1));
-               fprintf(pipe_fd, "--not\n");
-               for (i = 0; i < have_obj.nr; i++)
-                       fprintf(pipe_fd, "%s\n",
-                               sha1_to_hex(have_obj.objects[i].item->sha1));
-               fprintf(pipe_fd, "\n");
-               fflush(pipe_fd);
-               fclose(pipe_fd);
-       }
-
+       pipe_fd = xfdopen(pack_objects.in, "w");
+
+       for (i = 0; i < want_obj.nr; i++)
+               fprintf(pipe_fd, "%s\n",
+                       sha1_to_hex(want_obj.objects[i].item->sha1));
+       fprintf(pipe_fd, "--not\n");
+       for (i = 0; i < have_obj.nr; i++)
+               fprintf(pipe_fd, "%s\n",
+                       sha1_to_hex(have_obj.objects[i].item->sha1));
+       for (i = 0; i < extra_edge_obj.nr; i++)
+               fprintf(pipe_fd, "%s\n",
+                       sha1_to_hex(extra_edge_obj.objects[i].item->sha1));
+       fprintf(pipe_fd, "\n");
+       fflush(pipe_fd);
+       fclose(pipe_fd);
 
        /* We read from pack_objects.err to capture stderr output for
         * progress bar, and pack_objects.out to capture the pack data.
@@ -308,8 +242,11 @@ static void create_pack_file(void)
                error("git upload-pack: git-pack-objects died with error.");
                goto fail;
        }
-       if (shallow_nr && finish_async(&rev_list))
-               goto fail;      /* error was already reported */
+       if (shallow_file) {
+               if (*shallow_file)
+                       unlink(shallow_file);
+               free(shallow_file);
+       }
 
        /* flush the data */
        if (0 <= buffered) {
@@ -610,7 +547,7 @@ static void receive_needs(void)
                                die("invalid shallow line: %s", line);
                        object = parse_object(sha1);
                        if (!object)
-                               die("did not find object for %s", line);
+                               continue;
                        if (object->type != OBJ_COMMIT)
                                die("invalid shallow object %s", sha1_to_hex(sha1));
                        if (!(object->flags & CLIENT_SHALLOW)) {