Only in git-0.04-b64: base64val.pl diff -urp git-0.04/cache.h git-0.04-b64/cache.h --- git-0.04/cache.h 2005-04-10 11:19:02.000000000 -0700 +++ git-0.04-b64/cache.h 2005-04-12 15:52:32.000000000 -0700 @@ -99,9 +99,9 @@ extern void * read_sha1_file(const unsig extern int write_sha1_file(char *buf, unsigned len, unsigned char *return_sha1); extern int check_sha1_signature(unsigned char *sha1, void *buf, unsigned long size); -/* Convert to/from hex/sha1 representation */ -extern int get_sha1_hex(const char *hex, unsigned char *sha1); -extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ +/* Convert to/from base64/sha1 representation */ +extern int get_sha1_b64(const char *hex, unsigned char *sha1); +extern char *sha1_to_b64(const unsigned char *sha1); /* static buffer result! */ /* General helper functions */ extern void usage(const char *err, ...); diff -urp git-0.04/cat-file.c git-0.04-b64/cat-file.c --- git-0.04/cat-file.c 2005-04-09 11:16:47.000000000 -0700 +++ git-0.04-b64/cat-file.c 2005-04-12 15:43:36.000000000 -0700 @@ -12,7 +12,7 @@ int main(int argc, char **argv) void *buf; unsigned long size; - if (argc != 3 || get_sha1_hex(argv[2], sha1)) + if (argc != 3 || get_sha1_b64(argv[2], sha1)) usage("cat-file: cat-file [-t | tagname] "); buf = read_sha1_file(sha1, type, &size); if (!buf) { diff -urp git-0.04/checkout-cache.c git-0.04-b64/checkout-cache.c --- git-0.04/checkout-cache.c 2005-04-11 09:21:33.000000000 -0700 +++ git-0.04-b64/checkout-cache.c 2005-04-12 15:43:36.000000000 -0700 @@ -75,7 +75,7 @@ static int write_entry(struct cache_entr new = read_sha1_file(ce->sha1, type, &size); if (!new || strcmp(type, "blob")) { fprintf(stderr, "checkout-cache: unable to read sha1 file of %s (%s)\n", - ce->name, sha1_to_hex(ce->sha1)); + ce->name, sha1_to_b64(ce->sha1)); return -1; } fd = create_file(ce->name, ce->st_mode); diff -urp git-0.04/commit-tree.c git-0.04-b64/commit-tree.c --- git-0.04/commit-tree.c 2005-04-11 07:36:00.000000000 -0700 +++ git-0.04-b64/commit-tree.c 2005-04-12 15:43:36.000000000 -0700 @@ -121,13 +121,13 @@ int main(int argc, char **argv) char *buffer; unsigned int size; - if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0) + if (argc < 2 || get_sha1_b64(argv[1], tree_sha1) < 0) usage("commit-tree [-p ]* < changelog"); for (i = 2; i < argc; i += 2) { char *a, *b; a = argv[i]; b = argv[i+1]; - if (!b || strcmp(a, "-p") || get_sha1_hex(b, parent_sha1[parents])) + if (!b || strcmp(a, "-p") || get_sha1_b64(b, parent_sha1[parents])) usage("commit-tree [-p ]* < changelog"); parents++; } @@ -153,7 +153,7 @@ int main(int argc, char **argv) remove_special(date); remove_special(realdate); init_buffer(&buffer, &size); - add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1)); + add_buffer(&buffer, &size, "tree %s\n", sha1_to_b64(tree_sha1)); /* * NOTE! This ordering means that the same exact tree merged with a @@ -161,7 +161,7 @@ int main(int argc, char **argv) * if everything else stays the same. */ for (i = 0; i < parents; i++) - add_buffer(&buffer, &size, "parent %s\n", sha1_to_hex(parent_sha1[i])); + add_buffer(&buffer, &size, "parent %s\n", sha1_to_b64(parent_sha1[i])); /* Person/date information */ add_buffer(&buffer, &size, "author %s <%s> %s\n", gecos, email, date); @@ -174,6 +174,6 @@ int main(int argc, char **argv) finish_buffer("commit ", &buffer, &size); write_sha1_file(buffer, size, commit_sha1); - printf("%s\n", sha1_to_hex(commit_sha1)); + printf("%s\n", sha1_to_b64(commit_sha1)); return 0; } diff -urp git-0.04/diff-tree.c git-0.04-b64/diff-tree.c --- git-0.04/diff-tree.c 2005-04-11 07:36:23.000000000 -0700 +++ git-0.04-b64/diff-tree.c 2005-04-12 15:45:32.000000000 -0700 @@ -64,7 +64,7 @@ static void show_file(const char *prefix tree = read_sha1_file(sha1, type, &size); if (!tree || strcmp(type, "tree")) - usage("corrupt tree sha %s", sha1_to_hex(sha1)); + usage("corrupt tree sha %s", sha1_to_b64(sha1)); show_tree(prefix, tree, size, newbase); @@ -73,7 +73,7 @@ static void show_file(const char *prefix return; } - printf("%s%o %s %s%s%c", prefix, mode, sha1_to_hex(sha1), base, path, 0); + printf("%s%o %s %s%s%c", prefix, mode, sha1_to_b64(sha1), base, path, 0); } static int compare_tree_entry(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base) @@ -82,7 +82,7 @@ static int compare_tree_entry(void *tree const char *path1, *path2; const unsigned char *sha1, *sha2; int cmp, pathlen1, pathlen2; - char old_sha1_hex[50]; + char old_sha1_b64[28]; sha1 = extract(tree1, size1, &path1, &mode1); sha2 = extract(tree2, size2, &path2, &mode2); @@ -119,8 +119,8 @@ static int compare_tree_entry(void *tree return retval; } - strcpy(old_sha1_hex, sha1_to_hex(sha1)); - printf("*%o->%o %s->%s %s%s%c", mode1, mode2, old_sha1_hex, sha1_to_hex(sha2), base, path1, 0); + strcpy(old_sha1_b64, sha1_to_b64(sha1)); + printf("*%o->%o %s->%s %s%s%c", mode1, mode2, old_sha1_b64, sha1_to_b64(sha2), base, path1, 0); return 0; } @@ -187,7 +187,7 @@ int main(int argc, char **argv) usage("diff-tree [-R] "); } - if (argc != 3 || get_sha1_hex(argv[1], old) || get_sha1_hex(argv[2], new)) + if (argc != 3 || get_sha1_b64(argv[1], old) || get_sha1_b64(argv[2], new)) usage("diff-tree "); return diff_tree_sha1(old, new, ""); } diff -urp git-0.04/fsck-cache.c git-0.04-b64/fsck-cache.c --- git-0.04/fsck-cache.c 2005-04-10 22:33:13.000000000 -0700 +++ git-0.04-b64/fsck-cache.c 2005-04-13 19:39:57.261198520 -0700 @@ -20,6 +20,9 @@ static struct seen *seen; static int nr_seen, alloc_seen, nr_needs, alloc_needs; +static const char base64sym[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + /* * These two functions build up a graph in memory about * what objects we've referenced, and found, and types.. @@ -68,8 +71,8 @@ static void check_connectivity(void) if (lookup_seen(n->needs, n->tag)) continue; - strcpy(hex, sha1_to_hex(n->parent)); - printf("missing %s: %s referenced by %s\n", n->tag, sha1_to_hex(n->needs), hex); + strcpy(hex, sha1_to_b64(n->parent)); + printf("missing %s: %s referenced by %s\n", n->tag, sha1_to_b64(n->needs), hex); } /* Tell the user about things not referenced.. */ @@ -78,7 +81,7 @@ static void check_connectivity(void) if (s->needed) continue; - printf("unreferenced %s: %s\n", s->tag, sha1_to_hex(s->sha1)); + printf("unreferenced %s: %s\n", s->tag, sha1_to_b64(s->sha1)); } } @@ -128,7 +131,7 @@ static int fsck_tree(unsigned char *sha1 /* Warn about trees that don't do the recursive thing.. */ if (warn_old_tree && strchr(path, '/')) { - fprintf(stderr, "warning: fsck-cache: tree %s has full pathnames in it\n", sha1_to_hex(sha1)); + fprintf(stderr, "warning: fsck-cache: tree %s has full pathnames in it\n", sha1_to_b64(sha1)); warn_old_tree = 0; } @@ -147,20 +150,20 @@ static int fsck_commit(unsigned char *sh if (memcmp(data, "tree ", 5)) return -1; - if (get_sha1_hex(data + 5, tree_sha1) < 0) + if (get_sha1_b64(data + 5, tree_sha1) < 0) return -1; mark_needs_sha1(sha1, "tree", tree_sha1); - data += 5 + 40 + 1; /* "tree " + + '\n' */ + data += 5 + 27 + 1; /* "tree " + + '\n' */ parents = 0; while (!memcmp(data, "parent ", 7)) { - if (get_sha1_hex(data + 7, parent_sha1) < 0) + if (get_sha1_b64(data + 7, parent_sha1) < 0) return -1; mark_needs_sha1(sha1, "commit", parent_sha1); - data += 7 + 40 + 1; /* "parent " + + '\n' */ + data += 7 + 27 + 1; /* "parent " + + '\n' */ parents++; } if (!parents) - printf("root: %s\n", sha1_to_hex(sha1)); + printf("root: %s\n", sha1_to_b64(sha1)); return 0; } @@ -182,7 +185,7 @@ static int fsck_entry(unsigned char *sha static int fsck_name(char *hex) { unsigned char sha1[20]; - if (!get_sha1_hex(hex, sha1)) { + if (!get_sha1_b64(hex, sha1)) { unsigned long mapsize; void *map = map_sha1_file(sha1, &mapsize); if (map) { @@ -205,8 +208,12 @@ static int fsck_dir(int i, char *path) struct dirent *de; if (!dir) { - fprintf(stderr, "missing sha1 directory '%s'", path); +#if 0 /* This is now permitted */ + fprintf(stderr, "missing sha1 directory '%s'\n", path); return -1; +#else + return 0; +#endif } while ((de = readdir(dir)) != NULL) { @@ -221,8 +228,9 @@ static int fsck_dir(int i, char *path) if (de->d_name[0] != '.') break; continue; - case 38: - sprintf(name, "%02x", i); + case 25: + name[0] = base64sym[i >> 6]; + name[1] = base64sym[i & 0x3f]; memcpy(name+2, de->d_name, len+1); if (!fsck_name(name)) continue; @@ -241,9 +249,10 @@ int main(int argc, char **argv) if (argc != 1) usage("fsck-cache"); sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT; - for (i = 0; i < 256; i++) { + for (i = 0; i < 4096; i++) { static char dir[4096]; - sprintf(dir, "%s/%02x", sha1_dir, i); + sprintf(dir, "%s/%c%c", sha1_dir, + base64sym[i >> 6], base64sym[i & 0x3f]); fsck_dir(i, dir); } check_connectivity(); diff -urp git-0.04/init-db.c git-0.04-b64/init-db.c --- git-0.04/init-db.c 2005-04-11 09:20:49.000000000 -0700 +++ git-0.04-b64/init-db.c 2005-04-13 19:40:03.021258711 -0700 @@ -5,10 +5,13 @@ */ #include "cache.h" +static const char base64sym[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + int main(int argc, char **argv) { char *sha1_dir = getenv(DB_ENVIRONMENT), *path; - int len, i; + int len, i, j; if (mkdir(".dircache", 0755) < 0) { perror("unable to create .dircache"); @@ -41,16 +44,23 @@ int main(int argc, char **argv) exit(1); } } +#if 0 /* Optional, but is it good or bad for performance? */ path = malloc(len + 40); memcpy(path, sha1_dir, len); - for (i = 0; i < 256; i++) { - sprintf(path+len, "/%02x", i); - if (mkdir(path, 0755) < 0) { - if (errno != EEXIST) { - perror(path); - exit(1); + path[len] = '/'; + path[len+3] = '\0'; + for (i = 0; i < 64; i++) { + path[len+1] = base64sym[i]; + for (j = 0; j < 64; j++) { + path[len+2] = base64sym[j]; + if (mkdir(path, 0755) < 0) { + if (errno != EEXIST) { + perror(path); + exit(1); + } } } } +#endif return 0; } diff -urp git-0.04/Makefile git-0.04-b64/Makefile --- git-0.04/Makefile 2005-04-10 20:48:10.000000000 -0700 +++ git-0.04-b64/Makefile 2005-04-12 17:06:42.000000000 -0700 @@ -1,4 +1,4 @@ -CFLAGS=-g -O3 -Wall +CFLAGS=-g -O -W -Wall CC=gcc PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ diff -urp git-0.04/read-cache.c git-0.04-b64/read-cache.c --- git-0.04/read-cache.c 2005-04-10 21:05:12.000000000 -0700 +++ git-0.04-b64/read-cache.c 2005-04-13 19:39:36.123977639 -0700 @@ -3,6 +3,8 @@ * * Copyright (C) Linus Torvalds, 2005 */ + +#include #include "cache.h" const char *sha1_file_directory = NULL; @@ -19,43 +21,81 @@ void usage(const char *err, ...) exit(1); } -static unsigned hexval(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return ~0; -} +/* This is actually a hybrid of filesystem-safe base64, and regular + base64, see RFC 3548. However, we *have* to avoid slashes, and + *want* to avoid filenames starting with "-". */ + +static const char base64sym[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + +static char base64val[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; -int get_sha1_hex(const char *hex, unsigned char *sha1) +int get_sha1_b64(const char *hex, unsigned char *sha1) { int i; - for (i = 0; i < 20; i++) { - unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]); - if (val & ~0xff) + unsigned int d = 0; + int b = 0; + + for (i = 0; i < 27; i++) { + signed char v = base64val[(unsigned char)*hex++]; + if ( v < 0 ) return -1; - *sha1++ = val; - hex += 2; + d = (d << 6) + v; + b += 6; + + if ( b >= 8 ) { + b -= 8; + *sha1++ = d >> b; + } } return 0; } -char * sha1_to_hex(const unsigned char *sha1) +static void sha1_to_b64_p(const unsigned char * digest, char * output) { - static char buffer[50]; - static const char hex[] = "0123456789abcdef"; - char *buf = buffer; + unsigned char input[21]; int i; - - for (i = 0; i < 20; i++) { - unsigned int val = *sha1++; - *buf++ = hex[val >> 4]; - *buf++ = hex[val & 0xf]; - } - return buffer; + unsigned char *p; + char *q; + uint32_t bv; + + memcpy(input, digest, 20); + input[20] = 0; /* Pad to multiple of 3 bytes */ + + p = input; q = output; + for ( i = 0 ; i < 7 ; i++ ) { + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + *q++ = base64sym[bv >> 18]; + *q++ = base64sym[(bv >> 12) & 0x3f]; + *q++ = base64sym[(bv >> 6) & 0x3f]; + *q++ = base64sym[bv & 0x3f]; + } + *--q = '\0'; /* The last character is not significant */ +} + +char * sha1_to_b64(const unsigned char *digest) +{ + static unsigned char output[28]; /* 27 chars + final null */ + sha1_to_b64_p(digest, output); + return output; } /* @@ -65,7 +105,6 @@ char * sha1_to_hex(const unsigned char * */ char *sha1_file_name(const unsigned char *sha1) { - int i; static char *name, *base; if (!base) { @@ -73,18 +112,13 @@ char *sha1_file_name(const unsigned char int len = strlen(sha1_file_directory); base = malloc(len + 60); memcpy(base, sha1_file_directory, len); - memset(base+len, 0, 60); base[len] = '/'; - base[len+3] = '/'; name = base + len + 1; } - for (i = 0; i < 20; i++) { - static char hex[] = "0123456789abcdef"; - unsigned int val = sha1[i]; - char *pos = name + i*2 + (i > 0); - *pos++ = hex[val >> 4]; - *pos = hex[val & 0xf]; - } + sha1_to_b64_p(sha1, name+1); + name[0] = name[1]; + name[1] = name[2]; + name[2] = '/'; return base; } @@ -211,9 +245,22 @@ int write_sha1_file(char *buf, unsigned int write_sha1_buffer(const unsigned char *sha1, void *buf, unsigned int size) { char *filename = sha1_file_name(sha1); - int fd; + char *p; + int fd, mrv; fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (fd < 0 && + errno == ENOENT && + (p = strrchr(filename, '/'))) { + int e = errno; + *p = '\0'; + mrv = mkdir(filename, 0777); + *p = '/'; + if ( mrv == 0 ) + fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); + else + errno = e; + } if (fd < 0) return (errno == EEXIST) ? 0 : -1; write(fd, buf, size); diff -urp git-0.04/read-tree.c git-0.04-b64/read-tree.c --- git-0.04/read-tree.c 2005-04-10 10:28:53.000000000 -0700 +++ git-0.04-b64/read-tree.c 2005-04-12 15:43:36.000000000 -0700 @@ -87,7 +87,7 @@ int main(int argc, char **argv) } continue; } - if (get_sha1_hex(arg, sha1) < 0) { + if (get_sha1_b64(arg, sha1) < 0) { fprintf(stderr, "read-tree [-m] \n"); goto out; } diff -urp git-0.04/show-diff.c git-0.04-b64/show-diff.c --- git-0.04/show-diff.c 2005-04-09 11:16:47.000000000 -0700 +++ git-0.04-b64/show-diff.c 2005-04-12 16:12:14.000000000 -0700 @@ -29,7 +29,7 @@ int main(int argc, char **argv) for (i = 0; i < entries; i++) { struct stat st; struct cache_entry *ce = active_cache[i]; - int n, changed; + int changed; unsigned long size; char type[20]; void *new; @@ -43,10 +43,8 @@ int main(int argc, char **argv) printf("%s: ok\n", ce->name); continue; } - printf("%.*s: ", ce->namelen, ce->name); - for (n = 0; n < 20; n++) - printf("%02x", ce->sha1[n]); - printf("\n"); + printf("%.*s: %s\n", + ce->namelen, ce->name, sha1_to_b64(ce->sha1)); new = read_sha1_file(ce->sha1, type, &size); show_differences(ce, &st, new, size); free(new); diff -urp git-0.04/write-tree.c git-0.04-b64/write-tree.c --- git-0.04/write-tree.c 2005-04-10 09:13:10.000000000 -0700 +++ git-0.04-b64/write-tree.c 2005-04-12 15:43:36.000000000 -0700 @@ -109,6 +109,6 @@ int main(int argc, char **argv) usage("no cache contents to write"); if (write_tree(active_cache, entries, "", 0, sha1) != entries) usage("write-tree: internal error"); - printf("%s\n", sha1_to_hex(sha1)); + printf("%s\n", sha1_to_b64(sha1)); return 0; }