X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=send-pack.c;h=d5b51628dfbcc44b22b5069df19eeac67dda1e57;hb=95655d79ad13697e0d68e986d3b0b402efad007a;hp=29cf73681f3caf0b91b0d7d11cafbfcd6c4bf8d0;hpb=4b4ee90e587779233488325d2832a946eebe03e0;p=git.git diff --git a/send-pack.c b/send-pack.c index 29cf73681..d5b51628d 100644 --- a/send-pack.c +++ b/send-pack.c @@ -3,111 +3,51 @@ #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] [--exec=git-receive-pack] [...]\n" -" --all and explicit specification are mutually exclusive."; -static const char *exec = "git-receive-pack"; +"git-send-pack [--all] [--force] [--receive-pack=] [--verbose] [--thin] [:] [...]\n" +" --all and explicit specification are mutually exclusive."; +static const char *receivepack = "git-receive-pack"; static int verbose; static int send_all; static int force_update; static int use_thin_pack; -static void exec_pack_objects(void) +/* + * Make a pack stream and spit it out into file descriptor fd + */ +static int pack_objects(int fd, struct ref *refs) { - static const char *args[] = { + /* + * 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, + NULL, }; - execv_git_cmd(args); - die("git-pack-objects exec failed (%s)", strerror(errno)); -} - -static void exec_rev_list(struct ref *refs) -{ - static const char *args[4]; - int i = 0; - - args[i++] = "rev-list"; /* 0 */ - if (use_thin_pack) /* 1 */ - args[i++] = "--objects-edge"; - else - args[i++] = "--objects"; - - args[i++] = "--stdin"; - - args[i] = NULL; - execv_git_cmd(args); - die("git-rev-list exec failed (%s)", strerror(errno)); -} - -/* - * Run "rev-list --stdin | pack-objects" pipe. - */ -static void rev_list(struct ref *refs) -{ - int pipe_fd[2]; - pid_t pack_objects_pid; - - if (pipe(pipe_fd) < 0) - die("rev-list setup: pipe failed"); - pack_objects_pid = fork(); - if (!pack_objects_pid) { - /* The child becomes pack-objects; reads from pipe - * and writes to the original fd - */ - dup2(pipe_fd[0], 0); - close(pipe_fd[0]); - close(pipe_fd[1]); - exec_pack_objects(); - die("pack-objects setup failed"); - } - if (pack_objects_pid < 0) - die("pack-objects fork failed"); - - /* We become rev-list --stdin; output goes to pipe. */ - dup2(pipe_fd[1], 1); - close(pipe_fd[0]); - close(pipe_fd[1]); - exec_rev_list(refs); -} + 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)); -/* - * Create "rev-list --stdin | pack-objects" pipe and feed - * the refs into the pipeline. - */ -static void rev_list_generate(int fd, struct ref *refs) -{ - int pipe_fd[2]; - pid_t rev_list_generate_pid; - - if (pipe(pipe_fd) < 0) - die("rev-list-generate setup: pipe failed"); - rev_list_generate_pid = fork(); - if (!rev_list_generate_pid) { - /* The child becomes the "rev-list | pack-objects" - * pipeline. It takes input from us, and its output - * goes to fd. - */ - dup2(pipe_fd[0], 0); - dup2(fd, 1); - close(pipe_fd[0]); - close(pipe_fd[1]); - close(fd); - rev_list(refs); - die("rev-list setup failed"); - } - if (rev_list_generate_pid < 0) - die("rev-list-generate fork failed"); - - /* We feed the rev parameters to them. We do not write into - * fd nor read from the pipe. + /* + * 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]; @@ -116,38 +56,23 @@ static void rev_list_generate(int fd, struct ref *refs) memcpy(buf + 1, sha1_to_hex(refs->old_sha1), 40); buf[0] = '^'; buf[41] = '\n'; - write(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'; - write(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]); - // waitpid(rev_list_generate_pid); - exit(0); -} -/* - * Make a pack stream and spit it out into file descriptor fd - */ -static void pack_objects(int fd, struct ref *refs) -{ - pid_t rev_list_pid; - - rev_list_pid = fork(); - if (!rev_list_pid) { - rev_list_generate(fd, refs); - die("rev-list setup failed"); - } - if (rev_list_pid < 0) - die("rev-list fork failed"); - /* - * We don't wait for the rev-list pipeline in the parent: - * we end up waiting for the other end instead - */ + 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) @@ -379,7 +304,7 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec) packet_flush(out); if (new_refs) - pack_objects(out, remote_refs); + ret = pack_objects(out, remote_refs); close(out); if (expect_status_report) { @@ -428,8 +353,12 @@ int main(int argc, char **argv) char *arg = *argv; if (*arg == '-') { - if (!strncmp(arg, "--exec=", 7)) { - exec = arg + 7; + if (!prefixcmp(arg, "--receive-pack=")) { + receivepack = arg + 15; + continue; + } + if (!prefixcmp(arg, "--exec=")) { + receivepack = arg + 7; continue; } if (!strcmp(arg, "--all")) { @@ -464,7 +393,7 @@ int main(int argc, char **argv) usage(send_pack_usage); verify_remote_names(nr_heads, heads); - pid = git_connect(fd, dest, exec); + pid = git_connect(fd, dest, receivepack); if (pid < 0) return 1; ret = send_pack(fd[0], fd[1], nr_heads, heads);