sha1_file: restore OBJECT_INFO_QUICK functionality
[gitweb.git] / builtin / pack-objects.c
index c753e9237a8d5981a17e872db33d5326bd8d7eab..f5fc40177cc052eb1bb5cb1ec5b94eae6b481d11 100644 (file)
@@ -15,6 +15,8 @@
 #include "diff.h"
 #include "revision.h"
 #include "list-objects.h"
+#include "list-objects-filter.h"
+#include "list-objects-filter-options.h"
 #include "pack-objects.h"
 #include "progress.h"
 #include "refs.h"
@@ -25,6 +27,7 @@
 #include "sha1-array.h"
 #include "argv-array.h"
 #include "mru.h"
+#include "packfile.h"
 
 static const char *pack_usage[] = {
        N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),
@@ -72,12 +75,24 @@ static int use_bitmap_index = -1;
 static int write_bitmap_index;
 static uint16_t write_bitmap_options;
 
+static int exclude_promisor_objects;
+
 static unsigned long delta_cache_size = 0;
 static unsigned long max_delta_cache_size = 256 * 1024 * 1024;
 static unsigned long cache_max_small_delta_size = 1000;
 
 static unsigned long window_memory_limit = 0;
 
+static struct list_objects_filter_options filter_options;
+
+enum missing_action {
+       MA_ERROR = 0,      /* fail if any missing objects are encountered */
+       MA_ALLOW_ANY,      /* silently allow ALL missing objects */
+       MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
+};
+static enum missing_action arg_missing_action;
+static show_object_fn fn_show_object;
+
 /*
  * stats
  */
@@ -1011,7 +1026,7 @@ static int want_object_in_pack(const unsigned char *sha1,
                        return want;
        }
 
-       for (entry = packed_git_mru->head; entry; entry = entry->next) {
+       for (entry = packed_git_mru.head; entry; entry = entry->next) {
                struct packed_git *p = entry->item;
                off_t offset;
 
@@ -1029,7 +1044,7 @@ static int want_object_in_pack(const unsigned char *sha1,
                        }
                        want = want_found_object(exclude, p);
                        if (!exclude && want > 0)
-                               mru_mark(packed_git_mru, entry);
+                               mru_mark(&packed_git_mru, entry);
                        if (want != -1)
                                return want;
                }
@@ -1276,7 +1291,7 @@ static int done_pbase_path_pos(unsigned hash)
        int lo = 0;
        int hi = done_pbase_paths_num;
        while (lo < hi) {
-               int mi = (hi + lo) / 2;
+               int mi = lo + (hi - lo) / 2;
                if (done_pbase_paths[mi] == hash)
                        return mi;
                if (done_pbase_paths[mi] < hash)
@@ -2170,7 +2185,10 @@ static void *threaded_find_deltas(void *arg)
 {
        struct thread_params *me = arg;
 
+       progress_lock();
        while (me->remaining) {
+               progress_unlock();
+
                find_deltas(me->list, &me->remaining,
                            me->window, me->depth, me->processed);
 
@@ -2192,7 +2210,10 @@ static void *threaded_find_deltas(void *arg)
                        pthread_cond_wait(&me->cond, &me->mutex);
                me->data_ready = 0;
                pthread_mutex_unlock(&me->mutex);
+
+               progress_lock();
        }
+       progress_unlock();
        /* leave ->working 1 so that this doesn't get more work assigned */
        return NULL;
 }
@@ -2545,6 +2566,64 @@ static void show_object(struct object *obj, const char *name, void *data)
        obj->flags |= OBJECT_ADDED;
 }
 
+static void show_object__ma_allow_any(struct object *obj, const char *name, void *data)
+{
+       assert(arg_missing_action == MA_ALLOW_ANY);
+
+       /*
+        * Quietly ignore ALL missing objects.  This avoids problems with
+        * staging them now and getting an odd error later.
+        */
+       if (!has_object_file(&obj->oid))
+               return;
+
+       show_object(obj, name, data);
+}
+
+static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data)
+{
+       assert(arg_missing_action == MA_ALLOW_PROMISOR);
+
+       /*
+        * Quietly ignore EXPECTED missing objects.  This avoids problems with
+        * staging them now and getting an odd error later.
+        */
+       if (!has_object_file(&obj->oid) && is_promisor_object(&obj->oid))
+               return;
+
+       show_object(obj, name, data);
+}
+
+static int option_parse_missing_action(const struct option *opt,
+                                      const char *arg, int unset)
+{
+       assert(arg);
+       assert(!unset);
+
+       if (!strcmp(arg, "error")) {
+               arg_missing_action = MA_ERROR;
+               fn_show_object = show_object;
+               return 0;
+       }
+
+       if (!strcmp(arg, "allow-any")) {
+               arg_missing_action = MA_ALLOW_ANY;
+               fetch_if_missing = 0;
+               fn_show_object = show_object__ma_allow_any;
+               return 0;
+       }
+
+       if (!strcmp(arg, "allow-promisor")) {
+               arg_missing_action = MA_ALLOW_PROMISOR;
+               fetch_if_missing = 0;
+               fn_show_object = show_object__ma_allow_promisor;
+               return 0;
+       }
+
+       die(_("invalid value for --missing"));
+       return 0;
+}
+
 static void show_edge(struct commit *commit)
 {
        add_preferred_base(commit->object.oid.hash);
@@ -2556,8 +2635,8 @@ struct in_pack_object {
 };
 
 struct in_pack {
-       int alloc;
-       int nr;
+       unsigned int alloc;
+       unsigned int nr;
        struct in_pack_object *array;
 };
 
@@ -2809,7 +2888,12 @@ static void get_object_list(int ac, const char **av)
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
        mark_edges_uninteresting(&revs, show_edge);
-       traverse_commit_list(&revs, show_commit, show_object, NULL);
+
+       if (!fn_show_object)
+               fn_show_object = show_object;
+       traverse_commit_list_filtered(&filter_options, &revs,
+                                     show_commit, fn_show_object, NULL,
+                                     NULL);
 
        if (unpack_unreachable_expiration) {
                revs.ignore_missing_links = 1;
@@ -2945,6 +3029,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                         N_("use a bitmap index if available to speed up counting objects")),
                OPT_BOOL(0, "write-bitmap-index", &write_bitmap_index,
                         N_("write a bitmap index together with the pack index")),
+               OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
+               { OPTION_CALLBACK, 0, "missing", NULL, N_("action"),
+                 N_("handling for missing objects"), PARSE_OPT_NONEG,
+                 option_parse_missing_action },
+               OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects,
+                        N_("do not pack objects in promisor packfiles")),
                OPT_END(),
        };
 
@@ -2990,6 +3080,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                argv_array_push(&rp, "--unpacked");
        }
 
+       if (exclude_promisor_objects) {
+               use_internal_rev_list = 1;
+               fetch_if_missing = 0;
+               argv_array_push(&rp, "--exclude-promisor-objects");
+       }
+
        if (!reuse_object)
                reuse_delta = 0;
        if (pack_compression_level == -1)
@@ -3021,6 +3117,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        if (!rev_list_all || !rev_list_reflog || !rev_list_index)
                unpack_unreachable_expiration = 0;
 
+       if (filter_options.choice) {
+               if (!pack_to_stdout)
+                       die("cannot use --filter without --stdout.");
+               use_bitmap_index = 0;
+       }
+
        /*
         * "soft" reasons not to use bitmaps - for on-disk repack by default we want
         *