{"thread":{"id":"5468","subject":"[PATCH] unpack-objects --desperate","startedAt":"2006-09-04T06:05:54Z","lastAt":"2006-09-04T06:05:54Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"26285","messageId":"7vveo4p3nh.fsf@assigned-by-dhcp.cox.net","threadId":"5468","inReplyTo":null,"subject":"[PATCH] unpack-objects --desperate","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-09-04T06:05:54Z","receivedAt":"2006-09-04T06:05:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The command unpack-objects dies upon the first error.  This is\nprobably considered a feature -- if a pack is corrupt, instead\nof trying to extract from it and possibly risking to contaminate\na good repository with objects whose validity is dubious, we\nshould seek a good copy of the pack and retry.  However, we may\nnot have any good copy anywhere.  This implements the last\nresort effort to extract what are salvageable from such a\ncorrupt pack.\n\nThis flag might have helped Sergio when recovering from a\ncorrupt pack.  In my test, it managed to salvage 247 objects out\nof a pack that had 251 objects but without it the command\nstopped after extracting 73 objects.\n\n---\n\n* A new flag I do not know what to call so I used -r for\n  \"recover\" but used the word \"salvage\" when describing it in\n  the documentation and the variable used for this option is\n  called \"desperate\".  Obviously I am not good at naming things.\n\n  Only lightly tested.\n\ndiff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt\nindex c20b38b..415c09b 100644\n--- a/Documentation/git-unpack-objects.txt\n+++ b/Documentation/git-unpack-objects.txt\n@@ -8,7 +8,7 @@ git-unpack-objects - Unpack objects from\n \n SYNOPSIS\n --------\n-'git-unpack-objects' [-n] [-q] <pack-file\n+'git-unpack-objects' [-n] [-q] [-r] <pack-file\n \n \n DESCRIPTION\n@@ -34,6 +34,12 @@ OPTIONS\n \tThe command usually shows percentage progress.  This\n \tflag suppresses it.\n \n+-r::\n+\tWhen unpacking a corrupt packfile, the command dies at\n+\tthe first corruption.  This flag tells it to keep going\n+\tand make the best effort to salvage as many objects as\n+\tpossible.\n+\n \n Author\n ------\ndiff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c\nindex 0c180b5..5f9c0d2 100644\n--- a/builtin-unpack-objects.c\n+++ b/builtin-unpack-objects.c\n@@ -10,7 +10,7 @@ #include \"tree.h\"\n \n #include <sys/time.h>\n \n-static int dry_run, quiet;\n+static int dry_run, quiet, desperate, has_errors;\n static const char unpack_usage[] = \"git-unpack-objects [-n] [-q] < pack-file\";\n \n /* We always read in 4kB chunks. */\n@@ -71,8 +71,15 @@ static void *get_data(unsigned long size\n \t\tuse(len - stream.avail_in);\n \t\tif (stream.total_out == size && ret == Z_STREAM_END)\n \t\t\tbreak;\n-\t\tif (ret != Z_OK)\n-\t\t\tdie(\"inflate returned %d\\n\", ret);\n+\t\tif (ret != Z_OK) {\n+\t\t\terror(\"inflate returned %d\\n\", ret);\n+\t\t\tfree(buf);\n+\t\t\tbuf = NULL;\n+\t\t\tif (!desperate)\n+\t\t\t\texit(1);\n+\t\t\thas_errors = 1;\n+\t\t\tbreak;\n+\t\t}\n \t\tstream.next_in = fill(1);\n \t\tstream.avail_in = len;\n \t}\n@@ -110,9 +117,9 @@ static void write_object(void *buf, unsi\n \tadded_object(sha1, type, buf, size);\n }\n \n-static int resolve_delta(const char *type,\n-\tvoid *base, unsigned long base_size,\n-\tvoid *delta, unsigned long delta_size)\n+static void resolve_delta(const char *type,\n+\t\t\t  void *base, unsigned long base_size,\n+\t\t\t  void *delta, unsigned long delta_size)\n {\n \tvoid *result;\n \tunsigned long result_size;\n@@ -125,7 +132,6 @@ static int resolve_delta(const char *typ\n \tfree(delta);\n \twrite_object(result, result_size, type);\n \tfree(result);\n-\treturn 0;\n }\n \n static void added_object(unsigned char *sha1, const char *type, void *data, unsigned long size)\n@@ -145,7 +151,7 @@ static void added_object(unsigned char *\n \t}\n }\n \n-static int unpack_non_delta_entry(enum object_type kind, unsigned long size)\n+static void unpack_non_delta_entry(enum object_type kind, unsigned long size)\n {\n \tvoid *buf = get_data(size);\n \tconst char *type;\n@@ -157,39 +163,42 @@ static int unpack_non_delta_entry(enum o\n \tcase OBJ_TAG:    type = tag_type; break;\n \tdefault: die(\"bad type %d\", kind);\n \t}\n-\tif (!dry_run)\n+\tif (!dry_run && buf)\n \t\twrite_object(buf, size, type);\n \tfree(buf);\n-\treturn 0;\n }\n \n-static int unpack_delta_entry(unsigned long delta_size)\n+static void unpack_delta_entry(unsigned long delta_size)\n {\n \tvoid *delta_data, *base;\n \tunsigned long base_size;\n \tchar type[20];\n \tunsigned char base_sha1[20];\n-\tint result;\n \n \thashcpy(base_sha1, fill(20));\n \tuse(20);\n \n \tdelta_data = get_data(delta_size);\n-\tif (dry_run) {\n+\tif (dry_run || !delta_data) {\n \t\tfree(delta_data);\n-\t\treturn 0;\n+\t\treturn;\n \t}\n \n \tif (!has_sha1_file(base_sha1)) {\n \t\tadd_delta_to_list(base_sha1, delta_data, delta_size);\n-\t\treturn 0;\n+\t\treturn;\n \t}\n \tbase = read_sha1_file(base_sha1, type, &base_size);\n-\tif (!base)\n-\t\tdie(\"failed to read delta-pack base object %s\", sha1_to_hex(base_sha1));\n-\tresult = resolve_delta(type, base, base_size, delta_data, delta_size);\n+\tif (!base) {\n+\t\terror(\"failed to read delta-pack base object %s\",\n+\t\t      sha1_to_hex(base_sha1));\n+\t\tif (!desperate)\n+\t\t\texit(1);\n+\t\thas_errors = 1;\n+\t\treturn;\n+\t}\n+\tresolve_delta(type, base, base_size, delta_data, delta_size);\n \tfree(base);\n-\treturn result;\n }\n \n static void unpack_one(unsigned nr, unsigned total)\n@@ -236,7 +245,11 @@ static void unpack_one(unsigned nr, unsi\n \t\tunpack_delta_entry(size);\n \t\treturn;\n \tdefault:\n-\t\tdie(\"bad object type %d\", type);\n+\t\terror(\"bad object type %d\", type);\n+\t\thas_errors = 1;\n+\t\tif (desperate)\n+\t\t\treturn;\n+\t\texit(1);\n \t}\n }\n \n@@ -280,6 +293,10 @@ int cmd_unpack_objects(int argc, const c\n \t\t\t\tquiet = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"-r\")) {\n+\t\t\t\tdesperate = 1;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tusage(unpack_usage);\n \t\t}\n \n@@ -306,5 +323,5 @@ int cmd_unpack_objects(int argc, const c\n \t/* All done */\n \tif (!quiet)\n \t\tfprintf(stderr, \"\\n\");\n-\treturn 0;\n+\treturn has_errors;\n }\n\n\n-- \nVGER BF report: S 0.999272\n"}]}