Merge branch 'sr/transport-helper-fix'
[gitweb.git] / builtin / pack-objects.c
index 0e8167311884d38c48a9421bf8aede89e7f2c22d..84e6dafb12657a6f0431f2a287d0cca976269c35 100644 (file)
 #include "list-objects.h"
 #include "progress.h"
 #include "refs.h"
-
-#ifndef NO_PTHREADS
-#include <pthread.h>
 #include "thread-utils.h"
-#endif
 
 static const char pack_usage[] =
-  "git pack-objects [{ -q | --progress | --all-progress }]\n"
+  "git pack-objects [ -q | --progress | --all-progress ]\n"
   "        [--all-progress-implied]\n"
-  "        [--max-pack-size=N] [--local] [--incremental]\n"
-  "        [--window=N] [--window-memory=N] [--depth=N]\n"
+  "        [--max-pack-size=<n>] [--local] [--incremental]\n"
+  "        [--window=<n>] [--window-memory=<n>] [--depth=<n>]\n"
   "        [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset]\n"
-  "        [--threads=N] [--non-empty] [--revs [--unpacked | --all]*]\n"
+  "        [--threads=<n>] [--non-empty] [--revs [--unpacked | --all]]\n"
   "        [--reflog] [--stdout | base-name] [--include-tag]\n"
-  "        [--keep-unreachable | --unpack-unreachable \n"
-  "        [<ref-list | <object-list]";
+  "        [--keep-unreachable | --unpack-unreachable]\n"
+  "        [< ref-list | < object-list]";
 
 struct object_entry {
        struct pack_idx_entry idx;
@@ -74,6 +70,7 @@ static int local;
 static int incremental;
 static int ignore_packed_keep;
 static int allow_ofs_delta;
+static struct pack_idx_option pack_idx_opts;
 static const char *base_name;
 static int progress = 1;
 static int window = 10;
@@ -130,13 +127,13 @@ static void *get_delta(struct object_entry *entry)
 
 static unsigned long do_compress(void **pptr, unsigned long size)
 {
-       z_stream stream;
+       git_zstream stream;
        void *in, *out;
        unsigned long maxsize;
 
        memset(&stream, 0, sizeof(stream));
-       deflateInit(&stream, pack_compression_level);
-       maxsize = deflateBound(&stream, size);
+       git_deflate_init(&stream, pack_compression_level);
+       maxsize = git_deflate_bound(&stream, size);
 
        in = *pptr;
        out = xmalloc(maxsize);
@@ -146,9 +143,9 @@ static unsigned long do_compress(void **pptr, unsigned long size)
        stream.avail_in = size;
        stream.next_out = out;
        stream.avail_out = maxsize;
-       while (deflate(&stream, Z_FINISH) == Z_OK)
+       while (git_deflate(&stream, Z_FINISH) == Z_OK)
                ; /* nothing */
-       deflateEnd(&stream);
+       git_deflate_end(&stream);
 
        free(in);
        return stream.total_out;
@@ -164,7 +161,7 @@ static int check_pack_inflate(struct packed_git *p,
                off_t len,
                unsigned long expect)
 {
-       z_stream stream;
+       git_zstream stream;
        unsigned char fakebuf[4096], *in;
        int st;
 
@@ -191,12 +188,12 @@ static void copy_pack_data(struct sha1file *f,
                off_t len)
 {
        unsigned char *in;
-       unsigned int avail;
+       unsigned long avail;
 
        while (len) {
                in = use_pack(p, w_curs, offset, &avail);
                if (avail > len)
-                       avail = (unsigned int)len;
+                       avail = (unsigned long)len;
                sha1write(f, in, avail);
                offset += avail;
                len -= avail;
@@ -431,7 +428,7 @@ static int write_one(struct sha1file *f,
        written_list[nr_written++] = &e->idx;
 
        /* make sure off_t is sufficiently large not to wrap */
-       if (*offset > *offset + size)
+       if (signed_add_overflows(*offset, size))
                die("pack too large for current definition of off_t");
        *offset += size;
        return 1;
@@ -497,8 +494,8 @@ static void write_pack_file(void)
                        const char *idx_tmp_name;
                        char tmpname[PATH_MAX];
 
-                       idx_tmp_name = write_idx_file(NULL, written_list,
-                                                     nr_written, sha1);
+                       idx_tmp_name = write_idx_file(NULL, written_list, nr_written,
+                                                     &pack_idx_opts, sha1);
 
                        snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
                                 base_name, sha1_to_hex(sha1));
@@ -998,7 +995,7 @@ static void check_object(struct object_entry *entry)
                const unsigned char *base_ref = NULL;
                struct object_entry *base_entry;
                unsigned long used, used_0;
-               unsigned int avail;
+               unsigned long avail;
                off_t ofs;
                unsigned char *buf, c;
 
@@ -1146,8 +1143,12 @@ static void get_object_details(void)
                sorted_by_offset[i] = objects + i;
        qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
 
-       for (i = 0; i < nr_objects; i++)
-               check_object(sorted_by_offset[i]);
+       for (i = 0; i < nr_objects; i++) {
+               struct object_entry *entry = sorted_by_offset[i];
+               check_object(entry);
+               if (big_file_threshold <= entry->size)
+                       entry->no_try_delta = 1;
+       }
 
        free(sorted_by_offset);
 }
@@ -1298,9 +1299,23 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
                read_lock();
                src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz);
                read_unlock();
-               if (!src->data)
+               if (!src->data) {
+                       if (src_entry->preferred_base) {
+                               static int warned = 0;
+                               if (!warned++)
+                                       warning("object %s cannot be read",
+                                               sha1_to_hex(src_entry->idx.sha1));
+                               /*
+                                * Those objects are not included in the
+                                * resulting pack.  Be resilient and ignore
+                                * them if they can't be read, in case the
+                                * pack could be created nevertheless.
+                                */
+                               return 0;
+                       }
                        die("object %s cannot be read",
                            sha1_to_hex(src_entry->idx.sha1));
+               }
                if (sz != src_size)
                        die("object %s inconsistent object length (%lu vs %lu)",
                            sha1_to_hex(src_entry->idx.sha1), sz, src_size);
@@ -1529,7 +1544,7 @@ static void try_to_free_from_threads(size_t size)
        read_unlock();
 }
 
-try_to_free_t old_try_to_free_routine;
+static try_to_free_t old_try_to_free_routine;
 
 /*
  * The main thread waits on the condition that (at least) one of the workers
@@ -1870,10 +1885,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                return 0;
        }
        if (!strcmp(k, "pack.indexversion")) {
-               pack_idx_default_version = git_config_int(k, v);
-               if (pack_idx_default_version > 2)
+               pack_idx_opts.version = git_config_int(k, v);
+               if (pack_idx_opts.version > 2)
                        die("bad pack.indexversion=%"PRIu32,
-                               pack_idx_default_version);
+                           pack_idx_opts.version);
                return 0;
        }
        if (!strcmp(k, "pack.packsizelimit")) {
@@ -2120,6 +2135,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        rp_av[1] = "--objects"; /* --thin will make it --objects-edge */
        rp_ac = 2;
 
+       reset_pack_idx_option(&pack_idx_opts);
        git_config(git_pack_config, NULL);
        if (!pack_compression_seen && core_compression_seen)
                pack_compression_level = core_compression_level;
@@ -2264,12 +2280,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                }
                if (!prefixcmp(arg, "--index-version=")) {
                        char *c;
-                       pack_idx_default_version = strtoul(arg + 16, &c, 10);
-                       if (pack_idx_default_version > 2)
+                       pack_idx_opts.version = strtoul(arg + 16, &c, 10);
+                       if (pack_idx_opts.version > 2)
                                die("bad %s", arg);
                        if (*c == ',')
-                               pack_idx_off32_limit = strtoul(c+1, &c, 0);
-                       if (*c || pack_idx_off32_limit & 0x80000000)
+                               pack_idx_opts.off32_limit = strtoul(c+1, &c, 0);
+                       if (*c || pack_idx_opts.off32_limit & 0x80000000)
                                die("bad %s", arg);
                        continue;
                }