diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-20 01:10:46 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-20 01:10:46 -0700 |
commit | d98b46f8d9a3daf965a39f8c0089c1401e0081ee (patch) | |
tree | 765ea3ef9d7d57d29a38d4c1d1ddc4be17554936 /convert-cache.c | |
parent | cb126d8d7906b3c15f313ca479259e567042840a (diff) | |
download | git-d98b46f8d9a3daf965a39f8c0089c1401e0081ee.tar.gz git-d98b46f8d9a3daf965a39f8c0089c1401e0081ee.tar.xz |
Do SHA1 hash _before_ compression.
And add a "convert-cache" program to convert from old-style
to new-style.
Diffstat (limited to 'convert-cache.c')
-rw-r--r-- | convert-cache.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/convert-cache.c b/convert-cache.c new file mode 100644 index 000000000..97e995251 --- /dev/null +++ b/convert-cache.c @@ -0,0 +1,138 @@ +#include "cache.h" + +struct entry { + unsigned char old_sha1[20]; + unsigned char new_sha1[20]; + int converted; +}; + +#define MAXOBJECTS (1000000) + +static struct entry *convert[MAXOBJECTS]; +static int nr_convert; + +static struct entry * convert_entry(unsigned char *sha1); + +static struct entry *insert_new(unsigned char *sha1, int pos) +{ + struct entry *new = malloc(sizeof(struct entry)); + + memset(new, 0, sizeof(*new)); + memcpy(new->old_sha1, sha1, 20); + memmove(convert + pos + 1, convert + pos, (nr_convert - pos) * sizeof(struct entry *)); + convert[pos] = new; + nr_convert++; + if (nr_convert == MAXOBJECTS) + die("you're kidding me - hit maximum object limit"); + return new; +} + +static struct entry *lookup_entry(unsigned char *sha1) +{ + int low = 0, high = nr_convert; + + while (low < high) { + int next = (low + high) / 2; + struct entry *n = convert[next]; + int cmp = memcmp(sha1, n->old_sha1, 20); + if (!cmp) + return n; + if (cmp < 0) { + high = next; + continue; + } + low = next+1; + } + return insert_new(sha1, low); +} + +static void convert_blob(void *buffer, unsigned long size) +{ + /* Nothing to do */ +} + +static void convert_binary_sha1(void *buffer) +{ + struct entry *entry = convert_entry(buffer); + memcpy(buffer, entry->new_sha1, 20); +} + +static void convert_ascii_sha1(void *buffer) +{ + unsigned char sha1[20]; + struct entry *entry; + + if (get_sha1_hex(buffer, sha1)) + die("bad sha1"); + entry = convert_entry(sha1); + memcpy(buffer, sha1_to_hex(entry->new_sha1), 40); +} + +static void convert_tree(void *buffer, unsigned long size) +{ + while (size) { + int len = 1+strlen(buffer); + + convert_binary_sha1(buffer + len); + + len += 20; + if (len > size) + die("corrupt tree object"); + size -= len; + buffer += len; + } +} + +static void convert_commit(void *buffer, unsigned long size) +{ + convert_ascii_sha1(buffer+5); + buffer += 46; /* "tree " + "hex sha1" + "\n" */ + while (!memcmp(buffer, "parent ", 7)) { + convert_ascii_sha1(buffer+7); + buffer += 48; + } +} + +static struct entry * convert_entry(unsigned char *sha1) +{ + struct entry *entry = lookup_entry(sha1); + char type[20]; + void *buffer, *data; + unsigned long size, offset; + + if (entry->converted) + return entry; + data = read_sha1_file(sha1, type, &size); + if (!data) + die("unable to read object %s", sha1_to_hex(sha1)); + + buffer = malloc(size + 100); + offset = sprintf(buffer, "%s %lu", type, size)+1; + memcpy(buffer + offset, data, size); + + if (!strcmp(type, "blob")) + convert_blob(buffer + offset, size); + else if (!strcmp(type, "tree")) + convert_tree(buffer + offset, size); + else if (!strcmp(type, "commit")) + convert_commit(buffer + offset, size); + else + die("unknown object type '%s' in %s", type, sha1_to_hex(sha1)); + write_sha1_file(buffer, size + offset, entry->new_sha1); + entry->converted = 1; + free(buffer); + return entry; +} + +int main(int argc, char **argv) +{ + unsigned char sha1[20]; + struct entry *entry; + + if (argc != 2 || get_sha1_hex(argv[1], sha1)) + usage("convert-cache <sha1>"); + + entry = convert_entry(sha1); + printf("new sha1: %s\n", sha1_to_hex(entry->new_sha1)); + return 0; +} |