Skip to content

Commit cd2b740

Browse files
committed
Merge branch 'ds/fsck-bitmap'
"git fsck" learned to detect bit-flip breakages in the reachability bitmap files. * ds/fsck-bitmap: fsck: use local repository fsck: verify checksums of all .bitmap files
2 parents 29b8a3f + cf9cd8b commit cd2b740

File tree

4 files changed

+98
-3
lines changed

4 files changed

+98
-3
lines changed

builtin/fsck.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "run-command.h"
2828
#include "worktree.h"
2929
#include "pack-revindex.h"
30+
#include "pack-bitmap.h"
3031

3132
#define REACHABLE 0x0001
3233
#define SEEN 0x0002
@@ -57,6 +58,7 @@ static int name_objects;
5758
#define ERROR_COMMIT_GRAPH 020
5859
#define ERROR_MULTI_PACK_INDEX 040
5960
#define ERROR_PACK_REV_INDEX 0100
61+
#define ERROR_BITMAP 0200
6062

6163
static const char *describe_object(const struct object_id *oid)
6264
{
@@ -867,20 +869,20 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
867869
int res = 0;
868870

869871
if (show_progress) {
870-
for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next)
872+
for (struct packed_git *p = get_all_packs(r); p; p = p->next)
871873
pack_count++;
872874
progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count);
873875
pack_count = 0;
874876
}
875877

876-
for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next) {
878+
for (struct packed_git *p = get_all_packs(r); p; p = p->next) {
877879
int load_error = load_pack_revindex_from_disk(p);
878880

879881
if (load_error < 0) {
880882
error(_("unable to load rev-index for pack '%s'"), p->pack_name);
881883
res = ERROR_PACK_REV_INDEX;
882884
} else if (!load_error &&
883-
!load_pack_revindex(the_repository, p) &&
885+
!load_pack_revindex(r, p) &&
884886
verify_pack_revindex(p)) {
885887
error(_("invalid rev-index for pack '%s'"), p->pack_name);
886888
res = ERROR_PACK_REV_INDEX;
@@ -1056,6 +1058,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
10561058
}
10571059

10581060
errors_found |= check_pack_rev_indexes(the_repository, show_progress);
1061+
if (verify_bitmap_files(the_repository))
1062+
errors_found |= ERROR_BITMAP;
10591063

10601064
check_connectivity();
10611065

pack-bitmap.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,3 +2346,48 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)
23462346

23472347
return 0;
23482348
}
2349+
2350+
static int verify_bitmap_file(const char *name)
2351+
{
2352+
struct stat st;
2353+
unsigned char *data;
2354+
int fd = git_open(name);
2355+
int res = 0;
2356+
2357+
/* It is OK to not have the file. */
2358+
if (fd < 0 || fstat(fd, &st)) {
2359+
if (fd >= 0)
2360+
close(fd);
2361+
return 0;
2362+
}
2363+
2364+
data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
2365+
close(fd);
2366+
if (!hashfile_checksum_valid(data, st.st_size))
2367+
res = error(_("bitmap file '%s' has invalid checksum"),
2368+
name);
2369+
2370+
munmap(data, st.st_size);
2371+
return res;
2372+
}
2373+
2374+
int verify_bitmap_files(struct repository *r)
2375+
{
2376+
int res = 0;
2377+
2378+
for (struct multi_pack_index *m = get_multi_pack_index(r);
2379+
m; m = m->next) {
2380+
char *midx_bitmap_name = midx_bitmap_filename(m);
2381+
res |= verify_bitmap_file(midx_bitmap_name);
2382+
free(midx_bitmap_name);
2383+
}
2384+
2385+
for (struct packed_git *p = get_all_packs(r);
2386+
p; p = p->next) {
2387+
char *pack_bitmap_name = pack_bitmap_filename(p);
2388+
res |= verify_bitmap_file(pack_bitmap_name);
2389+
free(pack_bitmap_name);
2390+
}
2391+
2392+
return res;
2393+
}

pack-bitmap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,6 @@ int bitmap_is_midx(struct bitmap_index *bitmap_git);
111111
const struct string_list *bitmap_preferred_tips(struct repository *r);
112112
int bitmap_is_preferred_refname(struct repository *r, const char *refname);
113113

114+
int verify_bitmap_files(struct repository *r);
115+
114116
#endif

t/t5326-multi-pack-bitmaps.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,4 +434,48 @@ test_expect_success 'tagged commits are selected for bitmapping' '
434434
)
435435
'
436436

437+
corrupt_file () {
438+
chmod a+w "$1" &&
439+
printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc
440+
}
441+
442+
test_expect_success 'git fsck correctly identifies good and bad bitmaps' '
443+
git init valid &&
444+
test_when_finished rm -rf valid &&
445+
446+
test_commit_bulk 20 &&
447+
git repack -adbf &&
448+
449+
# Move pack-bitmap aside so it is not deleted
450+
# in next repack.
451+
packbitmap=$(ls .git/objects/pack/pack-*.bitmap) &&
452+
mv "$packbitmap" "$packbitmap.bak" &&
453+
454+
test_commit_bulk 10 &&
455+
git repack -b --write-midx &&
456+
midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) &&
457+
458+
# Copy MIDX bitmap to backup. Copy pack bitmap from backup.
459+
cp "$midxbitmap" "$midxbitmap.bak" &&
460+
cp "$packbitmap.bak" "$packbitmap" &&
461+
462+
# fsck works at first
463+
git fsck 2>err &&
464+
test_must_be_empty err &&
465+
466+
corrupt_file "$packbitmap" &&
467+
test_must_fail git fsck 2>err &&
468+
grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err &&
469+
470+
cp "$packbitmap.bak" "$packbitmap" &&
471+
corrupt_file "$midxbitmap" &&
472+
test_must_fail git fsck 2>err &&
473+
grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
474+
475+
corrupt_file "$packbitmap" &&
476+
test_must_fail git fsck 2>err &&
477+
grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
478+
grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err
479+
'
480+
437481
test_done

0 commit comments

Comments
 (0)