From f3123c4ab3d3698262e59561ac084de45b10365a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 22 Oct 2005 01:28:13 -0700 Subject: [PATCH] pack-objects: Allow use of pre-generated pack. 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 --- Makefile | 2 +- cache.h | 1 + copy.c | 37 ++++++++++++++++++++++++++ pack-objects.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 copy.c diff --git a/Makefile b/Makefile index 5b0306d3..701067d4 100644 --- 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 d7760168..2e36cc5b 100644 --- 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 index 00000000..20092757 --- /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; +} + diff --git a/pack-objects.c b/pack-objects.c index b3e61520..4e941e73 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -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; } -- 2.11.0