I wrote a quick and dirty patch to check out blobs into .git/blobs, and hardlink them into the working directory; if you symlink .git/blobs together for a number of trees, this should save a lot of space if you have a lot of working directories. It also seems to speed up and save space in "git fork" (or whatever it ends up being called) if the symlink is added to the list of symlinks. It seems effective from trying it with a git tree. Ingo: do you want to try it with a kernel tree? I think you said you wanted good performance for that sort of thing.
Patch follows: Make a cache of expanded blobs, and hardlink against them instead of creating more files. This is useful if the cache is shared between different working directories and your editor breaks hard links appropriately. Signed-Off-By: Daniel Barkalow <[EMAIL PROTECTED]> Index: checkout-cache.c =================================================================== --- e4d994ccc556a50f89297c6dbcf22e484a344cf8/checkout-cache.c (mode:100664 sha1:431b7032576f40d93a08be801e26f76c168ed57b) +++ 2ee21d9b73c81d51f6c0e8ff35a92a4f11105fc4/checkout-cache.c (mode:100664 sha1:9624b3c783c482c9f6da8bf8b2cf45b316107776) @@ -34,6 +34,8 @@ */ #include "cache.h" +#define HARDLINK_CACHE ".git/blobs" + static int force = 0, quiet = 0; static void create_directories(const char *path) @@ -64,6 +66,80 @@ return fd; } +#ifdef HARDLINK_CACHE + +/* + * NOTE! This returns a statically allocated buffer, so you have to be + * careful about using it. Do a "strdup()" if you need to save the + * filename. + */ +char *sha1_blob_cache_file_name(const unsigned char *sha1) +{ + int i; + static char *name, *base; + + if (!base) { + char *sha1_file_directory = HARDLINK_CACHE; + 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]; + } + return base; +} + +static int write_entry(struct cache_entry *ce) +{ + int fd; + void *new; + unsigned long size; + long wrote; + char type[20]; + char *cache_name; + struct stat st; + + cache_name = sha1_blob_cache_file_name(ce->sha1); + + if (stat(cache_name, &st)) { + new = read_sha1_file(ce->sha1, type, &size); + if (!new || strcmp(type, "blob")) { + return error("checkout-cache: unable to read sha1 file of %s (%s)", + ce->name, sha1_to_hex(ce->sha1)); + } + fd = create_file(cache_name, ntohl(ce->ce_mode)); + if (fd < 0) { + free(new); + return error("checkout-cache: unable to create %s (%s)", + ce->name, strerror(errno)); + } + wrote = write(fd, new, size); + close(fd); + free(new); + if (wrote != size) + return error("checkout-cache: unable to write %s", + ce->name); + } + if (link(cache_name, ce->name)) { + if (errno == ENOENT) { + create_directories(ce->name); + link(cache_name, ce->name); + } + } + return 0; +} + +#else + static int write_entry(struct cache_entry *ce) { int fd; @@ -91,6 +167,8 @@ return 0; } +#endif + static int checkout_entry(struct cache_entry *ce) { struct stat st; - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html