[PATCH] Anal retentive 'const unsigned char *sha1'
[git/git.git] / delta.c
1 #include "object.h"
2 #include "blob.h"
3 #include "tree.h"
4 #include "commit.h"
5 #include "tag.h"
6 #include "delta.h"
7 #include "cache.h"
8
9 /* the delta object definition (it can alias any other object) */
10 struct delta {
11 union {
12 struct object object;
13 struct blob blob;
14 struct tree tree;
15 struct commit commit;
16 struct tag tag;
17 } u;
18 };
19
20 struct delta *lookup_delta(const unsigned char *sha1)
21 {
22 struct object *obj = lookup_object(sha1);
23 if (!obj) {
24 struct delta *ret = xmalloc(sizeof(struct delta));
25 memset(ret, 0, sizeof(struct delta));
26 created_object(sha1, &ret->u.object);
27 return ret;
28 }
29 return (struct delta *) obj;
30 }
31
32 int parse_delta_buffer(struct delta *item, void *buffer, unsigned long size)
33 {
34 struct object *reference;
35 struct object_list *p;
36
37 if (item->u.object.delta)
38 return 0;
39 item->u.object.delta = 1;
40 if (size <= 20)
41 return -1;
42 reference = lookup_object(buffer);
43 if (!reference) {
44 struct delta *ref = xmalloc(sizeof(struct delta));
45 memset(ref, 0, sizeof(struct delta));
46 created_object(buffer, &ref->u.object);
47 reference = &ref->u.object;
48 }
49
50 p = xmalloc(sizeof(*p));
51 p->item = &item->u.object;
52 p->next = reference->attached_deltas;
53 reference->attached_deltas = p;
54 return 0;
55 }
56
57 int process_deltas(void *src, unsigned long src_size, const char *src_type,
58 struct object_list *delta_list)
59 {
60 int deepest = 0;
61 do {
62 struct object *obj = delta_list->item;
63 static char type[10];
64 void *map, *delta, *buf;
65 unsigned long map_size, delta_size, buf_size;
66 map = map_sha1_file(obj->sha1, &map_size);
67 if (!map)
68 continue;
69 delta = unpack_sha1_file(map, map_size, type, &delta_size);
70 munmap(map, map_size);
71 if (!delta)
72 continue;
73 if (strcmp(type, "delta") || delta_size <= 20) {
74 free(delta);
75 continue;
76 }
77 buf = patch_delta(src, src_size,
78 delta+20, delta_size-20,
79 &buf_size);
80 free(delta);
81 if (!buf)
82 continue;
83 if (check_sha1_signature(obj->sha1, buf, buf_size, src_type) < 0)
84 printf("sha1 mismatch for delta %s\n", sha1_to_hex(obj->sha1));
85 if (obj->type && obj->type != src_type) {
86 error("got %s when expecting %s for delta %s",
87 src_type, obj->type, sha1_to_hex(obj->sha1));
88 free(buf);
89 continue;
90 }
91 obj->type = src_type;
92 if (src_type == blob_type) {
93 parse_blob_buffer((struct blob *)obj, buf, buf_size);
94 } else if (src_type == tree_type) {
95 parse_tree_buffer((struct tree *)obj, buf, buf_size);
96 } else if (src_type == commit_type) {
97 parse_commit_buffer((struct commit *)obj, buf, buf_size);
98 } else if (src_type == tag_type) {
99 parse_tag_buffer((struct tag *)obj, buf, buf_size);
100 } else {
101 error("unknown object type %s", src_type);
102 free(buf);
103 continue;
104 }
105 if (obj->attached_deltas) {
106 int depth = process_deltas(buf, buf_size, src_type,
107 obj->attached_deltas);
108 if (deepest < depth)
109 deepest = depth;
110 }
111 free(buf);
112 } while ((delta_list = delta_list->next));
113 return deepest + 1;
114 }