Code

Do SHA1 hash _before_ compression.
[git.git] / convert-cache.c
1 #include "cache.h"
3 struct entry {
4         unsigned char old_sha1[20];
5         unsigned char new_sha1[20];
6         int converted;
7 };
9 #define MAXOBJECTS (1000000)
11 static struct entry *convert[MAXOBJECTS];
12 static int nr_convert;
14 static struct entry * convert_entry(unsigned char *sha1);
16 static struct entry *insert_new(unsigned char *sha1, int pos)
17 {
18         struct entry *new = malloc(sizeof(struct entry));
20         memset(new, 0, sizeof(*new));
21         memcpy(new->old_sha1, sha1, 20);
22         memmove(convert + pos + 1, convert + pos, (nr_convert - pos) * sizeof(struct entry *));
23         convert[pos] = new;
24         nr_convert++;
25         if (nr_convert == MAXOBJECTS)
26                 die("you're kidding me - hit maximum object limit");
27         return new;
28 }
30 static struct entry *lookup_entry(unsigned char *sha1)
31 {
32         int low = 0, high = nr_convert;
34         while (low < high) {
35                 int next = (low + high) / 2;
36                 struct entry *n = convert[next];
37                 int cmp = memcmp(sha1, n->old_sha1, 20);
38                 if (!cmp)
39                         return n;
40                 if (cmp < 0) {
41                         high = next;
42                         continue;
43                 }
44                 low = next+1;
45         }
46         return insert_new(sha1, low);
47 }
49 static void convert_blob(void *buffer, unsigned long size)
50 {
51         /* Nothing to do */
52 }
54 static void convert_binary_sha1(void *buffer)
55 {
56         struct entry *entry = convert_entry(buffer);
57         memcpy(buffer, entry->new_sha1, 20);
58 }
60 static void convert_ascii_sha1(void *buffer)
61 {
62         unsigned char sha1[20];
63         struct entry *entry;
65         if (get_sha1_hex(buffer, sha1))
66                 die("bad sha1");
67         entry = convert_entry(sha1);
68         memcpy(buffer, sha1_to_hex(entry->new_sha1), 40);
69 }
71 static void convert_tree(void *buffer, unsigned long size)
72 {
73         while (size) {
74                 int len = 1+strlen(buffer);
76                 convert_binary_sha1(buffer + len);
78                 len += 20;
79                 if (len > size)
80                         die("corrupt tree object");
81                 size -= len;
82                 buffer += len;
83         }
84 }
86 static void convert_commit(void *buffer, unsigned long size)
87 {
88         convert_ascii_sha1(buffer+5);
89         buffer += 46;    /* "tree " + "hex sha1" + "\n" */
90         while (!memcmp(buffer, "parent ", 7)) {
91                 convert_ascii_sha1(buffer+7);
92                 buffer += 48;
93         }
94 }
96 static struct entry * convert_entry(unsigned char *sha1)
97 {
98         struct entry *entry = lookup_entry(sha1);
99         char type[20];
100         void *buffer, *data;
101         unsigned long size, offset;
103         if (entry->converted)
104                 return entry;
105         data = read_sha1_file(sha1, type, &size);
106         if (!data)
107                 die("unable to read object %s", sha1_to_hex(sha1));
109         buffer = malloc(size + 100);
110         offset = sprintf(buffer, "%s %lu", type, size)+1;
111         memcpy(buffer + offset, data, size);
112         
113         if (!strcmp(type, "blob"))
114                 convert_blob(buffer + offset, size);
115         else if (!strcmp(type, "tree"))
116                 convert_tree(buffer + offset, size);
117         else if (!strcmp(type, "commit"))
118                 convert_commit(buffer + offset, size);
119         else
120                 die("unknown object type '%s' in %s", type, sha1_to_hex(sha1));
121         write_sha1_file(buffer, size + offset, entry->new_sha1);
122         entry->converted = 1;
123         free(buffer);
124         return entry;
127 int main(int argc, char **argv)
129         unsigned char sha1[20];
130         struct entry *entry;
132         if (argc != 2 || get_sha1_hex(argv[1], sha1))
133                 usage("convert-cache <sha1>");
135         entry = convert_entry(sha1);
136         printf("new sha1: %s\n", sha1_to_hex(entry->new_sha1));
137         return 0;