400
401
/*
402
* We would want to bypass the object transfer altogether if
403
- * everything we are going to fetch already exists and connected
403
+ * everything we are going to fetch already exists and is connected
404
* locally.
405
*
406
- * The refs we are going to fetch are in to_fetch (nr_heads in
407
- * total). If running
406
+ * The refs we are going to fetch are in ref_map. If running
407
*
409
- * $ git rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
408
+ * $ git rev-list --objects --stdin --not --all
409
*
410
+ * (feeding all the refs in ref_map on its standard input)
411
* does not error out, that means everything reachable from the
412
* refs we are going to fetch exists and is connected to some of
413
* our existing refs.
416
{
417
struct child_process revlist;
418
struct ref *ref;
419
- char **argv;
420
- int i, err;
419
+ int err;
420
+ const char *argv[] = {"rev-list",
421
+ "--quiet", "--objects", "--stdin", "--not", "--all", NULL};
422
423
/*
424
* If we are deepening a shallow clone we already have these
430
if (depth)
431
return -1;
432
432
- for (i = 0, ref = ref_map; ref; ref = ref->next)
433
- i++;
434
- if (!i)
433
+ if (!ref_map)
434
return 0;
435
437
- argv = xmalloc(sizeof(*argv) * (i + 6));
438
- i = 0;
439
- argv[i++] = xstrdup("rev-list");
440
- argv[i++] = xstrdup("--quiet");
441
- argv[i++] = xstrdup("--objects");
442
- for (ref = ref_map; ref; ref = ref->next)
443
- argv[i++] = xstrdup(sha1_to_hex(ref->old_sha1));
444
- argv[i++] = xstrdup("--not");
445
- argv[i++] = xstrdup("--all");
446
- argv[i++] = NULL;
447
-
436
memset(&revlist, 0, sizeof(revlist));
449
- revlist.argv = (const char**)argv;
437
+ revlist.argv = argv;
438
revlist.git_cmd = 1;
451
- revlist.no_stdin = 1;
439
revlist.no_stdout = 1;
440
revlist.no_stderr = 1;
454
- err = run_command(&revlist);
441
+ revlist.in = -1;
442
+
443
+ err = start_command(&revlist);
444
+ if (err) {
445
+ error("could not run rev-list");
446
+ return err;
447
+ }
448
+
449
+ /*
450
+ * If rev-list --stdin encounters an unknown commit, it terminates,
451
+ * which will cause SIGPIPE in the write loop below.
452
+ */
453
+ sigchain_push(SIGPIPE, SIG_IGN);
454
+
455
+ for (ref = ref_map; ref; ref = ref->next) {
456
+ if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 ||
457
+ write_in_full(revlist.in, "\n", 1) < 0) {
458
+ if (errno != EPIPE && errno != EINVAL)
459
+ error("failed write to rev-list: %s", strerror(errno));
460
+ err = -1;
461
+ break;
462
+ }
463
+ }
464
+
465
+ if (close(revlist.in)) {
466
+ error("failed to close rev-list's stdin: %s", strerror(errno));
467
+ err = -1;
468
+ }
469
+
470
+ sigchain_pop(SIGPIPE);
471
456
- for (i = 0; argv[i]; i++)
457
- free(argv[i]);
458
- free(argv);
459
- return err;
472
+ return finish_command(&revlist) || err;
473
}
474
475
static int fetch_refs(struct transport *transport, struct ref *ref_map)