summaryrefslogtreecommitdiff
path: root/builtin/cat-file.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2013-07-10 07:45:47 -0400
committerJunio C Hamano <gitster@pobox.com>2013-07-12 09:18:12 -0700
commit93d2a607ba05fba31442941d0425019120993846 (patch)
treef2fe7d26dc9e6a517a0a526eb0c6879ede4feab1 /builtin/cat-file.c
parentb71bd48017981f7257d8c0a5096825321b4fb49b (diff)
downloadgit-93d2a607ba05fba31442941d0425019120993846.tar.gz
cat-file: add --batch-check=<format>
The `cat-file --batch-check` command can be used to quickly get information about a large number of objects. However, it provides a fixed set of information. This patch adds an optional <format> option to --batch-check to allow a caller to specify which items they are interested in, and in which order to output them. This is not very exciting for now, since we provide the same limited set that you could already get. However, it opens the door to adding new format items in the future without breaking backwards compatibility (or forcing callers to pay the cost to calculate uninteresting items). Since the --batch option shares code with --batch-check, it receives the same feature, though it is less likely to be of interest there. The format atom names are chosen to match their counterparts in for-each-ref. Though we do not (yet) share any code with for-each-ref's formatter, this keeps the interface as consistent as possible, and may help later on if the implementations are unified. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/cat-file.c')
-rw-r--r--builtin/cat-file.c107
1 files changed, 92 insertions, 15 deletions
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 5254fe8956..b43a0c5040 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -114,6 +114,66 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
return 0;
}
+struct expand_data {
+ unsigned char sha1[20];
+ enum object_type type;
+ unsigned long size;
+
+ /*
+ * If mark_query is true, we do not expand anything, but rather
+ * just mark the object_info with items we wish to query.
+ */
+ int mark_query;
+
+ /*
+ * After a mark_query run, this object_info is set up to be
+ * passed to sha1_object_info_extended. It will point to the data
+ * elements above, so you can retrieve the response from there.
+ */
+ struct object_info info;
+};
+
+static int is_atom(const char *atom, const char *s, int slen)
+{
+ int alen = strlen(atom);
+ return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void expand_atom(struct strbuf *sb, const char *atom, int len,
+ void *vdata)
+{
+ struct expand_data *data = vdata;
+
+ if (is_atom("objectname", atom, len)) {
+ if (!data->mark_query)
+ strbuf_addstr(sb, sha1_to_hex(data->sha1));
+ } else if (is_atom("objecttype", atom, len)) {
+ if (!data->mark_query)
+ strbuf_addstr(sb, typename(data->type));
+ } else if (is_atom("objectsize", atom, len)) {
+ if (data->mark_query)
+ data->info.sizep = &data->size;
+ else
+ strbuf_addf(sb, "%lu", data->size);
+ } else
+ die("unknown format element: %.*s", len, atom);
+}
+
+static size_t expand_format(struct strbuf *sb, const char *start, void *data)
+{
+ const char *end;
+
+ if (*start != '(')
+ return 0;
+ end = strchr(start + 1, ')');
+ if (!end)
+ die("format element '%s' does not end in ')'", start);
+
+ expand_atom(sb, start + 1, end - start - 1, data);
+
+ return end - start + 1;
+}
+
static void print_object_or_die(int fd, const unsigned char *sha1,
enum object_type type, unsigned long size)
{
@@ -142,35 +202,37 @@ static void print_object_or_die(int fd, const unsigned char *sha1,
struct batch_options {
int enabled;
int print_contents;
+ const char *format;
};
-static int batch_one_object(const char *obj_name, struct batch_options *opt)
+static int batch_one_object(const char *obj_name, struct batch_options *opt,
+ struct expand_data *data)
{
- unsigned char sha1[20];
- enum object_type type = 0;
- unsigned long size;
+ struct strbuf buf = STRBUF_INIT;
if (!obj_name)
return 1;
- if (get_sha1(obj_name, sha1)) {
+ if (get_sha1(obj_name, data->sha1)) {
printf("%s missing\n", obj_name);
fflush(stdout);
return 0;
}
- type = sha1_object_info(sha1, &size);
- if (type <= 0) {
+ data->type = sha1_object_info_extended(data->sha1, &data->info);
+ if (data->type <= 0) {
printf("%s missing\n", obj_name);
fflush(stdout);
return 0;
}
- printf("%s %s %lu\n", sha1_to_hex(sha1), typename(type), size);
- fflush(stdout);
+ strbuf_expand(&buf, opt->format, expand_format, data);
+ strbuf_addch(&buf, '\n');
+ write_or_die(1, buf.buf, buf.len);
+ strbuf_release(&buf);
if (opt->print_contents) {
- print_object_or_die(1, sha1, type, size);
+ print_object_or_die(1, data->sha1, data->type, data->size);
write_or_die(1, "\n", 1);
}
return 0;
@@ -179,9 +241,23 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt)
static int batch_objects(struct batch_options *opt)
{
struct strbuf buf = STRBUF_INIT;
+ struct expand_data data;
+
+ if (!opt->format)
+ opt->format = "%(objectname) %(objecttype) %(objectsize)";
+
+ /*
+ * Expand once with our special mark_query flag, which will prime the
+ * object_info to be handed to sha1_object_info_extended for each
+ * object.
+ */
+ memset(&data, 0, sizeof(data));
+ data.mark_query = 1;
+ strbuf_expand(&buf, opt->format, expand_format, &data);
+ data.mark_query = 0;
while (strbuf_getline(&buf, stdin, '\n') != EOF) {
- int error = batch_one_object(buf.buf, opt);
+ int error = batch_one_object(buf.buf, opt, &data);
if (error)
return error;
}
@@ -216,6 +292,7 @@ static int batch_option_callback(const struct option *opt,
bo->enabled = 1;
bo->print_contents = !strcmp(opt->long_name, "batch");
+ bo->format = arg;
return 0;
}
@@ -235,12 +312,12 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
OPT_SET_INT('p', NULL, &opt, N_("pretty-print object's content"), 'p'),
OPT_SET_INT(0, "textconv", &opt,
N_("for blob objects, run textconv on object's content"), 'c'),
- { OPTION_CALLBACK, 0, "batch", &batch, NULL,
+ { OPTION_CALLBACK, 0, "batch", &batch, "format",
N_("show info and content of objects fed from the standard input"),
- PARSE_OPT_NOARG, batch_option_callback },
- { OPTION_CALLBACK, 0, "batch-check", &batch, NULL,
+ PARSE_OPT_OPTARG, batch_option_callback },
+ { OPTION_CALLBACK, 0, "batch-check", &batch, "format",
N_("show info about objects fed from the standard input"),
- PARSE_OPT_NOARG, batch_option_callback },
+ PARSE_OPT_OPTARG, batch_option_callback },
OPT_END()
};