@matheusbsbs / matheus-bagliano / commits / ed62089c1c
Fork 0

revision traversal and pack: notice and die on missing commit

cc0e6c5 (Handle return code of parse_commit in revision machinery, 2007-05-04) attempted to tighten error checking in the revision machinery, but it wasn't enough. When get_revision_1() was asked for the next commit to return, it tries to read and simplify the parents of the commit to be returned, but an error while doing so was silently ignored and reported as a truncated history to the caller instead. This resulted in an early end of "git log" output or a pack that lacks older commits from "git pack-objects", without any error indication in the exit status from these commands, even though the underlying parse_commit() issues an error message to the end user. Note that the codepath in add_parents_list() that paints parents of an UNINTERESTING commit UNINTERESTING silently ignores the error when parse_commit() fails; this is deliberate and in line with aeeae1b (revision traversal: allow UNINTERESTING objects to be missing, 2009-01-27). Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Feb 11, 2009 at 01:27 UTC ed62089c1c32a9bfca2ec61d331a70443647344c
2 files changed +43 -2
revision.c
+4 -2
@@ -1484,14 +1484,16 @@ static struct commit *get_revision_1(struct rev_info *revs)
1484 (commit->date < revs->max_age))
1485 continue;
1486 if (add_parents_to_list(revs, commit, &revs->commits) < 0)
1487 - return NULL;
1487 + die("Failed to traverse parents of commit %s",
1488 + sha1_to_hex(commit->object.sha1));
1489 }
1490
1491 switch (simplify_commit(revs, commit)) {
1492 case commit_ignore:
1493 continue;
1494 case commit_error:
1494 - return NULL;
1495 + die("Failed to simplify parents of commit %s",
1496 + sha1_to_hex(commit->object.sha1));
1497 default:
1498 return commit;
1499 }
t/t5307-pack-missing-commit.sh new
+39
@@ -0,0 +1,39 @@
1 +#!/bin/sh
2 +
3 +test_description='pack should notice missing commit objects'
4 +
5 +. ./test-lib.sh
6 +
7 +test_expect_success setup '
8 + for i in 1 2 3 4 5
9 + do
10 + echo "$i" >"file$i" &&
11 + git add "file$i" &&
12 + test_tick &&
13 + git commit -m "$i" &&
14 + git tag "tag$i"
15 + done &&
16 + obj=$(git rev-parse --verify tag3) &&
17 + fanout=$(expr "$obj" : "\(..\)") &&
18 + remainder=$(expr "$obj" : "..\(.*\)") &&
19 + rm -f ".git/objects/$fanout/$remainder"
20 +'
21 +
22 +test_expect_success 'check corruption' '
23 + test_must_fail git fsck
24 +'
25 +
26 +test_expect_success 'rev-list notices corruption (1)' '
27 + test_must_fail git rev-list HEAD
28 +'
29 +
30 +test_expect_success 'rev-list notices corruption (2)' '
31 + test_must_fail git rev-list --objects HEAD
32 +'
33 +
34 +test_expect_success 'pack-objects notices corruption' '
35 + echo HEAD |
36 + test_must_fail git pack-objects --revs pack
37 +'
38 +
39 +test_done