1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-06-06 11:26:10 +02:00

Merge branch 'ds/fsck-bitmap' into next

"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
This commit is contained in:
Junio C Hamano 2023-05-09 14:56:53 -07:00
commit c2148408a2
4 changed files with 98 additions and 3 deletions

View File

@ -27,6 +27,7 @@
#include "run-command.h"
#include "worktree.h"
#include "pack-revindex.h"
#include "pack-bitmap.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
@ -57,6 +58,7 @@ static int name_objects;
#define ERROR_COMMIT_GRAPH 020
#define ERROR_MULTI_PACK_INDEX 040
#define ERROR_PACK_REV_INDEX 0100
#define ERROR_BITMAP 0200
static const char *describe_object(const struct object_id *oid)
{
@ -867,20 +869,20 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
int res = 0;
if (show_progress) {
for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next)
for (struct packed_git *p = get_all_packs(r); p; p = p->next)
pack_count++;
progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count);
pack_count = 0;
}
for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next) {
for (struct packed_git *p = get_all_packs(r); p; p = p->next) {
int load_error = load_pack_revindex_from_disk(p);
if (load_error < 0) {
error(_("unable to load rev-index for pack '%s'"), p->pack_name);
res = ERROR_PACK_REV_INDEX;
} else if (!load_error &&
!load_pack_revindex(the_repository, p) &&
!load_pack_revindex(r, p) &&
verify_pack_revindex(p)) {
error(_("invalid rev-index for pack '%s'"), p->pack_name);
res = ERROR_PACK_REV_INDEX;
@ -1056,6 +1058,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
errors_found |= check_pack_rev_indexes(the_repository, show_progress);
if (verify_bitmap_files(the_repository))
errors_found |= ERROR_BITMAP;
check_connectivity();

View File

@ -2346,3 +2346,48 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)
return 0;
}
static int verify_bitmap_file(const char *name)
{
struct stat st;
unsigned char *data;
int fd = git_open(name);
int res = 0;
/* It is OK to not have the file. */
if (fd < 0 || fstat(fd, &st)) {
if (fd >= 0)
close(fd);
return 0;
}
data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (!hashfile_checksum_valid(data, st.st_size))
res = error(_("bitmap file '%s' has invalid checksum"),
name);
munmap(data, st.st_size);
return res;
}
int verify_bitmap_files(struct repository *r)
{
int res = 0;
for (struct multi_pack_index *m = get_multi_pack_index(r);
m; m = m->next) {
char *midx_bitmap_name = midx_bitmap_filename(m);
res |= verify_bitmap_file(midx_bitmap_name);
free(midx_bitmap_name);
}
for (struct packed_git *p = get_all_packs(r);
p; p = p->next) {
char *pack_bitmap_name = pack_bitmap_filename(p);
res |= verify_bitmap_file(pack_bitmap_name);
free(pack_bitmap_name);
}
return res;
}

View File

@ -111,4 +111,6 @@ int bitmap_is_midx(struct bitmap_index *bitmap_git);
const struct string_list *bitmap_preferred_tips(struct repository *r);
int bitmap_is_preferred_refname(struct repository *r, const char *refname);
int verify_bitmap_files(struct repository *r);
#endif

View File

@ -434,4 +434,48 @@ test_expect_success 'tagged commits are selected for bitmapping' '
)
'
corrupt_file () {
chmod a+w "$1" &&
printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc
}
test_expect_success 'git fsck correctly identifies good and bad bitmaps' '
git init valid &&
test_when_finished rm -rf valid &&
test_commit_bulk 20 &&
git repack -adbf &&
# Move pack-bitmap aside so it is not deleted
# in next repack.
packbitmap=$(ls .git/objects/pack/pack-*.bitmap) &&
mv "$packbitmap" "$packbitmap.bak" &&
test_commit_bulk 10 &&
git repack -b --write-midx &&
midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) &&
# Copy MIDX bitmap to backup. Copy pack bitmap from backup.
cp "$midxbitmap" "$midxbitmap.bak" &&
cp "$packbitmap.bak" "$packbitmap" &&
# fsck works at first
git fsck 2>err &&
test_must_be_empty err &&
corrupt_file "$packbitmap" &&
test_must_fail git fsck 2>err &&
grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err &&
cp "$packbitmap.bak" "$packbitmap" &&
corrupt_file "$midxbitmap" &&
test_must_fail git fsck 2>err &&
grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
corrupt_file "$packbitmap" &&
test_must_fail git fsck 2>err &&
grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err
'
test_done