diff --git a/builtin-fetch.c b/builtin-fetch.c
index cd5eb9aff530fcb9629bd561bc774e2b9ad69afc..6303aa0f581ace87381fb6a6d425ea8031915c21 100644 (file)
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "..");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
- r = s_update_ref("fast forward", ref, 1);
+ r = s_update_ref("fast-forward", ref, 1);
sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
pretty_ref, r ? " (unable to update local ref)" : "");
r ? "unable to update local ref" : "forced update");
return r;
} else {
- sprintf(display, "! %-*s %-*s -> %s (non fast forward)",
+ sprintf(display, "! %-*s %-*s -> %s (non-fast-forward)",
SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote,
pretty_ref);
return 1;
/*
* We would want to bypass the object transfer altogether if
- * everything we are going to fetch already exists and connected
+ * everything we are going to fetch already exists and is connected
* locally.
*
- * The refs we are going to fetch are in to_fetch (nr_heads in
- * total). If running
+ * The refs we are going to fetch are in ref_map. If running
*
- * $ git rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
+ * $ git rev-list --objects --stdin --not --all
*
+ * (feeding all the refs in ref_map on its standard input)
* does not error out, that means everything reachable from the
* refs we are going to fetch exists and is connected to some of
* our existing refs.
{
struct child_process revlist;
struct ref *ref;
- char **argv;
- int i, err;
+ int err;
+ const char *argv[] = {"rev-list",
+ "--quiet", "--objects", "--stdin", "--not", "--all", NULL};
/*
* If we are deepening a shallow clone we already have these
if (depth)
return -1;
- for (i = 0, ref = ref_map; ref; ref = ref->next)
- i++;
- if (!i)
+ if (!ref_map)
return 0;
- argv = xmalloc(sizeof(*argv) * (i + 6));
- i = 0;
- argv[i++] = xstrdup("rev-list");
- argv[i++] = xstrdup("--quiet");
- argv[i++] = xstrdup("--objects");
- for (ref = ref_map; ref; ref = ref->next)
- argv[i++] = xstrdup(sha1_to_hex(ref->old_sha1));
- argv[i++] = xstrdup("--not");
- argv[i++] = xstrdup("--all");
- argv[i++] = NULL;
-
memset(&revlist, 0, sizeof(revlist));
- revlist.argv = (const char**)argv;
+ revlist.argv = argv;
revlist.git_cmd = 1;
- revlist.no_stdin = 1;
revlist.no_stdout = 1;
revlist.no_stderr = 1;
- err = run_command(&revlist);
+ revlist.in = -1;
+
+ err = start_command(&revlist);
+ if (err) {
+ error("could not run rev-list");
+ return err;
+ }
+
+ /*
+ * If rev-list --stdin encounters an unknown commit, it terminates,
+ * which will cause SIGPIPE in the write loop below.
+ */
+ sigchain_push(SIGPIPE, SIG_IGN);
+
+ for (ref = ref_map; ref; ref = ref->next) {
+ if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 ||
+ write_str_in_full(revlist.in, "\n") < 0) {
+ if (errno != EPIPE && errno != EINVAL)
+ error("failed write to rev-list: %s", strerror(errno));
+ err = -1;
+ break;
+ }
+ }
+
+ if (close(revlist.in)) {
+ error("failed to close rev-list's stdin: %s", strerror(errno));
+ err = -1;
+ }
+
+ sigchain_pop(SIGPIPE);
- for (i = 0; argv[i]; i++)
- free(argv[i]);
- free(argv);
- return err;
+ return finish_command(&revlist) || err;
}
static int fetch_refs(struct transport *transport, struct ref *ref_map)