Lazily open pack index files on demand
[gitweb.git] / send-pack.c
index 512b660e99f26e391df34d48e1aebc9c6c3250e7..83ee87dcf82d1720c1c39ae377b4c7a595c5a059 100644 (file)
@@ -3,7 +3,7 @@
 #include "tag.h"
 #include "refs.h"
 #include "pkt-line.h"
-#include "exec_cmd.h"
+#include "run-command.h"
 
 static const char send_pack_usage[] =
 "git-send-pack [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
@@ -19,46 +19,35 @@ static int use_thin_pack;
  */
 static int pack_objects(int fd, struct ref *refs)
 {
-       int pipe_fd[2];
-       pid_t pid;
-
-       if (pipe(pipe_fd) < 0)
-               return error("send-pack: pipe failed");
-       pid = fork();
-       if (pid < 0)
-               return error("send-pack: unable to fork git-pack-objects");
-       if (!pid) {
-               /*
-                * The child becomes pack-objects --revs; we feed
-                * the revision parameters to it via its stdin and
-                * let its stdout go back to the other end.
-                */
-               static const char *args[] = {
-                       "pack-objects",
-                       "--all-progress",
-                       "--revs",
-                       "--stdout",
-                       NULL,
-                       NULL,
-               };
-               if (use_thin_pack)
-                       args[4] = "--thin";
-               dup2(pipe_fd[0], 0);
-               dup2(fd, 1);
-               close(pipe_fd[0]);
-               close(pipe_fd[1]);
-               close(fd);
-               execv_git_cmd(args);
-               die("git-pack-objects exec failed (%s)", strerror(errno));
-       }
+       /*
+        * The child becomes pack-objects --revs; we feed
+        * the revision parameters to it via its stdin and
+        * let its stdout go back to the other end.
+        */
+       const char *args[] = {
+               "pack-objects",
+               "--all-progress",
+               "--revs",
+               "--stdout",
+               NULL,
+               NULL,
+       };
+       struct child_process po;
+
+       if (use_thin_pack)
+               args[4] = "--thin";
+       memset(&po, 0, sizeof(po));
+       po.argv = args;
+       po.in = -1;
+       po.out = fd;
+       po.git_cmd = 1;
+       if (start_command(&po))
+               die("git-pack-objects failed (%s)", strerror(errno));
 
        /*
         * We feed the pack-objects we just spawned with revision
         * parameters by writing to the pipe.
         */
-       close(pipe_fd[0]);
-       close(fd);
-
        while (refs) {
                char buf[42];
 
@@ -67,38 +56,23 @@ static int pack_objects(int fd, struct ref *refs)
                        memcpy(buf + 1, sha1_to_hex(refs->old_sha1), 40);
                        buf[0] = '^';
                        buf[41] = '\n';
-                       if (!write_or_whine(pipe_fd[1], buf, 42,
+                       if (!write_or_whine(po.in, buf, 42,
                                                "send-pack: send refs"))
                                break;
                }
                if (!is_null_sha1(refs->new_sha1)) {
                        memcpy(buf, sha1_to_hex(refs->new_sha1), 40);
                        buf[40] = '\n';
-                       if (!write_or_whine(pipe_fd[1], buf, 41,
+                       if (!write_or_whine(po.in, buf, 41,
                                                "send-pack: send refs"))
                                break;
                }
                refs = refs->next;
        }
-       close(pipe_fd[1]);
-
-       for (;;) {
-               int status, code;
-               pid_t waiting = waitpid(pid, &status, 0);
 
-               if (waiting < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       return error("waitpid failed (%s)", strerror(errno));
-               }
-               if ((waiting != pid) || WIFSIGNALED(status) ||
-                   !WIFEXITED(status))
-                       return error("pack-objects died with strange error");
-               code = WEXITSTATUS(status);
-               if (code)
-                       return -code;
-               return 0;
-       }
+       if (finish_command(&po))
+               return error("pack-objects died with strange error");
+       return 0;
 }
 
 static void unmark_and_free(struct commit_list *list, unsigned int mark)
@@ -419,7 +393,7 @@ int main(int argc, char **argv)
                usage(send_pack_usage);
        verify_remote_names(nr_heads, heads);
 
-       pid = git_connect(fd, dest, receivepack);
+       pid = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0);
        if (pid < 0)
                return 1;
        ret = send_pack(fd[0], fd[1], nr_heads, heads);