From: Junio C Hamano Date: Thu, 1 Nov 2007 20:47:47 +0000 (-0700) Subject: Merge branch 'js/forkexec' X-Git-Tag: v1.5.4-rc0~292 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/4340a813d007b592534de664d152d66417dbe809?hp=-c Merge branch 'js/forkexec' * js/forkexec: Use the asyncronous function infrastructure to run the content filter. Avoid a dup2(2) in apply_filter() - start_command() can do it for us. t0021-conversion.sh: Test that the clean filter really cleans content. upload-pack: Run rev-list in an asynchronous function. upload-pack: Move the revision walker into a separate function. Use the asyncronous function infrastructure in builtin-fetch-pack.c. Add infrastructure to run a function asynchronously. upload-pack: Use start_command() to run pack-objects in create_pack_file(). Have start_command() create a pipe to read the stderr of the child. Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. Use run_command() to spawn external diff programs instead of fork/exec. Use start_command() to run content filters instead of explicit fork/exec. Use start_command() in git_connect() instead of explicit fork/exec. Change git_connect() to return a struct child_process instead of a pid_t. Conflicts: builtin-fetch-pack.c --- 4340a813d007b592534de664d152d66417dbe809 diff --combined builtin-archive.c index 6f29c2f40a,76f8d3d83d..14a1b3077c --- a/builtin-archive.c +++ b/builtin-archive.c @@@ -30,7 -30,7 +30,7 @@@ static int run_remote_archiver(const ch { char *url, buf[LARGE_PACKET_MAX]; int fd[2], i, len, rv; - pid_t pid; + struct child_process *conn; const char *exec = "git-upload-archive"; int exec_at = 0; @@@ -46,9 -46,7 +46,7 @@@ } url = xstrdup(remote); - pid = git_connect(fd, url, exec, 0); - if (pid < 0) - return pid; + conn = git_connect(fd, url, exec, 0); for (i = 1; i < argc; i++) { if (i == exec_at) @@@ -76,7 -74,7 +74,7 @@@ rv = recv_sideband("archive", fd[0], 1, 2); close(fd[0]); close(fd[1]); - rv |= finish_connect(pid); + rv |= finish_connect(conn); return !!rv; } @@@ -148,14 -146,12 +146,14 @@@ void *sha1_file_to_archive(const char * buffer = read_sha1_file(sha1, type, sizep); if (buffer && S_ISREG(mode)) { struct strbuf buf; + size_t size = 0; strbuf_init(&buf, 0); strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); convert_to_archive(path, buf.buf, buf.len, &buf, commit); - buffer = strbuf_detach(&buf, sizep); + buffer = strbuf_detach(&buf, &size); + *sizep = size; } return buffer; diff --combined builtin-fetch-pack.c index 8753840a82,51d8a32791..862652be92 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@@ -7,16 -7,16 +7,17 @@@ #include "pack.h" #include "sideband.h" #include "fetch-pack.h" + #include "run-command.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; static int unpack_limit = 100; -static struct fetch_pack_args args; +static struct fetch_pack_args args = { + /* .uploadpack = */ "git-upload-pack", +}; static const char fetch_pack_usage[] = "git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=] [--depth=] [--no-progress] [-v] [:] [...]"; -static const char *uploadpack = "git-upload-pack"; #define COMPLETE (1U << 0) #define COMMON (1U << 1) @@@ -457,53 -457,49 +458,49 @@@ static int everything_local(struct ref return retval; } - static pid_t setup_sideband(int fd[2], int xd[2]) + static int sideband_demux(int fd, void *data) { - pid_t side_pid; + int *xd = data; + close(xd[1]); + return recv_sideband("fetch-pack", xd[0], fd, 2); + } + + static void setup_sideband(int fd[2], int xd[2], struct async *demux) + { if (!use_sideband) { fd[0] = xd[0]; fd[1] = xd[1]; - return 0; + return; } /* xd[] is talking with upload-pack; subprocess reads from * xd[0], spits out band#2 to stderr, and feeds us band#1 - * through our fd[0]. + * through demux->out. */ - if (pipe(fd) < 0) - die("fetch-pack: unable to set up pipe"); - side_pid = fork(); - if (side_pid < 0) + demux->proc = sideband_demux; + demux->data = xd; + if (start_async(demux)) die("fetch-pack: unable to fork off sideband demultiplexer"); - if (!side_pid) { - /* subprocess */ - close(fd[0]); - if (xd[0] != xd[1]) - close(xd[1]); - if (recv_sideband("fetch-pack", xd[0], fd[1], 2)) - exit(1); - exit(0); - } close(xd[0]); - close(fd[1]); + fd[0] = demux->out; fd[1] = xd[1]; - return side_pid; } static int get_pack(int xd[2], char **pack_lockfile) { - int status; - pid_t pid, side_pid; + struct async demux; int fd[2]; const char *argv[20]; char keep_arg[256]; char hdr_arg[256]; const char **av; int do_keep = args.keep_pack; - int keep_pipe[2]; + struct child_process cmd; - side_pid = setup_sideband(fd, xd); + setup_sideband(fd, xd, &demux); + memset(&cmd, 0, sizeof(cmd)); + cmd.argv = argv; av = argv; *hdr_arg = 0; if (!args.keep_pack && unpack_limit) { @@@ -520,8 -516,8 +517,8 @@@ } if (do_keep) { - if (pack_lockfile && pipe(keep_pipe)) - die("fetch-pack: pipe setup failure: %s", strerror(errno)); + if (pack_lockfile) + cmd.out = -1; *av++ = "index-pack"; *av++ = "--stdin"; if (!args.quiet && !args.no_progress) @@@ -545,43 -541,19 +542,19 @@@ *av++ = hdr_arg; *av++ = NULL; - pid = fork(); - if (pid < 0) + cmd.in = fd[0]; + cmd.git_cmd = 1; + if (start_command(&cmd)) die("fetch-pack: unable to fork off %s", argv[0]); - if (!pid) { - dup2(fd[0], 0); - if (do_keep && pack_lockfile) { - dup2(keep_pipe[1], 1); - close(keep_pipe[0]); - close(keep_pipe[1]); - } - close(fd[0]); - close(fd[1]); - execv_git_cmd(argv); - die("%s exec failed", argv[0]); - } - close(fd[0]); close(fd[1]); - if (do_keep && pack_lockfile) { - close(keep_pipe[1]); - *pack_lockfile = index_pack_lockfile(keep_pipe[0]); - close(keep_pipe[0]); - } - while (waitpid(pid, &status, 0) < 0) { - if (errno != EINTR) - die("waiting for %s: %s", argv[0], strerror(errno)); - } - if (WIFEXITED(status)) { - int code = WEXITSTATUS(status); - if (code) - die("%s died with error code %d", argv[0], code); - return 0; - } - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - die("%s died of signal %d", argv[0], sig); - } - die("%s died of unnatural causes %d", argv[0], status); + if (do_keep && pack_lockfile) + *pack_lockfile = index_pack_lockfile(cmd.out); + + if (finish_command(&cmd)) + die("%s failed", argv[0]); + if (use_sideband && finish_async(&demux)) + die("error in sideband demultiplexer"); + return 0; } static struct ref *do_fetch_pack(int fd[2], @@@ -763,7 -735,7 +736,7 @@@ struct ref *fetch_pack(struct fetch_pac { int i, ret; int fd[2]; - pid_t pid; + struct child_process *conn; struct ref *ref; struct stat st; @@@ -774,16 -746,14 +747,14 @@@ st.st_mtime = 0; } - pid = git_connect(fd, (char *)dest, args.uploadpack, - conn = git_connect(fd, (char *)dest, uploadpack, ++ conn = git_connect(fd, (char *)dest, args.uploadpack, args.verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return NULL; if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile); close(fd[0]); close(fd[1]); - ret = finish_connect(pid); + ret = finish_connect(conn); if (!ret && nr_heads) { /* If the heads to pull were given, we should have diff --combined diff.c index af85b94d1b,30b7544171..a6aaaf7e5a --- a/diff.c +++ b/diff.c @@@ -9,6 -9,7 +9,7 @@@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" + #include "run-command.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@@ -1440,18 -1441,9 +1441,18 @@@ struct diff_filespec *alloc_filespec(co memset(spec, 0, sizeof(*spec)); spec->path = (char *)(spec + 1); memcpy(spec->path, path, namelen+1); + spec->count = 1; return spec; } +void free_filespec(struct diff_filespec *spec) +{ + if (!--spec->count) { + diff_free_filespec_data(spec); + free(spec); + } +} + void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, unsigned short mode) { @@@ -1521,7 -1513,6 +1522,7 @@@ static int reuse_worktree_file(const ch static int populate_from_stdin(struct diff_filespec *s) { struct strbuf buf; + size_t size = 0; strbuf_init(&buf, 0); if (strbuf_read(&buf, 0, 0) < 0) @@@ -1529,8 -1520,7 +1530,8 @@@ strerror(errno)); s->should_munmap = 0; - s->data = strbuf_detach(&buf, &s->size); + s->data = strbuf_detach(&buf, &size); + s->size = size; s->should_free = 1; return 0; } @@@ -1620,11 -1610,9 +1621,11 @@@ int diff_populate_filespec(struct diff_ */ strbuf_init(&buf, 0); if (convert_to_git(s->path, s->data, s->size, &buf)) { + size_t size = 0; munmap(s->data, s->size); s->should_munmap = 0; - s->data = strbuf_detach(&buf, &s->size); + s->data = strbuf_detach(&buf, &size); + s->size = size; s->should_free = 1; } } @@@ -1761,40 -1749,6 +1762,6 @@@ static void remove_tempfile_on_signal(i raise(signo); } - static int spawn_prog(const char *pgm, const char **arg) - { - pid_t pid; - int status; - - fflush(NULL); - pid = fork(); - if (pid < 0) - die("unable to fork"); - if (!pid) { - execvp(pgm, (char *const*) arg); - exit(255); - } - - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - return -1; - } - - /* Earlier we did not check the exit status because - * diff exits non-zero if files are different, and - * we are not interested in knowing that. It was a - * mistake which made it harder to quit a diff-* - * session that uses the git-apply-patch-script as - * the GIT_EXTERNAL_DIFF. A custom GIT_EXTERNAL_DIFF - * should also exit non-zero only when it wants to - * abort the entire diff-* session. - */ - if (WIFEXITED(status) && !WEXITSTATUS(status)) - return 0; - return -1; - } - /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@@ -1847,7 -1801,8 +1814,8 @@@ static void run_external_diff(const cha *arg++ = name; } *arg = NULL; - retval = spawn_prog(pgm, spawn_arg); + fflush(NULL); + retval = run_command_v_opt(spawn_arg, 0); remove_tempfile(); if (retval) { fprintf(stderr, "external diff died, stopping at %s.\n", name); @@@ -2444,8 -2399,10 +2412,8 @@@ struct diff_filepair *diff_queue(struc void diff_free_filepair(struct diff_filepair *p) { - diff_free_filespec_data(p->one); - diff_free_filespec_data(p->two); - free(p->one); - free(p->two); + free_filespec(p->one); + free_filespec(p->two); free(p); } @@@ -2597,9 -2554,9 +2565,9 @@@ void diff_debug_filepair(const struct d { diff_debug_filespec(p->one, i, "one"); diff_debug_filespec(p->two, i, "two"); - fprintf(stderr, "score %d, status %c stays %d broken %d\n", + fprintf(stderr, "score %d, status %c rename_used %d broken %d\n", p->score, p->status ? p->status : '?', - p->source_stays, p->broken_pair); + p->one->rename_used, p->broken_pair); } void diff_debug_queue(const char *msg, struct diff_queue_struct *q) @@@ -2617,8 -2574,8 +2585,8 @@@ static void diff_resolve_rename_copy(void) { - int i, j; - struct diff_filepair *p, *pp; + int i; + struct diff_filepair *p; struct diff_queue_struct *q = &diff_queued_diff; diff_debug_queue("resolve-rename-copy", q); @@@ -2640,21 -2597,27 +2608,21 @@@ * either in-place edit or rename/copy edit. */ else if (DIFF_PAIR_RENAME(p)) { - if (p->source_stays) { - p->status = DIFF_STATUS_COPIED; - continue; - } - /* See if there is some other filepair that - * copies from the same source as us. If so - * we are a copy. Otherwise we are either a - * copy if the path stays, or a rename if it - * does not, but we already handled "stays" case. + /* + * A rename might have re-connected a broken + * pair up, causing the pathnames to be the + * same again. If so, that's not a rename at + * all, just a modification.. + * + * Otherwise, see if this source was used for + * multiple renames, in which case we decrement + * the count, and call it a copy. */ - for (j = i + 1; j < q->nr; j++) { - pp = q->queue[j]; - if (strcmp(pp->one->path, p->one->path)) - continue; /* not us */ - if (!DIFF_PAIR_RENAME(pp)) - continue; /* not a rename/copy */ - /* pp is a rename/copy from the same source */ + if (!strcmp(p->one->path, p->two->path)) + p->status = DIFF_STATUS_MODIFIED; + else if (--p->one->rename_used > 0) p->status = DIFF_STATUS_COPIED; - break; - } - if (!p->status) + else p->status = DIFF_STATUS_RENAMED; } else if (hashcmp(p->one->sha1, p->two->sha1) || diff --combined send-pack.c index 25053d2c2f,147f44b01d..5e127a1b7b --- a/send-pack.c +++ b/send-pack.c @@@ -178,35 -178,6 +178,35 @@@ static int receive_status(int in return ret; } +static void update_tracking_ref(struct remote *remote, struct ref *ref) +{ + struct refspec rs; + int will_delete_ref; + + rs.src = ref->name; + rs.dst = NULL; + + if (!ref->peer_ref) + return; + + will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1); + + if (!will_delete_ref && + !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) + return; + + if (!remote_find_tracking(remote, &rs)) { + fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); + if (is_null_sha1(ref->peer_ref->new_sha1)) { + if (delete_ref(rs.dst, NULL)) + error("Failed to delete"); + } else + update_ref("update by push", rs.dst, + ref->new_sha1, NULL, 0, 0); + free(rs.dst); + } +} + static int send_pack(int in, int out, struct remote *remote, int nr_refspec, char **refspec) { struct ref *ref; @@@ -234,8 -205,7 +234,8 @@@ return -1; if (!remote_refs) { - fprintf(stderr, "No refs in common and none specified; doing nothing.\n"); + fprintf(stderr, "No refs in common and none specified; doing nothing.\n" + "Perhaps you should specify a branch such as 'master'.\n"); return 0; } @@@ -335,6 -305,22 +335,6 @@@ fprintf(stderr, "\n from %s\n to %s\n", old_hex, new_hex); } - if (remote && !dry_run) { - struct refspec rs; - rs.src = ref->name; - rs.dst = NULL; - if (!remote_find_tracking(remote, &rs)) { - fprintf(stderr, " Also local %s\n", rs.dst); - if (will_delete_ref) { - if (delete_ref(rs.dst, NULL)) { - error("Failed to delete"); - } - } else - update_ref("update by push", rs.dst, - ref->new_sha1, NULL, 0, 0); - free(rs.dst); - } - } } packet_flush(out); @@@ -347,11 -333,6 +347,11 @@@ ret = -4; } + if (!dry_run && remote && ret == 0) { + for (ref = remote_refs; ref; ref = ref->next) + update_tracking_ref(remote, ref); + } + if (!new_refs && ret == 0) fprintf(stderr, "Everything up-to-date\n"); return ret; @@@ -384,7 -365,7 +384,7 @@@ int main(int argc, char **argv char *dest = NULL; char **heads = NULL; int fd[2], ret; - pid_t pid; + struct child_process *conn; char *remote_name = NULL; struct remote *remote = NULL; @@@ -452,12 -433,10 +452,10 @@@ } } - pid = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return 1; + conn = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); ret = send_pack(fd[0], fd[1], remote, nr_heads, heads); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(conn); return !!ret; }