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

Reply via email to