diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cache.h | 1 | ||||
-rw-r--r-- | copy.c | 37 | ||||
-rw-r--r-- | pack-objects.c | 84 |
4 files changed, 112 insertions, 12 deletions
@@ -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) @@ -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 0000000000..20092757d3 --- /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 b3e6152033..4e941e7392 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; } |