Browse Source
This adds knowledge of delta objects to fsck-cache and various object parsing code. A new switch to git-fsck-cache is provided to display the maximum delta depth found in a repository. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>maint
Nicolas Pitre
20 years ago
committed by
Linus Torvalds
10 changed files with 202 additions and 6 deletions
@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
|
||||
#include "object.h" |
||||
#include "blob.h" |
||||
#include "tree.h" |
||||
#include "commit.h" |
||||
#include "tag.h" |
||||
#include "delta.h" |
||||
#include "cache.h" |
||||
#include <string.h> |
||||
|
||||
/* the delta object definition (it can alias any other object) */ |
||||
struct delta { |
||||
union { |
||||
struct object object; |
||||
struct blob blob; |
||||
struct tree tree; |
||||
struct commit commit; |
||||
struct tag tag; |
||||
} u; |
||||
}; |
||||
|
||||
struct delta *lookup_delta(unsigned char *sha1) |
||||
{ |
||||
struct object *obj = lookup_object(sha1); |
||||
if (!obj) { |
||||
struct delta *ret = xmalloc(sizeof(struct delta)); |
||||
memset(ret, 0, sizeof(struct delta)); |
||||
created_object(sha1, &ret->u.object); |
||||
return ret; |
||||
} |
||||
return (struct delta *) obj; |
||||
} |
||||
|
||||
int parse_delta_buffer(struct delta *item, void *buffer, unsigned long size) |
||||
{ |
||||
struct object *reference; |
||||
struct object_list *p; |
||||
|
||||
if (item->u.object.delta) |
||||
return 0; |
||||
item->u.object.delta = 1; |
||||
if (size <= 20) |
||||
return -1; |
||||
reference = lookup_object(buffer); |
||||
if (!reference) { |
||||
struct delta *ref = xmalloc(sizeof(struct delta)); |
||||
memset(ref, 0, sizeof(struct delta)); |
||||
created_object(buffer, &ref->u.object); |
||||
reference = &ref->u.object; |
||||
} |
||||
|
||||
p = xmalloc(sizeof(*p)); |
||||
p->item = &item->u.object; |
||||
p->next = reference->attached_deltas; |
||||
reference->attached_deltas = p; |
||||
return 0; |
||||
} |
||||
|
||||
int process_deltas(void *src, unsigned long src_size, const char *src_type, |
||||
struct object_list *delta_list) |
||||
{ |
||||
int deepest = 0; |
||||
do { |
||||
struct object *obj = delta_list->item; |
||||
static char type[10]; |
||||
void *map, *delta, *buf; |
||||
unsigned long map_size, delta_size, buf_size; |
||||
map = map_sha1_file(obj->sha1, &map_size); |
||||
if (!map) |
||||
continue; |
||||
delta = unpack_sha1_file(map, map_size, type, &delta_size); |
||||
munmap(map, map_size); |
||||
if (!delta) |
||||
continue; |
||||
if (strcmp(type, "delta") || delta_size <= 20) { |
||||
free(delta); |
||||
continue; |
||||
} |
||||
buf = patch_delta(src, src_size, |
||||
delta+20, delta_size-20, |
||||
&buf_size); |
||||
free(delta); |
||||
if (!buf) |
||||
continue; |
||||
if (check_sha1_signature(obj->sha1, buf, buf_size, src_type) < 0) |
||||
printf("sha1 mismatch for delta %s\n", sha1_to_hex(obj->sha1)); |
||||
if (obj->type && obj->type != src_type) { |
||||
error("got %s when expecting %s for delta %s", |
||||
src_type, obj->type, sha1_to_hex(obj->sha1)); |
||||
free(buf); |
||||
continue; |
||||
} |
||||
obj->type = src_type; |
||||
if (src_type == blob_type) { |
||||
parse_blob_buffer((struct blob *)obj, buf, buf_size); |
||||
} else if (src_type == tree_type) { |
||||
parse_tree_buffer((struct tree *)obj, buf, buf_size); |
||||
} else if (src_type == commit_type) { |
||||
parse_commit_buffer((struct commit *)obj, buf, buf_size); |
||||
} else if (src_type == tag_type) { |
||||
parse_tag_buffer((struct tag *)obj, buf, buf_size); |
||||
} else { |
||||
error("unknown object type %s", src_type); |
||||
free(buf); |
||||
continue; |
||||
} |
||||
if (obj->attached_deltas) { |
||||
int depth = process_deltas(buf, buf_size, src_type, |
||||
obj->attached_deltas); |
||||
if (deepest < depth) |
||||
deepest = depth; |
||||
} |
||||
free(buf); |
||||
} while ((delta_list = delta_list->next)); |
||||
return deepest + 1; |
||||
} |
@ -1,6 +1,21 @@
@@ -1,6 +1,21 @@
|
||||
#ifndef DELTA_H |
||||
#define DELTA_H |
||||
|
||||
/* handling of delta buffers */ |
||||
extern void *diff_delta(void *from_buf, unsigned long from_size, |
||||
void *to_buf, unsigned long to_size, |
||||
unsigned long *delta_size); |
||||
extern void *patch_delta(void *src_buf, unsigned long src_size, |
||||
void *delta_buf, unsigned long delta_size, |
||||
unsigned long *dst_size); |
||||
|
||||
/* handling of delta objects */ |
||||
struct delta; |
||||
struct object_list; |
||||
extern struct delta *lookup_delta(unsigned char *sha1); |
||||
extern int parse_delta_buffer(struct delta *item, void *buffer, unsigned long size); |
||||
extern int parse_delta(struct delta *item, unsigned char sha1); |
||||
extern int process_deltas(void *src, unsigned long src_size, |
||||
const char *src_type, struct object_list *delta); |
||||
|
||||
#endif |
||||
|
Loading…
Reference in new issue