unpack-trees: pass checkout state explicitly to check_updates()
[gitweb.git] / builtin / cat-file.c
index 95604c4a63b88f7935a8bfb890cbdbee7e396ffe..2dfe6265f7df6099b51645fa67dbeeb3f4f567a4 100644 (file)
@@ -9,6 +9,7 @@
 #include "userdiff.h"
 #include "streaming.h"
 #include "tree-walk.h"
+#include "sha1-array.h"
 
 struct batch_options {
        int enabled;
@@ -130,7 +131,7 @@ struct expand_data {
        unsigned char sha1[20];
        enum object_type type;
        unsigned long size;
-       unsigned long disk_size;
+       off_t disk_size;
        const char *rest;
        unsigned char delta_base_sha1[20];
 
@@ -153,6 +154,13 @@ struct expand_data {
         * elements above, so you can retrieve the response from there.
         */
        struct object_info info;
+
+       /*
+        * This flag will be true if the requested batch format and options
+        * don't require us to call sha1_object_info, which can then be
+        * optimized out.
+        */
+       unsigned skip_object_info : 1;
 };
 
 static int is_atom(const char *atom, const char *s, int slen)
@@ -183,7 +191,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,
                if (data->mark_query)
                        data->info.disk_sizep = &data->disk_size;
                else
-                       strbuf_addf(sb, "%lu", data->disk_size);
+                       strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
        } else if (is_atom("rest", atom, len)) {
                if (data->mark_query)
                        data->split_on_whitespace = 1;
@@ -257,7 +265,8 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
 {
        struct strbuf buf = STRBUF_INIT;
 
-       if (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) {
+       if (!data->skip_object_info &&
+           sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) {
                printf("%s missing\n", obj_name ? obj_name : sha1_to_hex(data->sha1));
                fflush(stdout);
                return;
@@ -324,19 +333,19 @@ struct object_cb_data {
        struct expand_data *expand;
 };
 
-static int batch_object_cb(const unsigned char *sha1,
-                          struct object_cb_data *data)
+static void batch_object_cb(const unsigned char sha1[20], void *vdata)
 {
+       struct object_cb_data *data = vdata;
        hashcpy(data->expand->sha1, sha1);
        batch_object_write(NULL, data->opt, data->expand);
-       return 0;
 }
 
 static int batch_loose_object(const unsigned char *sha1,
                              const char *path,
                              void *data)
 {
-       return batch_object_cb(sha1, data);
+       sha1_array_append(data, sha1);
+       return 0;
 }
 
 static int batch_packed_object(const unsigned char *sha1,
@@ -344,7 +353,8 @@ static int batch_packed_object(const unsigned char *sha1,
                               uint32_t pos,
                               void *data)
 {
-       return batch_object_cb(sha1, data);
+       sha1_array_append(data, sha1);
+       return 0;
 }
 
 static int batch_objects(struct batch_options *opt)
@@ -367,6 +377,13 @@ static int batch_objects(struct batch_options *opt)
        strbuf_expand(&buf, opt->format, expand_format, &data);
        data.mark_query = 0;
 
+       if (opt->all_objects) {
+               struct object_info empty;
+               memset(&empty, 0, sizeof(empty));
+               if (!memcmp(&data.info, &empty, sizeof(empty)))
+                       data.skip_object_info = 1;
+       }
+
        /*
         * If we are printing out the object, then always fill in the type,
         * since we will want to decide whether or not to stream.
@@ -375,11 +392,17 @@ static int batch_objects(struct batch_options *opt)
                data.info.typep = &data.type;
 
        if (opt->all_objects) {
+               struct sha1_array sa = SHA1_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);
+
                cb.opt = opt;
                cb.expand = &data;
-               for_each_loose_object(batch_loose_object, &cb, 0);
-               for_each_packed_object(batch_packed_object, &cb, 0);
+               sha1_array_for_each_unique(&sa, batch_object_cb, &cb);
+
+               sha1_array_clear(&sa);
                return 0;
        }
 
@@ -393,7 +416,7 @@ static int batch_objects(struct batch_options *opt)
        save_warning = warn_on_object_refname_ambiguity;
        warn_on_object_refname_ambiguity = 0;
 
-       while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+       while (strbuf_getline(&buf, stdin) != EOF) {
                if (data.split_on_whitespace) {
                        /*
                         * Split at first whitespace, tying off the beginning
@@ -418,7 +441,7 @@ static int batch_objects(struct batch_options *opt)
 
 static const char * const cat_file_usage[] = {
        N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv) <object>"),
-       N_("git cat-file (--batch | --batch-check) [--follow-symlinks] < <list-of-objects>"),
+       N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"),
        NULL
 };
 
@@ -481,6 +504,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 
        git_config(git_cat_file_config, NULL);
 
+       batch.buffer_output = -1;
        argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
 
        if (opt) {
@@ -504,6 +528,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
                usage_with_options(cat_file_usage, options);
        }
 
+       if (batch.buffer_output < 0)
+               batch.buffer_output = batch.all_objects;
+
        if (batch.enabled)
                return batch_objects(&batch);