Code

pack-objects: Allow use of pre-generated pack.
authorJunio C Hamano <junkio@cox.net>
Sat, 22 Oct 2005 08:28:13 +0000 (01:28 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 26 Oct 2005 19:37:49 +0000 (12:37 -0700)
git-pack-objects can reuse pack files stored in $GIT_DIR/pack-cache
directory, when a necessary pack is found.  This is hopefully useful
when upload-pack (called from git-daemon) is expected to receive
requests for the same set of objects many times (e.g full cloning
request of any project, or updates from the set of heads previous day
to the latest for a slow moving project).

Currently git-pack-objects does *not* keep pack files it creates for
reusing.  It might be useful to add --update-cache option to it,
which would allow it store pack files it created in the pack-cache
directory, and prune rarely used ones from it.

Signed-off-by: Junio C Hamano <junkio@cox.net>
Makefile
cache.h
copy.c [new file with mode: 0644]
pack-objects.c

index 5b0306d3910f1e19a2b80c75e180dc5121366667..701067d43519274cce028358fe8e3e10457df017 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -159,7 +159,7 @@ LIB_OBJS = \
        object.o pack-check.o patch-delta.o path.o pkt-line.o \
        quote.o read-cache.o refs.o run-command.o \
        server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
-       tag.o tree.o usage.o config.o environment.o ctype.o \
+       tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
        $(DIFF_OBJS)
 
 LIBS = $(LIB_FILE)
diff --git a/cache.h b/cache.h
index d776016822a8fed78358c7dccc334ee576302a36..2e36cc5b8b28859a9e2322893789a27b9057a7be 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -413,4 +413,5 @@ static inline int sane_case(int x, int high)
        return x;
 }
 
+extern int copy_fd(int ifd, int ofd);
 #endif /* CACHE_H */
diff --git a/copy.c b/copy.c
new file mode 100644 (file)
index 0000000..2009275
--- /dev/null
+++ b/copy.c
@@ -0,0 +1,37 @@
+#include "cache.h"
+
+int copy_fd(int ifd, int ofd)
+{
+       while (1) {
+               int len;
+               char buffer[8192];
+               char *buf = buffer;
+               len = read(ifd, buffer, sizeof(buffer));
+               if (!len)
+                       break;
+               if (len < 0) {
+                       if (errno == EAGAIN)
+                               continue;
+                       return error("copy-fd: read returned %s",
+                                    strerror(errno));
+               }
+               while (1) {
+                       int written = write(ofd, buf, len);
+                       if (written > 0) {
+                               buf += written;
+                               len -= written;
+                               if (!len)
+                                       break;
+                       }
+                       if (!written)
+                               return error("copy-fd: write returned 0");
+                       if (errno == EAGAIN || errno == EINTR)
+                               continue;
+                       return error("copy-fd: write returned %s",
+                                    strerror(errno));
+               }
+       }
+       close(ifd);
+       return 0;
+}
+
index b3e61520339231f6d9a43c545100f4d5f87e0aac..4e941e7392077dca9b511282be13e2b559589e5b 100644 (file)
@@ -400,6 +400,71 @@ static void find_deltas(struct object_entry **list, int window, int depth)
        free(array);
 }
 
+static void prepare_pack(int window, int depth)
+{
+       get_object_details();
+
+       fprintf(stderr, "Packing %d objects\n", nr_objects);
+
+       sorted_by_type = create_sorted_list(type_size_sort);
+       if (window && depth)
+               find_deltas(sorted_by_type, window+1, depth);
+       write_pack_file();
+}
+
+static int reuse_cached_pack(unsigned char *sha1, int pack_to_stdout)
+{
+       static const char cache[] = "pack-cache/pack-%s.%s";
+       char *cached_pack, *cached_idx;
+       int ifd, ofd, ifd_ix = -1;
+
+       cached_pack = git_path(cache, sha1_to_hex(sha1), "pack");
+       ifd = open(cached_pack, O_RDONLY);
+       if (ifd < 0)
+               return 0;
+
+       if (!pack_to_stdout) {
+               cached_idx = git_path(cache, sha1_to_hex(sha1), "idx");
+               ifd_ix = open(cached_idx, O_RDONLY);
+               if (ifd_ix < 0) {
+                       close(ifd);
+                       return 0;
+               }
+       }
+
+       fprintf(stderr, "Reusing %d objects pack %s\n", nr_objects,
+               sha1_to_hex(sha1));
+
+       if (pack_to_stdout) {
+               if (copy_fd(ifd, 1))
+                       exit(1);
+               close(ifd);
+       }
+       else {
+               char name[PATH_MAX];
+               snprintf(name, sizeof(name),
+                        "%s-%s.%s", base_name, sha1_to_hex(sha1), "pack");
+               ofd = open(name, O_CREAT | O_EXCL | O_WRONLY, 0666);
+               if (ofd < 0)
+                       die("unable to open %s (%s)", name, strerror(errno));
+               if (copy_fd(ifd, ofd))
+                       exit(1);
+               close(ifd);
+
+               snprintf(name, sizeof(name),
+                        "%s-%s.%s", base_name, sha1_to_hex(sha1), "idx");
+               ofd = open(name, O_CREAT | O_EXCL | O_WRONLY, 0666);
+               if (ofd < 0)
+                       die("unable to open %s (%s)", name, strerror(errno));
+               if (copy_fd(ifd_ix, ofd))
+                       exit(1);
+               close(ifd_ix);
+               puts(sha1_to_hex(sha1));
+       }
+
+       return 1;
+}
+
 int main(int argc, char **argv)
 {
        SHA_CTX ctx;
@@ -472,9 +537,6 @@ int main(int argc, char **argv)
        }
        if (non_empty && !nr_objects)
                return 0;
-       get_object_details();
-
-       fprintf(stderr, "Packing %d objects\n", nr_objects);
 
        sorted_by_sha = create_sorted_list(sha1_sort);
        SHA1_Init(&ctx);
@@ -485,14 +547,14 @@ int main(int argc, char **argv)
        }
        SHA1_Final(object_list_sha1, &ctx);
 
-       sorted_by_type = create_sorted_list(type_size_sort);
-       if (window && depth)
-               find_deltas(sorted_by_type, window+1, depth);
-
-       write_pack_file();
-       if (!pack_to_stdout) {
-               write_index_file();
-               puts(sha1_to_hex(object_list_sha1));
+       if (reuse_cached_pack(object_list_sha1, pack_to_stdout))
+               ;
+       else {
+               prepare_pack(window, depth);
+               if (!pack_to_stdout) {
+                       write_index_file();
+                       puts(sha1_to_hex(object_list_sha1));
+               }
        }
        return 0;
 }