]>
Commit | Line | Data |
---|---|---|
d98b46f8 LT |
1 | #include "cache.h" |
2 | ||
3 | struct entry { | |
4 | unsigned char old_sha1[20]; | |
5 | unsigned char new_sha1[20]; | |
6 | int converted; | |
7 | }; | |
8 | ||
9 | #define MAXOBJECTS (1000000) | |
10 | ||
11 | static struct entry *convert[MAXOBJECTS]; | |
12 | static int nr_convert; | |
13 | ||
14 | static struct entry * convert_entry(unsigned char *sha1); | |
15 | ||
16 | static struct entry *insert_new(unsigned char *sha1, int pos) | |
17 | { | |
18 | struct entry *new = malloc(sizeof(struct entry)); | |
19 | ||
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 | } | |
29 | ||
30 | static struct entry *lookup_entry(unsigned char *sha1) | |
31 | { | |
32 | int low = 0, high = nr_convert; | |
33 | ||
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 | } | |
48 | ||
49 | static void convert_blob(void *buffer, unsigned long size) | |
50 | { | |
51 | /* Nothing to do */ | |
52 | } | |
53 | ||
54 | static void convert_binary_sha1(void *buffer) | |
55 | { | |
56 | struct entry *entry = convert_entry(buffer); | |
57 | memcpy(buffer, entry->new_sha1, 20); | |
58 | } | |
59 | ||
60 | static void convert_ascii_sha1(void *buffer) | |
61 | { | |
62 | unsigned char sha1[20]; | |
63 | struct entry *entry; | |
64 | ||
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 | } | |
70 | ||
71 | static void convert_tree(void *buffer, unsigned long size) | |
72 | { | |
73 | while (size) { | |
74 | int len = 1+strlen(buffer); | |
75 | ||
76 | convert_binary_sha1(buffer + len); | |
77 | ||
78 | len += 20; | |
79 | if (len > size) | |
80 | die("corrupt tree object"); | |
81 | size -= len; | |
82 | buffer += len; | |
83 | } | |
84 | } | |
85 | ||
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 | } | |
95 | ||
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; | |
102 | ||
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)); | |
108 | ||
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; | |
125 | } | |
126 | ||
127 | int main(int argc, char **argv) | |
128 | { | |
129 | unsigned char sha1[20]; | |
130 | struct entry *entry; | |
131 | ||
132 | if (argc != 2 || get_sha1_hex(argv[1], sha1)) | |
133 | usage("convert-cache <sha1>"); | |
134 | ||
135 | entry = convert_entry(sha1); | |
136 | printf("new sha1: %s\n", sha1_to_hex(entry->new_sha1)); | |
137 | return 0; | |
138 | } |