Re: My git repo is broken, how to fix it ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> writes:

> But to really look at this we should probably add a "really_careful" flag 
> that actually re-verifies the SHA1 on read so that we'd catch these kinds 
> of corruptions early. 
> ...
> I'm hoping somebody has any ideas. We really *could* check the SHA1 on 
> each read (and slow down git a lot) and that would catch corruption much 
> faster and hopefully pinpoint it more quickly where exactly it happens. 

At least, we could do something like this to catch the breakage
when we (re)pack, to prevent damage from propagating.


diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 73d448b..5d0692a 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -65,6 +65,7 @@ static int no_reuse_delta;
 static int local;
 static int incremental;
 static int allow_ofs_delta;
+static int revalidate_sha1;
 
 static struct object_entry **sorted_by_sha, **sorted_by_type;
 static struct object_entry *objects;
@@ -974,8 +975,31 @@ static void add_preferred_base(unsigned char *sha1)
 	it->pcache.tree_size = size;
 }
 
-static void check_object(struct object_entry *entry)
+static void check_object(struct object_entry *entry, int ith, unsigned *last)
 {
+	if (revalidate_sha1) {
+		unsigned char sha1[20];
+		enum object_type type;
+		unsigned long size;
+		void *buf;
+
+		buf = read_sha1_file(entry->sha1, &type, &size);
+		hash_sha1_file(buf, size, typename(type), sha1);
+		if (hashcmp(sha1, entry->sha1))
+			die("'%s': hash mismatch", sha1_to_hex(entry->sha1));
+		free(buf);
+
+		if (progress) {
+			unsigned percent = ith * 100 / nr_objects;
+			if (percent != *last || progress_update) {
+				fprintf(stderr, "%4u%% (%u/%u) done\r",
+					percent, ith, nr_objects);
+				progress_update = 0;
+				*last = percent;
+			}
+		}
+	}
+
 	if (entry->in_pack && !entry->preferred_base) {
 		struct packed_git *p = entry->in_pack;
 		struct pack_window *w_curs = NULL;
@@ -1082,10 +1106,16 @@ static void get_object_details(void)
 {
 	uint32_t i;
 	struct object_entry *entry;
+	unsigned last_percent = 999;
+
+	if (progress && revalidate_sha1)
+		fprintf(stderr, "Revalidating %u objects.\n", nr_objects);
 
 	prepare_pack_ix();
 	for (i = 0, entry = objects; i < nr_objects; i++, entry++)
-		check_object(entry);
+		check_object(entry, i+1, &last_percent);
+	if (progress && revalidate_sha1)
+		fputc('\n', stderr);
 
 	if (nr_objects == nr_result) {
 		/*
@@ -1629,6 +1659,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 			rp_av[1] = "--objects-edge";
 			continue;
 		}
+		if (!strcmp("--revalidate", arg)) {
+			revalidate_sha1 = 1;
+			continue;
+		}
 		usage(pack_usage);
 	}
 


-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]