зеркало из https://github.com/microsoft/git.git
Revert "unpack-objects: prevent writing of inconsistent objects"
This reverts commit d5ef408b9a
.
This commit is contained in:
Родитель
9eb7a50b6d
Коммит
c95b3ad9ea
|
@ -40,9 +40,6 @@ OPTIONS
|
||||||
and make the best effort to recover as many objects as
|
and make the best effort to recover as many objects as
|
||||||
possible.
|
possible.
|
||||||
|
|
||||||
--strict::
|
|
||||||
Don't write objects with broken content or links.
|
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
|
|
@ -7,13 +7,11 @@
|
||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "tree-walk.h"
|
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "decorate.h"
|
#include "decorate.h"
|
||||||
#include "fsck.h"
|
|
||||||
|
|
||||||
static int dry_run, quiet, recover, has_errors, strict;
|
static int dry_run, quiet, recover, has_errors;
|
||||||
static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] [--strict] < pack-file";
|
static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] < pack-file";
|
||||||
|
|
||||||
/* We always read in 4kB chunks. */
|
/* We always read in 4kB chunks. */
|
||||||
static unsigned char buffer[4096];
|
static unsigned char buffer[4096];
|
||||||
|
@ -33,16 +31,6 @@ static struct obj_buffer *lookup_object_buffer(struct object *base)
|
||||||
return lookup_decoration(&obj_decorate, base);
|
return lookup_decoration(&obj_decorate, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_object_buffer(struct object *object, char *buffer, unsigned long size)
|
|
||||||
{
|
|
||||||
struct obj_buffer *obj;
|
|
||||||
obj = xcalloc(1, sizeof(struct obj_buffer));
|
|
||||||
obj->buffer = buffer;
|
|
||||||
obj->size = size;
|
|
||||||
if (add_decoration(&obj_decorate, object, obj))
|
|
||||||
die("object %s tried to add buffer twice!", sha1_to_hex(object->sha1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure at least "min" bytes are available in the buffer, and
|
* Make sure at least "min" bytes are available in the buffer, and
|
||||||
* return the pointer to the buffer.
|
* return the pointer to the buffer.
|
||||||
|
@ -146,58 +134,9 @@ static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1,
|
||||||
struct obj_info {
|
struct obj_info {
|
||||||
off_t offset;
|
off_t offset;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
struct object *obj;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FLAG_OPEN (1u<<20)
|
|
||||||
#define FLAG_WRITTEN (1u<<21)
|
|
||||||
|
|
||||||
static struct obj_info *obj_list;
|
static struct obj_info *obj_list;
|
||||||
unsigned nr_objects;
|
|
||||||
|
|
||||||
static void write_cached_object(struct object *obj)
|
|
||||||
{
|
|
||||||
unsigned char sha1[20];
|
|
||||||
struct obj_buffer *obj_buf = lookup_object_buffer(obj);
|
|
||||||
if (write_sha1_file(obj_buf->buffer, obj_buf->size, typename(obj->type), sha1) < 0)
|
|
||||||
die("failed to write object %s", sha1_to_hex(obj->sha1));
|
|
||||||
obj->flags |= FLAG_WRITTEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_object(struct object *obj, int type, void *data)
|
|
||||||
{
|
|
||||||
if (!obj)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (obj->flags & FLAG_WRITTEN)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (type != OBJ_ANY && obj->type != type)
|
|
||||||
die("object type mismatch");
|
|
||||||
|
|
||||||
if (!(obj->flags & FLAG_OPEN)) {
|
|
||||||
unsigned long size;
|
|
||||||
int type = sha1_object_info(obj->sha1, &size);
|
|
||||||
if (type != obj->type || type <= 0)
|
|
||||||
die("object of unexpected type");
|
|
||||||
obj->flags |= FLAG_WRITTEN;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsck_object(obj, 1, fsck_error_function))
|
|
||||||
die("Error in object");
|
|
||||||
if (!fsck_walk(obj, check_object, 0))
|
|
||||||
die("Error on reachable objects of %s", sha1_to_hex(obj->sha1));
|
|
||||||
write_cached_object(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_rest(void)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < nr_objects; i++)
|
|
||||||
check_object(obj_list[i].obj, OBJ_ANY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void added_object(unsigned nr, enum object_type type,
|
static void added_object(unsigned nr, enum object_type type,
|
||||||
void *data, unsigned long size);
|
void *data, unsigned long size);
|
||||||
|
@ -205,36 +144,9 @@ static void added_object(unsigned nr, enum object_type type,
|
||||||
static void write_object(unsigned nr, enum object_type type,
|
static void write_object(unsigned nr, enum object_type type,
|
||||||
void *buf, unsigned long size)
|
void *buf, unsigned long size)
|
||||||
{
|
{
|
||||||
|
if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
|
||||||
|
die("failed to write object");
|
||||||
added_object(nr, type, buf, size);
|
added_object(nr, type, buf, size);
|
||||||
if (!strict) {
|
|
||||||
if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
|
|
||||||
die("failed to write object");
|
|
||||||
free(buf);
|
|
||||||
obj_list[nr].obj = 0;
|
|
||||||
} else if (type == OBJ_BLOB) {
|
|
||||||
struct blob *blob;
|
|
||||||
if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
|
|
||||||
die("failed to write object");
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
blob = lookup_blob(obj_list[nr].sha1);
|
|
||||||
if (blob)
|
|
||||||
blob->object.flags |= FLAG_WRITTEN;
|
|
||||||
else
|
|
||||||
die("invalid blob object");
|
|
||||||
obj_list[nr].obj = 0;
|
|
||||||
} else {
|
|
||||||
struct object *obj;
|
|
||||||
int eaten;
|
|
||||||
hash_sha1_file(buf, size, typename(type), obj_list[nr].sha1);
|
|
||||||
obj = parse_object_buffer(obj_list[nr].sha1, type, size, buf, &eaten);
|
|
||||||
if (!obj)
|
|
||||||
die("invalid %s", typename(type));
|
|
||||||
/* buf is stored via add_object_buffer and in obj, if its a tree or commit */
|
|
||||||
add_object_buffer(obj, buf, size);
|
|
||||||
obj->flags |= FLAG_OPEN;
|
|
||||||
obj_list[nr].obj = obj;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resolve_delta(unsigned nr, enum object_type type,
|
static void resolve_delta(unsigned nr, enum object_type type,
|
||||||
|
@ -251,6 +163,7 @@ static void resolve_delta(unsigned nr, enum object_type type,
|
||||||
die("failed to apply delta");
|
die("failed to apply delta");
|
||||||
free(delta);
|
free(delta);
|
||||||
write_object(nr, type, result, result_size);
|
write_object(nr, type, result, result_size);
|
||||||
|
free(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void added_object(unsigned nr, enum object_type type,
|
static void added_object(unsigned nr, enum object_type type,
|
||||||
|
@ -280,8 +193,7 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size,
|
||||||
|
|
||||||
if (!dry_run && buf)
|
if (!dry_run && buf)
|
||||||
write_object(nr, type, buf, size);
|
write_object(nr, type, buf, size);
|
||||||
else
|
free(buf);
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
|
static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
|
||||||
|
@ -424,8 +336,7 @@ static void unpack_all(void)
|
||||||
int i;
|
int i;
|
||||||
struct progress *progress = NULL;
|
struct progress *progress = NULL;
|
||||||
struct pack_header *hdr = fill(sizeof(struct pack_header));
|
struct pack_header *hdr = fill(sizeof(struct pack_header));
|
||||||
|
unsigned nr_objects = ntohl(hdr->hdr_entries);
|
||||||
nr_objects = ntohl(hdr->hdr_entries);
|
|
||||||
|
|
||||||
if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
|
if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
|
||||||
die("bad pack file");
|
die("bad pack file");
|
||||||
|
@ -436,7 +347,6 @@ static void unpack_all(void)
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
progress = start_progress("Unpacking objects", nr_objects);
|
progress = start_progress("Unpacking objects", nr_objects);
|
||||||
obj_list = xmalloc(nr_objects * sizeof(*obj_list));
|
obj_list = xmalloc(nr_objects * sizeof(*obj_list));
|
||||||
memset(obj_list, 0, nr_objects * sizeof(*obj_list));
|
|
||||||
for (i = 0; i < nr_objects; i++) {
|
for (i = 0; i < nr_objects; i++) {
|
||||||
unpack_one(i);
|
unpack_one(i);
|
||||||
display_progress(progress, i + 1);
|
display_progress(progress, i + 1);
|
||||||
|
@ -472,10 +382,6 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
|
||||||
recover = 1;
|
recover = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--strict")) {
|
|
||||||
strict = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prefixcmp(arg, "--pack_header=")) {
|
if (!prefixcmp(arg, "--pack_header=")) {
|
||||||
struct pack_header *hdr;
|
struct pack_header *hdr;
|
||||||
char *c;
|
char *c;
|
||||||
|
@ -501,8 +407,6 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
|
||||||
unpack_all();
|
unpack_all();
|
||||||
SHA1_Update(&ctx, buffer, offset);
|
SHA1_Update(&ctx, buffer, offset);
|
||||||
SHA1_Final(sha1, &ctx);
|
SHA1_Final(sha1, &ctx);
|
||||||
if (strict)
|
|
||||||
write_rest();
|
|
||||||
if (hashcmp(fill(20), sha1))
|
if (hashcmp(fill(20), sha1))
|
||||||
die("final sha1 did not match");
|
die("final sha1 did not match");
|
||||||
use(20);
|
use(20);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче