clone: run check_everything_connected

When we fetch from a remote, we do a revision walk to make sure that what we received is connected to our existing history. We do not do the same check for clone, which should be able to check that we received an intact history graph. The upside of this patch is that it will make clone more resilient against propagating repository corruption. The downside is that we will now traverse "rev-list --objects --all" down to the roots, which may take some time (it is especially noticeable for a "--local --bare" clone). Note that we need to adjust t5710, which tries to make such a bogus clone. Rather than checking after the fact that our clone is bogus, we can simplify it to just make sure "git clone" reports failure. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Mar 25, 2013 at 16:26 UTC 0433ad128c59f233046b3f8a68246ca3a8a77af8
3 files changed +28 -8
builtin/clone.c
+26
@@ -23,6 +23,7 @@
23 #include "branch.h"
24 #include "remote.h"
25 #include "run-command.h"
26 +#include "connected.h"
27
28 /*
29 * Overall FIXMEs:
@@ -485,12 +486,37 @@ static void write_followtags(const struct ref *refs, const char *msg)
486 }
487 }
488
489 +static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
490 +{
491 + struct ref **rm = cb_data;
492 + struct ref *ref = *rm;
493 +
494 + /*
495 + * Skip anything missing a peer_ref, which we are not
496 + * actually going to write a ref for.
497 + */
498 + while (ref && !ref->peer_ref)
499 + ref = ref->next;
500 + /* Returning -1 notes "end of list" to the caller. */
501 + if (!ref)
502 + return -1;
503 +
504 + hashcpy(sha1, ref->old_sha1);
505 + *rm = ref->next;
506 + return 0;
507 +}
508 +
509 static void update_remote_refs(const struct ref *refs,
510 const struct ref *mapped_refs,
511 const struct ref *remote_head_points_at,
512 const char *branch_top,
513 const char *msg)
514 {
515 + const struct ref *rm = mapped_refs;
516 +
517 + if (check_everything_connected(iterate_ref_map, 0, &rm))
518 + die(_("remote did not send all necessary objects"));
519 +
520 if (refs) {
521 write_remote_refs(mapped_refs);
522 if (option_single_branch)
t/t1060-object-corruption.sh
+1 -1
@@ -79,7 +79,7 @@ test_expect_success 'clone --no-local --bare detects missing object' '
79 test_must_fail git clone --no-local --bare missing missing-transport
80 '
81
82 -test_expect_failure 'clone --no-local --bare detects misnamed object' '
82 +test_expect_success 'clone --no-local --bare detects misnamed object' '
83 test_must_fail git clone --no-local --bare misnamed misnamed-transport
84 '
85
t/t5710-info-alternate.sh
+1 -7
@@ -58,13 +58,7 @@ test_expect_success 'creating too deep nesting' \
58 git clone -l -s D E &&
59 git clone -l -s E F &&
60 git clone -l -s F G &&
61 -git clone --bare -l -s G H'
62 -
63 -test_expect_success 'invalidity of deepest repository' \
64 -'cd H && {
65 - test_valid_repo
66 - test $? -ne 0
67 -}'
61 +test_must_fail git clone --bare -l -s G H'
62
63 cd "$base_dir"
64