Skip to content

Commit 14e7b83

Browse files
ttaylorrgitster
authored andcommitted
builtin/pack-objects.c: ignore missing links with --stdin-packs
When 'git pack-objects --stdin-packs' encounters a commit in a pack, it marks it as a starting point of a best-effort reachability traversal that is used to populate the name-hash of the objects listed in the given packs. The traversal expects that it should be able to walk the ancestors of all commits in a pack without issue. Ordinarily this is the case, but it is possible to having missing parents from an unreachable part of the repository. In that case, we'd consider any missing objects in the unreachable portion of the graph to be junk. This should be handled gracefully: since the traversal is best-effort (i.e., we don't strictly need to fill in all of the name-hash fields), we should simply ignore any missing links. This patch does that (by setting the 'ignore_missing_links' bit on the rev_info struct), and ensures we don't regress in the future by adding a test which demonstrates this case. It is a little over-eager, since it will also ignore missing links in reachable parts of the packs (which would indicate a corrupted repository), but '--stdin-packs' is explicitly *not* about reachability. So this step isn't making anything worse for a repository which contains packs missing reachable objects (since we never drop objects with '--stdin-packs'). Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ccae01c commit 14e7b83

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

builtin/pack-objects.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3122,6 +3122,7 @@ static void read_packs_list_from_stdin(void)
31223122
revs.blob_objects = 1;
31233123
revs.tree_objects = 1;
31243124
revs.tag_objects = 1;
3125+
revs.ignore_missing_links = 1;
31253126

31263127
while (strbuf_getline(&buf, stdin) != EOF) {
31273128
if (!buf.len)

t/t5300-pack-object.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,4 +629,42 @@ test_expect_success '--stdin-packs with loose objects' '
629629
)
630630
'
631631

632+
test_expect_success '--stdin-packs with broken links' '
633+
(
634+
cd stdin-packs &&
635+
636+
# make an unreachable object with a bogus parent
637+
git cat-file -p HEAD >commit &&
638+
sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
639+
git hash-object -w -t commit --stdin >in &&
640+
641+
git pack-objects .git/objects/pack/pack-D <in &&
642+
643+
PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
644+
PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
645+
PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
646+
PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
647+
648+
git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
649+
$PACK_A
650+
^$PACK_B
651+
$PACK_C
652+
$PACK_D
653+
EOF
654+
655+
(
656+
git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
657+
git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
658+
git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
659+
git rev-list --objects --no-object-names \
660+
refs/tags/C..refs/tags/D
661+
) >expect.raw &&
662+
git show-index <$(ls test3-*.idx) >actual.raw &&
663+
664+
cut -d" " -f2 <expect.raw | sort >expect &&
665+
cut -d" " -f2 <actual.raw | sort >actual &&
666+
test_cmp expect actual
667+
)
668+
'
669+
632670
test_done

0 commit comments

Comments
 (0)