mirror of
https://github.com/git/git
synced 2024-08-27 03:29:21 +00:00
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
This commit is contained in:
commit
cd2b740ca9
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue