cat-file: use oidset check-and-insert
[gitweb.git] / builtin / cat-file.c
index 2c46d257cd9a09a8f8ff05820b53224394385c7d..04b5cda191804ce9727a1a01901c88222fb69535 100644 (file)
@@ -13,6 +13,7 @@
 #include "tree-walk.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "object-store.h"
 
 struct batch_options {
        int enabled;
@@ -20,6 +21,7 @@ struct batch_options {
        int print_contents;
        int buffer_output;
        int all_objects;
+       int unordered;
        int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
        const char *format;
 };
@@ -77,7 +79,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
        switch (opt) {
        case 't':
                oi.type_name = &sb;
-               if (oid_object_info_extended(&oid, &oi, flags) < 0)
+               if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
                        die("git cat-file: could not get object info");
                if (sb.len) {
                        printf("%s\n", sb.buf);
@@ -88,7 +90,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 
        case 's':
                oi.sizep = &size;
-               if (oid_object_info_extended(&oid, &oi, flags) < 0)
+               if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
                        die("git cat-file: could not get object info");
                printf("%lu\n", size);
                return 0;
@@ -116,7 +118,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                /* else fallthrough */
 
        case 'p':
-               type = oid_object_info(&oid, NULL);
+               type = oid_object_info(the_repository, &oid, NULL);
                if (type < 0)
                        die("Not a valid object name %s", obj_name);
 
@@ -140,7 +142,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
        case 0:
                if (type_from_string(exp_type) == OBJ_BLOB) {
                        struct object_id blob_oid;
-                       if (oid_object_info(&oid, NULL) == OBJ_TAG) {
+                       if (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {
                                char *buffer = read_object_file(&oid, &type,
                                                                &size);
                                const char *target;
@@ -151,7 +153,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                        } else
                                oidcpy(&blob_oid, &oid);
 
-                       if (oid_object_info(&blob_oid, NULL) == OBJ_BLOB)
+                       if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
                                return stream_blob_to_fd(1, &blob_oid, NULL, 0);
                        /*
                         * we attempted to dereference a tag to a blob
@@ -312,7 +314,7 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
                                        die("could not convert '%s' %s",
                                            oid_to_hex(oid), data->rest);
                        } else
-                               die("BUG: invalid cmdmode: %c", opt->cmdmode);
+                               BUG("invalid cmdmode: %c", opt->cmdmode);
                        batch_write(opt, contents, size);
                        free(contents);
                } else if (stream_blob_to_fd(1, oid, NULL, 0) < 0)
@@ -342,7 +344,7 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
        struct strbuf buf = STRBUF_INIT;
 
        if (!data->skip_object_info &&
-           oid_object_info_extended(&data->oid, &data->info,
+           oid_object_info_extended(the_repository, &data->oid, &data->info,
                                     OBJECT_INFO_LOOKUP_REPLACE) < 0) {
                printf("%s missing\n",
                       obj_name ? obj_name : oid_to_hex(&data->oid));
@@ -387,7 +389,7 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt,
                               (uintmax_t)strlen(obj_name), obj_name);
                        break;
                default:
-                       die("BUG: unknown get_sha1_with_context result %d\n",
+                       BUG("unknown get_sha1_with_context result %d\n",
                               result);
                        break;
                }
@@ -409,6 +411,7 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt,
 struct object_cb_data {
        struct batch_options *opt;
        struct expand_data *expand;
+       struct oidset *seen;
 };
 
 static int batch_object_cb(const struct object_id *oid, void *vdata)
@@ -419,23 +422,48 @@ static int batch_object_cb(const struct object_id *oid, void *vdata)
        return 0;
 }
 
-static int batch_loose_object(const struct object_id *oid,
-                             const char *path,
-                             void *data)
+static int collect_loose_object(const struct object_id *oid,
+                               const char *path,
+                               void *data)
 {
        oid_array_append(data, oid);
        return 0;
 }
 
-static int batch_packed_object(const struct object_id *oid,
-                              struct packed_git *pack,
-                              uint32_t pos,
-                              void *data)
+static int collect_packed_object(const struct object_id *oid,
+                                struct packed_git *pack,
+                                uint32_t pos,
+                                void *data)
 {
        oid_array_append(data, oid);
        return 0;
 }
 
+static int batch_unordered_object(const struct object_id *oid, void *vdata)
+{
+       struct object_cb_data *data = vdata;
+
+       if (oidset_insert(data->seen, oid))
+               return 0;
+
+       return batch_object_cb(oid, data);
+}
+
+static int batch_unordered_loose(const struct object_id *oid,
+                                const char *path,
+                                void *data)
+{
+       return batch_unordered_object(oid, data);
+}
+
+static int batch_unordered_packed(const struct object_id *oid,
+                                 struct packed_git *pack,
+                                 uint32_t pos,
+                                 void *data)
+{
+       return batch_unordered_object(oid, data);
+}
+
 static int batch_objects(struct batch_options *opt)
 {
        struct strbuf buf = STRBUF_INIT;
@@ -472,19 +500,35 @@ static int batch_objects(struct batch_options *opt)
                data.info.typep = &data.type;
 
        if (opt->all_objects) {
-               struct oid_array sa = OID_ARRAY_INIT;
                struct object_cb_data cb;
 
-               for_each_loose_object(batch_loose_object, &sa, 0);
-               for_each_packed_object(batch_packed_object, &sa, 0);
                if (repository_format_partial_clone)
                        warning("This repository has extensions.partialClone set. Some objects may not be loaded.");
 
                cb.opt = opt;
                cb.expand = &data;
-               oid_array_for_each_unique(&sa, batch_object_cb, &cb);
 
-               oid_array_clear(&sa);
+               if (opt->unordered) {
+                       struct oidset seen = OIDSET_INIT;
+
+                       cb.seen = &seen;
+
+                       for_each_loose_object(batch_unordered_loose, &cb, 0);
+                       for_each_packed_object(batch_unordered_packed, &cb,
+                                              FOR_EACH_OBJECT_PACK_ORDER);
+
+                       oidset_clear(&seen);
+               } else {
+                       struct oid_array sa = OID_ARRAY_INIT;
+
+                       for_each_loose_object(collect_loose_object, &sa, 0);
+                       for_each_packed_object(collect_packed_object, &sa, 0);
+
+                       oid_array_for_each_unique(&sa, batch_object_cb, &cb);
+
+                       oid_array_clear(&sa);
+               }
+
                return 0;
        }
 
@@ -585,6 +629,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
                         N_("follow in-tree symlinks (used with --batch or --batch-check)")),
                OPT_BOOL(0, "batch-all-objects", &batch.all_objects,
                         N_("show all objects with --batch or --batch-check")),
+               OPT_BOOL(0, "unordered", &batch.unordered,
+                        N_("do not order --batch-all-objects output")),
                OPT_END()
        };