Skip to content

Commit

Permalink
clone: run check_everything_connected
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Mar 27, 2013
1 parent 0aac7bb commit 0433ad1
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
26 changes: 26 additions & 0 deletions builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "branch.h"
#include "remote.h"
#include "run-command.h"
#include "connected.h"

/*
* Overall FIXMEs:
Expand Down Expand Up @@ -485,12 +486,37 @@ static void write_followtags(const struct ref *refs, const char *msg)
}
}

static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
{
struct ref **rm = cb_data;
struct ref *ref = *rm;

/*
* Skip anything missing a peer_ref, which we are not
* actually going to write a ref for.
*/
while (ref && !ref->peer_ref)
ref = ref->next;
/* Returning -1 notes "end of list" to the caller. */
if (!ref)
return -1;

hashcpy(sha1, ref->old_sha1);
*rm = ref->next;
return 0;
}

static void update_remote_refs(const struct ref *refs,
const struct ref *mapped_refs,
const struct ref *remote_head_points_at,
const char *branch_top,
const char *msg)
{
const struct ref *rm = mapped_refs;

if (check_everything_connected(iterate_ref_map, 0, &rm))
die(_("remote did not send all necessary objects"));

if (refs) {
write_remote_refs(mapped_refs);
if (option_single_branch)
Expand Down
2 changes: 1 addition & 1 deletion t/t1060-object-corruption.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ test_expect_success 'clone --no-local --bare detects missing object' '
test_must_fail git clone --no-local --bare missing missing-transport
'

test_expect_failure 'clone --no-local --bare detects misnamed object' '
test_expect_success 'clone --no-local --bare detects misnamed object' '
test_must_fail git clone --no-local --bare misnamed misnamed-transport
'

Expand Down
8 changes: 1 addition & 7 deletions t/t5710-info-alternate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,7 @@ test_expect_success 'creating too deep nesting' \
git clone -l -s D E &&
git clone -l -s E F &&
git clone -l -s F G &&
git clone --bare -l -s G H'

test_expect_success 'invalidity of deepest repository' \
'cd H && {
test_valid_repo
test $? -ne 0
}'
test_must_fail git clone --bare -l -s G H'

cd "$base_dir"

Expand Down

0 comments on commit 0433ad1

Please sign in to comment.