index-pack: start learning to emulate "verify-pack -v"
[gitweb.git] / builtin / pack-objects.c
index 0e8167311884d38c48a9421bf8aede89e7f2c22d..dc471b78c405f799ddd8ca8136559b0dc19bc255 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;
@@ -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));
@@ -1298,9 +1295,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 +1540,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 +1881,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 +2131,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 +2276,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;
                }