{"thread":{"id":"50565","subject":"[PATCH RFC 14/20] cat-file: move print_object_or_die to ref-filter","startedAt":"2019-02-22T16:05:48Z","lastAt":"2019-03-03T09:42:04Z","messageCount":32,"participants":["Olga Telezhnaya","Jeff King","Christian Couder"],"isPatch":true,"patchVersion":1,"patchTotal":20},"messages":[{"id":"369934","messageId":"0102016915f49a66-7e179c2f-b7d4-4d4d-935f-ff1431f86a77-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 14/20] cat-file: move print_object_or_die to ref-filter","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:48Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Move printing function to ref-filter, it is logical because\nwe move all formatting/printing logic to ref-filter.\nIt could be much better if we embed this logic into current\nflows in ref-filter, but it looks like the task for another patch.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 51 ---------------------------------------------\n ref-filter.c       | 52 ++++++++++++++++++++++++++++++++++++++++++++++\n ref-filter.h       |  3 +++\n 3 files changed, 55 insertions(+), 51 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 2066ff1e697e4..6c0cbf71f0f0c 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -226,57 +226,6 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data)\n \treturn end - start + 1;\n }\n \n-static void print_object_or_die(struct expand_data *data, int cmdmode,\n-\t\t\t\tint buffered, const char *rest)\n-{\n-\tconst struct object_id *oid = &data->oid;\n-\tunsigned long size;\n-\tchar *contents;\n-\n-\tassert(data->info.typep);\n-\n-\tif (data->type != OBJ_BLOB) {\n-\t\tenum object_type type;\n-\t\tcontents = read_object_file(oid, &type, &size);\n-\t\tif (!contents)\n-\t\t\tdie(\"object %s disappeared\", oid_to_hex(oid));\n-\t\tif (type != data->type)\n-\t\t\tdie(\"object %s changed type!?\", oid_to_hex(oid));\n-\t\tif (data->info.sizep && size != data->size)\n-\t\t\tdie(\"object %s changed size!?\", oid_to_hex(oid));\n-\n-\t\twrite_or_die(1, contents, size);\n-\t\tfree(contents);\n-\t\treturn;\n-\t}\n-\n-\tif (buffered)\n-\t\tfflush(stdout);\n-\tif (!cmdmode) {\n-\t\tif (stream_blob_to_fd(1, oid, NULL, 0))\n-\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n-\t\treturn;\n-\t}\n-\n-\tif (!rest)\n-\t\tdie(\"missing path for '%s'\", oid_to_hex(oid));\n-\n-\tif (cmdmode == 'w') {\n-\t\tif (filter_object(rest, 0100644, oid, &contents, &size))\n-\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n-\t} else if (cmdmode == 'c') {\n-\t\tenum object_type type;\n-\t\tif (!textconv_object(the_repository, rest, 0100644, oid, 1,\n-\t\t\t\t     &contents, &size))\n-\t\t\tcontents = read_object_file(oid, &type, &size);\n-\t\tif (!contents)\n-\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n-\t} else\n-\t\tBUG(\"invalid cmdmode: %c\", cmdmode);\n-\twrite_or_die(1, contents, size);\n-\tfree(contents);\n-}\n-\n static void batch_object_write(const char *obj_name,\n \t\t\t       struct strbuf *scratch,\n \t\t\t       struct batch_options *opt,\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 65b94ea21e54f..68d9741a56468 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -20,6 +20,7 @@\n #include \"commit-slab.h\"\n #include \"commit-graph.h\"\n #include \"commit-reach.h\"\n+#include \"streaming.h\"\n \n static struct ref_msg {\n \tconst char *gone;\n@@ -2366,3 +2367,54 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \n \treturn 0;\n }\n+\n+void print_object_or_die(struct expand_data *data, int cmdmode,\n+\t\t\t int buffered, const char *rest)\n+{\n+\tconst struct object_id *oid = &data->oid;\n+\tunsigned long size;\n+\tchar *contents;\n+\n+\tassert(data->info.typep);\n+\n+\tif (data->type != OBJ_BLOB) {\n+\t\tenum object_type type;\n+\t\tcontents = read_object_file(oid, &type, &size);\n+\t\tif (!contents)\n+\t\t\tdie(\"object %s disappeared\", oid_to_hex(oid));\n+\t\tif (type != data->type)\n+\t\t\tdie(\"object %s changed type!?\", oid_to_hex(oid));\n+\t\tif (data->info.sizep && size != data->size)\n+\t\t\tdie(\"object %s changed size!?\", oid_to_hex(oid));\n+\n+\t\twrite_or_die(1, contents, size);\n+\t\tfree(contents);\n+\t\treturn;\n+\t}\n+\n+\tif (buffered)\n+\t\tfflush(stdout);\n+\tif (!cmdmode) {\n+\t\tif (stream_blob_to_fd(1, oid, NULL, 0))\n+\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n+\t\treturn;\n+\t}\n+\n+\tif (!rest)\n+\t\tdie(\"missing path for '%s'\", oid_to_hex(oid));\n+\n+\tif (cmdmode == 'w') {\n+\t\tif (filter_object(rest, 0100644, oid, &contents, &size))\n+\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n+\t} else if (cmdmode == 'c') {\n+\t\tenum object_type type;\n+\t\tif (!textconv_object(the_repository, rest, 0100644, oid, 1,\n+\t\t\t\t     &contents, &size))\n+\t\t\tcontents = read_object_file(oid, &type, &size);\n+\t\tif (!contents)\n+\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n+\t} else\n+\t\tBUG(\"invalid cmdmode: %c\", cmdmode);\n+\twrite_or_die(1, contents, size);\n+\tfree(contents);\n+}\ndiff --git a/ref-filter.h b/ref-filter.h\nindex fc61457d4d660..3422f39e64b5b 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -157,4 +157,7 @@ struct ref_array_item *ref_array_push(struct ref_array *array,\n \t\t\t\t      const char *refname,\n \t\t\t\t      const struct object_id *oid);\n \n+void print_object_or_die(struct expand_data *data, int cmdmode,\n+\t\t\t int buffered, const char *rest);\n+\n #endif /*  REF_FILTER_H  */\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369935","messageId":"0102016915f49a72-81347643-bf78-47fe-8cee-d22ce2a18db0-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 18/20] cat-file: get rid of expand_data","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:50Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Clean up cat-file after moving all formatting logic\nto ref-filter.\nWe do not need to use struct expand_data anymore.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 43 +++++++++++++++++++++++--------------------\n ref-filter.c       | 11 ++++++++++-\n ref-filter.h       | 12 ------------\n 3 files changed, 33 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 6fa100d1bea72..ee7557e1e0975 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -28,8 +28,6 @@ struct batch_options {\n };\n \n static const char *force_path;\n-/* global rest will be deleted at the end of this patch */\n-static const char *rest;\n \n static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\tint unknown_type)\n@@ -170,16 +168,19 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n static void batch_object_write(const char *obj_name,\n \t\t\t       struct strbuf *scratch,\n \t\t\t       struct batch_options *opt,\n-\t\t\t       struct expand_data *data)\n+\t\t\t       struct ref_array_item *item)\n {\n \tstruct strbuf err = STRBUF_INIT;\n-\tstruct ref_array_item item = { data->oid };\n-\titem.request_rest = rest;\n-\titem.check_obj = 1;\n+\t/*\n+\t * TODO: get rid of memory leak. The best way is to reuse ref_array\n+\t * in batch_objects and then call ref_array_clear.\n+\t */\n+\titem->value = 0;\n+\titem->check_obj = 1;\n \tstrbuf_reset(scratch);\n \n-\tif (format_ref_array_item(&item, &opt->format, scratch, &err)) {\n-\t\tprintf(\"%s missing\\n\", obj_name ? obj_name : oid_to_hex(&item.oid));\n+\tif (format_ref_array_item(item, &opt->format, scratch, &err)) {\n+\t\tprintf(\"%s missing\\n\", obj_name ? obj_name : oid_to_hex(&item->oid));\n \t\tfflush(stdout);\n \t\treturn;\n \t}\n@@ -189,7 +190,7 @@ static void batch_object_write(const char *obj_name,\n \tstrbuf_release(&err);\n \n \tif (opt->print_contents) {\n-\t\tprint_raw_object_or_die(&item, opt->cmdmode, opt->buffer_output);\n+\t\tprint_raw_object_or_die(item, opt->cmdmode, opt->buffer_output);\n \t\twrite_or_die(1, \"\\n\", 1);\n \t}\n }\n@@ -197,14 +198,14 @@ static void batch_object_write(const char *obj_name,\n static void batch_one_object(const char *obj_name,\n \t\t\t     struct strbuf *scratch,\n \t\t\t     struct batch_options *opt,\n-\t\t\t     struct expand_data *data)\n+\t\t\t     struct ref_array_item *item)\n {\n \tstruct object_context ctx;\n \tint flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;\n \tenum get_oid_result result;\n \n \tresult = get_oid_with_context(the_repository, obj_name,\n-\t\t\t\t      flags, &data->oid, &ctx);\n+\t\t\t\t      flags, &item->oid, &ctx);\n \tif (result != FOUND) {\n \t\tswitch (result) {\n \t\tcase MISSING_OBJECT:\n@@ -242,12 +243,12 @@ static void batch_one_object(const char *obj_name,\n \t\treturn;\n \t}\n \n-\tbatch_object_write(obj_name, scratch, opt, data);\n+\tbatch_object_write(obj_name, scratch, opt, item);\n }\n \n struct object_cb_data {\n \tstruct batch_options *opt;\n-\tstruct expand_data *expand;\n+\tstruct ref_array_item *item;\n \tstruct oidset *seen;\n \tstruct strbuf *scratch;\n };\n@@ -255,8 +256,8 @@ struct object_cb_data {\n static int batch_object_cb(const struct object_id *oid, void *vdata)\n {\n \tstruct object_cb_data *data = vdata;\n-\toidcpy(&data->expand->oid, oid);\n-\tbatch_object_write(NULL, data->scratch, data->opt, data->expand);\n+\toidcpy(&data->item->oid, oid);\n+\tbatch_object_write(NULL, data->scratch, data->opt, data->item);\n \treturn 0;\n }\n \n@@ -306,20 +307,20 @@ static int batch_objects(struct batch_options *opt)\n {\n \tstruct strbuf input = STRBUF_INIT;\n \tstruct strbuf output = STRBUF_INIT;\n-\tstruct expand_data data;\n \tint save_warning;\n \tint retval = 0;\n \tint is_rest = strstr(opt->format.format, \"%(rest)\") != NULL || opt->cmdmode;\n-\tmemset(&data, 0, sizeof(data));\n \n \tif (opt->all_objects) {\n \t\tstruct object_cb_data cb;\n+\t\tstruct ref_array_item item;\n+\t\tmemset(&item, 0, sizeof(item));\n \n \t\tif (repository_format_partial_clone)\n \t\t\twarning(\"This repository has extensions.partialClone set. Some objects may not be loaded.\");\n \n \t\tcb.opt = opt;\n-\t\tcb.expand = &data;\n+\t\tcb.item = &item;\n \t\tcb.scratch = &output;\n \n \t\tif (opt->unordered) {\n@@ -358,6 +359,8 @@ static int batch_objects(struct batch_options *opt)\n \twarn_on_object_refname_ambiguity = 0;\n \n \twhile (strbuf_getline(&input, stdin) != EOF) {\n+\t\tstruct ref_array_item item;\n+\t\tmemset(&item, 0, sizeof(item));\n \t\tif (is_rest) {\n \t\t\t/*\n \t\t\t * Split at first whitespace, tying off the beginning\n@@ -369,10 +372,10 @@ static int batch_objects(struct batch_options *opt)\n \t\t\t\twhile (*p && strchr(\" \\t\", *p))\n \t\t\t\t\t*p++ = '\\0';\n \t\t\t}\n-\t\t\trest = p;\n+\t\t\titem.request_rest = p;\n \t\t}\n \n-\t\tbatch_one_object(input.buf, &output, opt, &data);\n+\t\tbatch_one_object(input.buf, &output, opt, &item);\n \t}\n \n \tstrbuf_release(&input);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 45d163246e3f3..3f9bd2fc6a76a 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -65,7 +65,16 @@ struct refname_atom {\n \tint lstrip, rstrip;\n };\n \n-static struct expand_data oi, oi_deref;\n+static struct expand_data {\n+\tstruct object_id oid;\n+\tenum object_type type;\n+\tunsigned long size;\n+\toff_t disk_size;\n+\tstruct object_id delta_base_oid;\n+\tvoid *content;\n+\n+\tstruct object_info info;\n+} oi, oi_deref;\n \n /*\n  * An atom is a valid field atom listed below, possibly prefixed with\ndiff --git a/ref-filter.h b/ref-filter.h\nindex e8cd97a49632c..237eed9818949 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -5,7 +5,6 @@\n #include \"refs.h\"\n #include \"commit.h\"\n #include \"parse-options.h\"\n-#include \"object-store.h\"\n \n /* Quoting styles */\n #define QUOTE_NONE 0\n@@ -75,17 +74,6 @@ struct ref_filter {\n \t\tverbose;\n };\n \n-struct expand_data {\n-\tstruct object_id oid;\n-\tenum object_type type;\n-\tunsigned long size;\n-\toff_t disk_size;\n-\tstruct object_id delta_base_oid;\n-\tvoid *content;\n-\n-\tstruct object_info info;\n-};\n-\n struct ref_format {\n \t/*\n \t * Set these to define the format; make sure you call\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369936","messageId":"0102016915f49a54-e28b7a40-d51c-4dd4-85a3-0eea83d4f0cb-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 08/20] cat-file: remove rest from expand_data","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:51Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Get rid of rest field in struct expand_data.\nexpand_data may be global further as we use it in ref-filter also,\nso we need to remove cat-file specific fields from it.\n\nAll globals that I add through this patch will be deleted in the end,\nso treat it just as the middle step.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 20 ++++++++++----------\n 1 file changed, 10 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex f6470380f55b3..e52646c0e6b5b 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -29,9 +29,10 @@ struct batch_options {\n };\n \n static const char *force_path;\n-/* Next 2 vars will be deleted at the end of this patch */\n+/* Next 3 vars will be deleted at the end of this patch */\n static int mark_query;\n static int skip_object_info;\n+static const char *rest;\n \n static int filter_object(const char *path, unsigned mode,\n \t\t\t const struct object_id *oid,\n@@ -197,7 +198,6 @@ struct expand_data {\n \tenum object_type type;\n \tunsigned long size;\n \toff_t disk_size;\n-\tconst char *rest;\n \tstruct object_id delta_base_oid;\n \n \t/*\n@@ -238,8 +238,8 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,\n \t\telse\n \t\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)data->disk_size);\n \t} else if (is_atom(\"rest\", atom, len)) {\n-\t\tif (data->rest)\n-\t\t\tstrbuf_addstr(sb, data->rest);\n+\t\tif (rest)\n+\t\t\tstrbuf_addstr(sb, rest);\n \t} else if (is_atom(\"deltabase\", atom, len)) {\n \t\tif (mark_query)\n \t\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n@@ -287,25 +287,25 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n \t\t\tchar *contents;\n \t\t\tunsigned long size;\n \n-\t\t\tif (!data->rest)\n+\t\t\tif (!rest)\n \t\t\t\tdie(\"missing path for '%s'\", oid_to_hex(oid));\n \n \t\t\tif (opt->cmdmode == 'w') {\n-\t\t\t\tif (filter_object(data->rest, 0100644, oid,\n+\t\t\t\tif (filter_object(rest, 0100644, oid,\n \t\t\t\t\t\t  &contents, &size))\n \t\t\t\t\tdie(\"could not convert '%s' %s\",\n-\t\t\t\t\t    oid_to_hex(oid), data->rest);\n+\t\t\t\t\t    oid_to_hex(oid), rest);\n \t\t\t} else if (opt->cmdmode == 'c') {\n \t\t\t\tenum object_type type;\n \t\t\t\tif (!textconv_object(the_repository,\n-\t\t\t\t\t\t     data->rest, 0100644, oid,\n+\t\t\t\t\t\t     rest, 0100644, oid,\n \t\t\t\t\t\t     1, &contents, &size))\n \t\t\t\t\tcontents = read_object_file(oid,\n \t\t\t\t\t\t\t\t    &type,\n \t\t\t\t\t\t\t\t    &size);\n \t\t\t\tif (!contents)\n \t\t\t\t\tdie(\"could not convert '%s' %s\",\n-\t\t\t\t\t    oid_to_hex(oid), data->rest);\n+\t\t\t\t\t    oid_to_hex(oid), rest);\n \t\t\t} else\n \t\t\t\tBUG(\"invalid cmdmode: %c\", opt->cmdmode);\n \t\t\tbatch_write(opt, contents, size);\n@@ -555,7 +555,7 @@ static int batch_objects(struct batch_options *opt)\n \t\t\t\twhile (*p && strchr(\" \\t\", *p))\n \t\t\t\t\t*p++ = '\\0';\n \t\t\t}\n-\t\t\tdata.rest = p;\n+\t\t\trest = p;\n \t\t}\n \n \t\tbatch_one_object(input.buf, &output, opt, &data);\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369937","messageId":"0102016915f49a75-65264938-9d50-4cf0-a55a-c5b7892c15b0-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 19/20] cat-file: tests for new atoms added","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:52Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add some tests for new formatting atoms from ref-filter.\nSome of new atoms are supported automatically,\nsome of them are expanded into empty string\n(because they are useless for some types of objects).\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n t/t1006-cat-file.sh | 48 +++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 48 insertions(+)\n\ndiff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh\nindex 43c4be1e5ef55..3c848f2773bbb 100755\n--- a/t/t1006-cat-file.sh\n+++ b/t/t1006-cat-file.sh\n@@ -20,6 +20,19 @@ maybe_remove_timestamp () {\n     fi\n }\n \n+test_atom () {\n+    name=$1\n+    sha1=$2\n+    atoms=$3\n+    expected=$4\n+\n+    test_expect_success \"$name\" '\n+\techo \"$expected\" >expect &&\n+\techo $sha1 | git cat-file --batch-check=\"$atoms\" >actual &&\n+\ttest_cmp expect actual\n+    '\n+}\n+\n run_tests () {\n     type=$1\n     sha1=$2\n@@ -119,6 +132,13 @@ $content\"\n \tmaybe_remove_timestamp \"$(cat actual.full)\" $no_ts >actual &&\n \ttest_cmp expect actual\n     '\n+\n+    for atom in refname parent body trailers upstream push symref flag\n+    do\n+\ttest_atom \"Check %($atom) gives empty output\" \"$sha1\" \"%($atom)\" \"\"\n+    done\n+\n+    test_atom \"Check %(HEAD) gives only one space as output\" \"$sha1\" '%(HEAD)' ' '\n }\n \n hello_content=\"Hello World\"\n@@ -140,6 +160,12 @@ test_expect_success '--batch-check without %(rest) considers whole line' '\n \ttest_cmp expect actual\n '\n \n+shortname=`echo $hello_sha1 | sed 's/^.\\{0\\}\\(.\\{7\\}\\).*/\\1/'`\n+test_atom 'Check format option %(objectname:short) works' \"$hello_sha1\" '%(objectname:short)' \"$shortname\"\n+\n+test_atom 'Check format option %(align) is not broken' \\\n+    \"$hello_sha1\" \"%(align:8)%(objecttype)%(end)%(objectname)\" \"blob    $hello_sha1\"\n+\n test_oid_init\n \n tree_sha1=$(git write-tree)\n@@ -159,6 +185,17 @@ $commit_message\"\n \n run_tests 'commit' $commit_sha1 $commit_size \"$commit_content\" \"$commit_content\" 1\n \n+test_atom \"Check format option %(if) is not broken\" \"$commit_sha1\" \\\n+    \"%(if)%(author)%(then)%(objectname)%(end)\" \"$commit_sha1\"\n+test_atom \"Check %(tree) works for commit\" \"$commit_sha1\" \"%(tree)\" \"$tree_sha1\"\n+test_atom \"Check %(numparent) works for commit\" \"$commit_sha1\" \"%(numparent)\" \"0\"\n+test_atom \"Check %(authorname) works for commit\" \"$commit_sha1\" \"%(authorname)\" \"$GIT_AUTHOR_NAME\"\n+test_atom \"Check %(authoremail) works for commit\" \"$commit_sha1\" \"%(authoremail)\" \"<$GIT_AUTHOR_EMAIL>\"\n+test_atom \"Check %(committername) works for commit\" \"$commit_sha1\" \"%(committername)\" \"$GIT_COMMITTER_NAME\"\n+test_atom \"Check %(committeremail) works for commit\" \"$commit_sha1\" \"%(committeremail)\" \"<$GIT_COMMITTER_EMAIL>\"\n+test_atom \"Check %(subject) works for commit\" \"$commit_sha1\" \"%(subject)\" \"$commit_message\"\n+test_atom \"Check %(contents) works for commit\" \"$commit_sha1\" \"%(contents)\" \"$commit_message\"\n+\n tag_header_without_timestamp=\"object $hello_sha1\n type blob\n tag hellotag\n@@ -173,6 +210,17 @@ tag_size=$(strlen \"$tag_content\")\n \n run_tests 'tag' $tag_sha1 $tag_size \"$tag_content\" \"$tag_content\" 1\n \n+test_atom \"Check %(object) works for tag\" \"$tag_sha1\" \"%(object)\" \"$hello_sha1\"\n+test_atom \"Check %(type) works for tag\" \"$tag_sha1\" \"%(type)\" \"blob\"\n+test_atom \"Check %(tag) works for tag\" \"$tag_sha1\" \"%(tag)\" \"hellotag\"\n+test_atom \"Check %(taggername) works for tag\" \"$tag_sha1\" \"%(taggername)\" \"$GIT_COMMITTER_NAME\"\n+test_atom \"Check %(taggeremail) works for tag\" \"$tag_sha1\" \"%(taggeremail)\" \"<$GIT_COMMITTER_EMAIL>\"\n+test_atom \"Check %(subject) works for tag\" \"$tag_sha1\" \"%(subject)\" \"$tag_description\"\n+test_atom \"Check %(contents) works for tag\" \"$tag_sha1\" \"%(contents)\" \"$tag_description\"\n+\n+test_atom \"Check %(color) gives no additional output\" \"$sha1\" \\\n+    \"%(objectname) %(color:green) %(objecttype)\" \"$sha1  $type\"\n+\n test_expect_success \\\n     \"Reach a blob from a tag pointing to it\" \\\n     \"test '$hello_content' = \\\"\\$(git cat-file blob $tag_sha1)\\\"\"\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369939","messageId":"0102016915f49a72-d28a8c0c-7594-4330-8c1c-e497622a8fd9-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 17/20] cat-file: reuse ref-filter formatting logic","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:53Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Start using general ref-filter formatting logic in cat-file.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 111 ++++++++-------------------------------------\n ref-filter.c       |  39 +++++++++++-----\n ref-filter.h       |   4 +-\n 3 files changed, 49 insertions(+), 105 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 6c0cbf71f0f0c..6fa100d1bea72 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -28,9 +28,7 @@ struct batch_options {\n };\n \n static const char *force_path;\n-/* Next 3 vars will be deleted at the end of this patch */\n-static int mark_query;\n-static int skip_object_info;\n+/* global rest will be deleted at the end of this patch */\n static const char *rest;\n \n static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n@@ -169,84 +167,29 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \treturn 0;\n }\n \n-static int is_atom(const char *atom, const char *s, int slen)\n-{\n-\tint alen = strlen(atom);\n-\treturn alen == slen && !memcmp(atom, s, alen);\n-}\n-\n-static void expand_atom(struct strbuf *sb, const char *atom, int len,\n-\t\t\tvoid *vdata)\n-{\n-\tstruct expand_data *data = vdata;\n-\n-\tif (is_atom(\"objectname\", atom, len)) {\n-\t\tif (!mark_query)\n-\t\t\tstrbuf_addstr(sb, oid_to_hex(&data->oid));\n-\t} else if (is_atom(\"objecttype\", atom, len)) {\n-\t\tif (mark_query)\n-\t\t\tdata->info.typep = &data->type;\n-\t\telse\n-\t\t\tstrbuf_addstr(sb, type_name(data->type));\n-\t} else if (is_atom(\"objectsize\", atom, len)) {\n-\t\tif (mark_query)\n-\t\t\tdata->info.sizep = &data->size;\n-\t\telse\n-\t\t\tstrbuf_addf(sb, \"%\"PRIuMAX , (uintmax_t)data->size);\n-\t} else if (is_atom(\"objectsize:disk\", atom, len)) {\n-\t\tif (mark_query)\n-\t\t\tdata->info.disk_sizep = &data->disk_size;\n-\t\telse\n-\t\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)data->disk_size);\n-\t} else if (is_atom(\"rest\", atom, len)) {\n-\t\tif (rest)\n-\t\t\tstrbuf_addstr(sb, rest);\n-\t} else if (is_atom(\"deltabase\", atom, len)) {\n-\t\tif (mark_query)\n-\t\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n-\t\telse\n-\t\t\tstrbuf_addstr(sb,\n-\t\t\t\t      oid_to_hex(&data->delta_base_oid));\n-\t} else\n-\t\tdie(\"unknown format element: %.*s\", len, atom);\n-}\n-\n-static size_t expand_format(struct strbuf *sb, const char *start, void *data)\n-{\n-\tconst char *end;\n-\n-\tif (*start != '(')\n-\t\treturn 0;\n-\tend = strchr(start + 1, ')');\n-\tif (!end)\n-\t\tdie(\"format element '%s' does not end in ')'\", start);\n-\n-\texpand_atom(sb, start + 1, end - start - 1, data);\n-\n-\treturn end - start + 1;\n-}\n-\n static void batch_object_write(const char *obj_name,\n \t\t\t       struct strbuf *scratch,\n \t\t\t       struct batch_options *opt,\n \t\t\t       struct expand_data *data)\n {\n-\tif (!skip_object_info &&\n-\t    oid_object_info_extended(the_repository, &data->oid, &data->info,\n-\t\t\t\t     OBJECT_INFO_LOOKUP_REPLACE) < 0) {\n-\t\tprintf(\"%s missing\\n\",\n-\t\t       obj_name ? obj_name : oid_to_hex(&data->oid));\n+\tstruct strbuf err = STRBUF_INIT;\n+\tstruct ref_array_item item = { data->oid };\n+\titem.request_rest = rest;\n+\titem.check_obj = 1;\n+\tstrbuf_reset(scratch);\n+\n+\tif (format_ref_array_item(&item, &opt->format, scratch, &err)) {\n+\t\tprintf(\"%s missing\\n\", obj_name ? obj_name : oid_to_hex(&item.oid));\n \t\tfflush(stdout);\n \t\treturn;\n \t}\n \n-\tstrbuf_reset(scratch);\n-\tstrbuf_expand(scratch, opt->format.format, expand_format, data);\n \tstrbuf_addch(scratch, '\\n');\n \twrite_or_die(1, scratch->buf, scratch->len);\n+\tstrbuf_release(&err);\n \n \tif (opt->print_contents) {\n-\t\tprint_object_or_die(data, opt->cmdmode, opt->buffer_output, rest);\n+\t\tprint_raw_object_or_die(&item, opt->cmdmode, opt->buffer_output);\n \t\twrite_or_die(1, \"\\n\", 1);\n \t}\n }\n@@ -367,30 +310,7 @@ static int batch_objects(struct batch_options *opt)\n \tint save_warning;\n \tint retval = 0;\n \tint is_rest = strstr(opt->format.format, \"%(rest)\") != NULL || opt->cmdmode;\n-\n-\t/*\n-\t * Expand once with our special mark_query flag, which will prime the\n-\t * object_info to be handed to oid_object_info_extended for each\n-\t * object.\n-\t */\n \tmemset(&data, 0, sizeof(data));\n-\tmark_query = 1;\n-\tstrbuf_expand(&output, opt->format.format, expand_format, &data);\n-\tmark_query = 0;\n-\tstrbuf_release(&output);\n-\n-\tif (opt->all_objects) {\n-\t\tstruct object_info empty = OBJECT_INFO_INIT;\n-\t\tif (!memcmp(&data.info, &empty, sizeof(empty)))\n-\t\t\tskip_object_info = 1;\n-\t}\n-\n-\t/*\n-\t * If we are printing out the object, then always fill in the type,\n-\t * since we will want to decide whether or not to stream.\n-\t */\n-\tif (opt->print_contents)\n-\t\tdata.info.typep = &data.type;\n \n \tif (opt->all_objects) {\n \t\tstruct object_cb_data cb;\n@@ -581,6 +501,15 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \n \tif (!batch.format.format)\n \t\tbatch.format.format = \"%(objectname) %(objecttype) %(objectsize)\";\n+\tif (batch.print_contents) {\n+\t\tconst char *contents = \"%(raw)\";\n+\t\tchar *format = (char *)calloc(strlen(batch.format.format) + strlen(contents) + 1, 1);\n+\t\tmemcpy(format, batch.format.format, strlen(batch.format.format));\n+\t\tmemcpy(format + strlen(format), contents, strlen(contents));\n+\t\tbatch.format.format = format;\n+\t}\n+\tif (verify_ref_format(&batch.format))\n+\t\tusage_with_options(cat_file_usage, options);\n \n \tif (batch.enabled)\n \t\treturn batch_objects(&batch);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex bb963a4110fb2..45d163246e3f3 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2231,6 +2231,7 @@ int format_ref_array_item(struct ref_array_item *info,\n {\n \tconst char *cp, *sp, *ep;\n \tstruct ref_formatting_state state = REF_FORMATTING_STATE_INIT;\n+\tstruct object_info empty = OBJECT_INFO_INIT;\n \n \tstate.quote_style = format->quote_style;\n \tpush_stack_element(&state.stack);\n@@ -2253,6 +2254,11 @@ int format_ref_array_item(struct ref_array_item *info,\n \t\tsp = cp + strlen(cp);\n \t\tappend_literal(cp, sp, &state);\n \t}\n+\tif (info->check_obj &&\n+\t    oid_object_info_extended(the_repository, &info->oid, &empty,\n+\t\t\t\t     OBJECT_INFO_LOOKUP_REPLACE))\n+\t\treturn strbuf_addf_ret(error_buf, -1, _(\"%s missing\\n\"),\n+\t\t\t\t       oid_to_hex(&info->oid));\n \tif (format->need_color_reset_at_eol) {\n \t\tstruct atom_value resetv;\n \t\tresetv.s = GIT_COLOR_RESET;\n@@ -2381,23 +2387,32 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \treturn 0;\n }\n \n-void print_object_or_die(struct expand_data *data, int cmdmode,\n-\t\t\t int buffered, const char *rest)\n+/*\n+ * TODO: add support of %(*raw). Need to switch between oi and oi_deref for that.\n+ * TODO: split logic and printing (as it is done in format_ref_array_item and\n+ * show_ref_array_item).\n+ * TODO: rewrite print_object_or_die so that it will reuse result of general\n+ * oid_object_info_extended call.\n+ * TODO: embed this function into general ref_filter flow, make it static.\n+ * That will allow other ref-filter users to print raw file\n+ * (now only cat_file can use it).\n+ */\n+void print_raw_object_or_die(struct ref_array_item *item, int cmdmode, int buffered)\n {\n-\tconst struct object_id *oid = &data->oid;\n+\tconst struct object_id *oid = &oi.oid;\n \tunsigned long size;\n \tchar *contents;\n \n-\tassert(data->info.typep);\n+\tassert(oi.info.typep);\n \n-\tif (data->type != OBJ_BLOB) {\n+\tif (oi.type != OBJ_BLOB) {\n \t\tenum object_type type;\n \t\tcontents = read_object_file(oid, &type, &size);\n \t\tif (!contents)\n \t\t\tdie(\"object %s disappeared\", oid_to_hex(oid));\n-\t\tif (type != data->type)\n+\t\tif (type != oi.type)\n \t\t\tdie(\"object %s changed type!?\", oid_to_hex(oid));\n-\t\tif (data->info.sizep && size != data->size)\n+\t\tif (oi.info.sizep && size != oi.size)\n \t\t\tdie(\"object %s changed size!?\", oid_to_hex(oid));\n \n \t\twrite_or_die(1, contents, size);\n@@ -2413,19 +2428,19 @@ void print_object_or_die(struct expand_data *data, int cmdmode,\n \t\treturn;\n \t}\n \n-\tif (!rest)\n+\tif (!item->request_rest)\n \t\tdie(\"missing path for '%s'\", oid_to_hex(oid));\n \n \tif (cmdmode == 'w') {\n-\t\tif (filter_object(rest, 0100644, oid, &contents, &size))\n-\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n+\t\tif (filter_object(item->request_rest, 0100644, oid, &contents, &size))\n+\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), item->request_rest);\n \t} else if (cmdmode == 'c') {\n \t\tenum object_type type;\n-\t\tif (!textconv_object(the_repository, rest, 0100644, oid, 1,\n+\t\tif (!textconv_object(the_repository, item->request_rest, 0100644, oid, 1,\n \t\t\t\t     &contents, &size))\n \t\t\tcontents = read_object_file(oid, &type, &size);\n \t\tif (!contents)\n-\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n+\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), item->request_rest);\n \t} else\n \t\tBUG(\"invalid cmdmode: %c\", cmdmode);\n \twrite_or_die(1, contents, size);\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 3422f39e64b5b..e8cd97a49632c 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -42,6 +42,7 @@ struct ref_array_item {\n \tstruct commit *commit;\n \tstruct atom_value *value;\n \tconst char *request_rest;\n+\tint check_obj;\n \tchar refname[FLEX_ARRAY];\n };\n \n@@ -157,7 +158,6 @@ struct ref_array_item *ref_array_push(struct ref_array *array,\n \t\t\t\t      const char *refname,\n \t\t\t\t      const struct object_id *oid);\n \n-void print_object_or_die(struct expand_data *data, int cmdmode,\n-\t\t\t int buffered, const char *rest);\n+void print_raw_object_or_die(struct ref_array_item *item, int cmdmode, int buffered);\n \n #endif /*  REF_FILTER_H  */\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369938","messageId":"0102016915f49a6b-667faefc-a0bc-4243-b846-b78076936a74-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 16/20] for-each-ref: tests for new atom %(raw) added","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:54Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add tests for new formatting atom %(raw).\nWe need this atom for cat-file command.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n t/t6300-for-each-ref.sh | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh\nindex fb361369a037c..6a5626d537f35 100755\n--- a/t/t6300-for-each-ref.sh\n+++ b/t/t6300-for-each-ref.sh\n@@ -328,6 +328,12 @@ test_expect_success 'Check format %(rest) gives empty output ' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'Check format %(raw) gives empty output ' '\n+\techo >expected &&\n+\tgit for-each-ref --format=\"%(raw)\" refs/heads >actual &&\n+\ttest_cmp expected actual\n+'\n+\n cat >expected <<\\EOF\n refs/heads/master\n refs/remotes/origin/master\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369940","messageId":"0102016915f49a88-27e5f4a8-225c-4d1b-8baf-9027c654169a-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 20/20] cat-file: update docs","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:55Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Update the docs for cat-file command. Some new formatting atoms added\nbecause of reusing ref-filter code.\n\nActually, %(rest) is supported for all ref-filter commands, but it\nhas the meaning only for cat-file, that's why I decided to leave it here.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n Documentation/git-cat-file.txt | 38 ++--------------------------------\n 1 file changed, 2 insertions(+), 36 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt\nindex 8eca671b8278c..b32fcde802ca1 100644\n--- a/Documentation/git-cat-file.txt\n+++ b/Documentation/git-cat-file.txt\n@@ -195,28 +195,8 @@ the whole line is considered as an object, as if it were fed to\n linkgit:git-rev-parse[1].\n \n You can specify the information shown for each object by using a custom\n-`<format>`. The `<format>` is copied literally to stdout for each\n-object, with placeholders of the form `%(atom)` expanded, followed by a\n-newline. The available atoms are:\n-\n-`objectname`::\n-\tThe 40-hex object name of the object.\n-\n-`objecttype`::\n-\tThe type of the object (the same as `cat-file -t` reports).\n-\n-`objectsize`::\n-\tThe size, in bytes, of the object (the same as `cat-file -s`\n-\treports).\n-\n-`objectsize:disk`::\n-\tThe size, in bytes, that the object takes up on disk. See the\n-\tnote about on-disk sizes in the `CAVEATS` section below.\n-\n-`deltabase`::\n-\tIf the object is stored as a delta on-disk, this expands to the\n-\t40-hex sha1 of the delta base object. Otherwise, expands to the\n-\tnull sha1 (40 zeroes). See `CAVEATS` below.\n+`<format>`. The format is the same as that of linkgit:git-for-each-ref[1],\n+with one additional option:\n \n `rest`::\n \tIf this atom is used in the output string, input lines are split\n@@ -300,20 +280,6 @@ notdir SP <size> LF\n is printed when, during symlink resolution, a file is used as a\n directory name.\n \n-CAVEATS\n--------\n-\n-Note that the sizes of objects on disk are reported accurately, but care\n-should be taken in drawing conclusions about which refs or objects are\n-responsible for disk usage. The size of a packed non-delta object may be\n-much larger than the size of objects which delta against it, but the\n-choice of which object is the base and which is the delta is arbitrary\n-and is subject to change during a repack.\n-\n-Note also that multiple copies of an object may be present in the object\n-database; in this case, it is undefined which copy's size or delta base\n-will be reported.\n-\n GIT\n ---\n Part of the linkgit:git[1] suite\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369942","messageId":"0102016915f49a4f-f02a6509-a3ba-41b0-b768-3d8ba116f526-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 06/20] cat-file: remove mark_query from expand_data","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:57Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Get rid of mark_query field in struct expand_data.\nexpand_data may be global further as we use it in ref-filter also,\nso we need to remove cat-file specific fields from it.\n\nAll globals that I add through this patch will be deleted in the end,\nso treat it just as the middle step.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 22 +++++++++-------------\n 1 file changed, 9 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 60f3839b06f8c..9bcb02fad1f0d 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -29,6 +29,8 @@ struct batch_options {\n };\n \n static const char *force_path;\n+/* Will be deleted at the end of this patch */\n+static int mark_query;\n \n static int filter_object(const char *path, unsigned mode,\n \t\t\t const struct object_id *oid,\n@@ -197,12 +199,6 @@ struct expand_data {\n \tconst char *rest;\n \tstruct object_id delta_base_oid;\n \n-\t/*\n-\t * If mark_query is true, we do not expand anything, but rather\n-\t * just mark the object_info with items we wish to query.\n-\t */\n-\tint mark_query;\n-\n \t/*\n \t * After a mark_query run, this object_info is set up to be\n \t * passed to oid_object_info_extended. It will point to the data\n@@ -230,20 +226,20 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,\n \tstruct expand_data *data = vdata;\n \n \tif (is_atom(\"objectname\", atom, len)) {\n-\t\tif (!data->mark_query)\n+\t\tif (!mark_query)\n \t\t\tstrbuf_addstr(sb, oid_to_hex(&data->oid));\n \t} else if (is_atom(\"objecttype\", atom, len)) {\n-\t\tif (data->mark_query)\n+\t\tif (mark_query)\n \t\t\tdata->info.typep = &data->type;\n \t\telse\n \t\t\tstrbuf_addstr(sb, type_name(data->type));\n \t} else if (is_atom(\"objectsize\", atom, len)) {\n-\t\tif (data->mark_query)\n+\t\tif (mark_query)\n \t\t\tdata->info.sizep = &data->size;\n \t\telse\n \t\t\tstrbuf_addf(sb, \"%\"PRIuMAX , (uintmax_t)data->size);\n \t} else if (is_atom(\"objectsize:disk\", atom, len)) {\n-\t\tif (data->mark_query)\n+\t\tif (mark_query)\n \t\t\tdata->info.disk_sizep = &data->disk_size;\n \t\telse\n \t\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)data->disk_size);\n@@ -251,7 +247,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,\n \t\tif (data->rest)\n \t\t\tstrbuf_addstr(sb, data->rest);\n \t} else if (is_atom(\"deltabase\", atom, len)) {\n-\t\tif (data->mark_query)\n+\t\tif (mark_query)\n \t\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n \t\telse\n \t\t\tstrbuf_addstr(sb,\n@@ -490,9 +486,9 @@ static int batch_objects(struct batch_options *opt)\n \t * object.\n \t */\n \tmemset(&data, 0, sizeof(data));\n-\tdata.mark_query = 1;\n+\tmark_query = 1;\n \tstrbuf_expand(&output, opt->format.format, expand_format, &data);\n-\tdata.mark_query = 0;\n+\tmark_query = 0;\n \tstrbuf_release(&output);\n \n \tif (opt->all_objects) {\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369941","messageId":"0102016915f49a49-6f817c1d-5b1c-47ac-98c3-18a124a733eb-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 03/20] ref-filter: add rest formatting option","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:58Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add rest option that allows to add string into ref_array_item\nand then put it into specific place of the output.\nWe are using it now in cat-file command: user could put anything\nin the input after objectname, and it will appear in the output\nin place of %(rest).\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n ref-filter.c | 4 ++++\n ref-filter.h | 1 +\n 2 files changed, 5 insertions(+)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 736e1f9cc38fc..46bf89b3330de 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -485,6 +485,7 @@ static struct {\n \t{ \"if\", SOURCE_NONE, FIELD_STR, if_atom_parser },\n \t{ \"then\", SOURCE_NONE },\n \t{ \"else\", SOURCE_NONE },\n+\t{ \"rest\", SOURCE_NONE },\n };\n \n #define REF_FORMATTING_STATE_INIT  { 0, NULL }\n@@ -1623,6 +1624,9 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\telse\n \t\t\t\tv->s = xstrdup(\" \");\n \t\t\tcontinue;\n+\t\t} else if (starts_with(name, \"rest\")) {\n+\t\t\tv->s = xstrdup(ref->request_rest ? ref->request_rest : \"\");\n+\t\t\tcontinue;\n \t\t} else if (starts_with(name, \"align\")) {\n \t\t\tv->handler = align_atom_handler;\n \t\t\tv->s = xstrdup(\"\");\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 4d7d36e9f522d..aaeda9f324f5c 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -40,6 +40,7 @@ struct ref_array_item {\n \tconst char *symref;\n \tstruct commit *commit;\n \tstruct atom_value *value;\n+\tconst char *request_rest;\n \tchar refname[FLEX_ARRAY];\n };\n \n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369943","messageId":"0102016915f49a66-0b8bf78d-6879-41da-b5e6-de6e7edbe71a-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 13/20] cat-file: rewrite print_object_or_die","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:05:59Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"In the next commit I will move function print_object_or_die\nto ref-filter, and I decided to rewrite it a little so that it\nbecomes much more flatten and a little bit shorter.\nI also changed input parameters, it allows me to move it\nto ref-filter, ref-filter knows nothing about batch_options.\n\nThe logic of the function remains the same.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 72 +++++++++++++++++++++-------------------------\n 1 file changed, 33 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex a4e56762f9e56..2066ff1e697e4 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -226,50 +226,17 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data)\n \treturn end - start + 1;\n }\n \n-static void print_object_or_die(struct batch_options *opt, struct expand_data *data)\n+static void print_object_or_die(struct expand_data *data, int cmdmode,\n+\t\t\t\tint buffered, const char *rest)\n {\n \tconst struct object_id *oid = &data->oid;\n+\tunsigned long size;\n+\tchar *contents;\n \n \tassert(data->info.typep);\n \n-\tif (data->type == OBJ_BLOB) {\n-\t\tif (opt->buffer_output)\n-\t\t\tfflush(stdout);\n-\t\tif (opt->cmdmode) {\n-\t\t\tchar *contents;\n-\t\t\tunsigned long size;\n-\n-\t\t\tif (!rest)\n-\t\t\t\tdie(\"missing path for '%s'\", oid_to_hex(oid));\n-\n-\t\t\tif (opt->cmdmode == 'w') {\n-\t\t\t\tif (filter_object(rest, 0100644, oid,\n-\t\t\t\t\t\t  &contents, &size))\n-\t\t\t\t\tdie(\"could not convert '%s' %s\",\n-\t\t\t\t\t    oid_to_hex(oid), rest);\n-\t\t\t} else if (opt->cmdmode == 'c') {\n-\t\t\t\tenum object_type type;\n-\t\t\t\tif (!textconv_object(the_repository,\n-\t\t\t\t\t\t     rest, 0100644, oid,\n-\t\t\t\t\t\t     1, &contents, &size))\n-\t\t\t\t\tcontents = read_object_file(oid,\n-\t\t\t\t\t\t\t\t    &type,\n-\t\t\t\t\t\t\t\t    &size);\n-\t\t\t\tif (!contents)\n-\t\t\t\t\tdie(\"could not convert '%s' %s\",\n-\t\t\t\t\t    oid_to_hex(oid), rest);\n-\t\t\t} else\n-\t\t\t\tBUG(\"invalid cmdmode: %c\", opt->cmdmode);\n-\t\t\twrite_or_die(1, contents, size);\n-\t\t\tfree(contents);\n-\t\t} else if (stream_blob_to_fd(1, oid, NULL, 0))\n-\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n-\t}\n-\telse {\n+\tif (data->type != OBJ_BLOB) {\n \t\tenum object_type type;\n-\t\tunsigned long size;\n-\t\tvoid *contents;\n-\n \t\tcontents = read_object_file(oid, &type, &size);\n \t\tif (!contents)\n \t\t\tdie(\"object %s disappeared\", oid_to_hex(oid));\n@@ -280,7 +247,34 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n \n \t\twrite_or_die(1, contents, size);\n \t\tfree(contents);\n+\t\treturn;\n+\t}\n+\n+\tif (buffered)\n+\t\tfflush(stdout);\n+\tif (!cmdmode) {\n+\t\tif (stream_blob_to_fd(1, oid, NULL, 0))\n+\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n+\t\treturn;\n \t}\n+\n+\tif (!rest)\n+\t\tdie(\"missing path for '%s'\", oid_to_hex(oid));\n+\n+\tif (cmdmode == 'w') {\n+\t\tif (filter_object(rest, 0100644, oid, &contents, &size))\n+\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n+\t} else if (cmdmode == 'c') {\n+\t\tenum object_type type;\n+\t\tif (!textconv_object(the_repository, rest, 0100644, oid, 1,\n+\t\t\t\t     &contents, &size))\n+\t\t\tcontents = read_object_file(oid, &type, &size);\n+\t\tif (!contents)\n+\t\t\tdie(\"could not convert '%s' %s\", oid_to_hex(oid), rest);\n+\t} else\n+\t\tBUG(\"invalid cmdmode: %c\", cmdmode);\n+\twrite_or_die(1, contents, size);\n+\tfree(contents);\n }\n \n static void batch_object_write(const char *obj_name,\n@@ -303,7 +297,7 @@ static void batch_object_write(const char *obj_name,\n \twrite_or_die(1, scratch->buf, scratch->len);\n \n \tif (opt->print_contents) {\n-\t\tprint_object_or_die(opt, data);\n+\t\tprint_object_or_die(data, opt->cmdmode, opt->buffer_output, rest);\n \t\twrite_or_die(1, \"\\n\", 1);\n \t}\n }\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369944","messageId":"0102016915f49a58-dc12f07d-00e6-42be-812b-3072d33910d3-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 09/20] ref-filter: make expand_data global","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:02Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Put struct expand_data into global scope to reuse it\nin cat-file.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 15 ---------------\n ref-filter.c       | 11 +----------\n ref-filter.h       | 12 ++++++++++++\n 3 files changed, 13 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex e52646c0e6b5b..edf45f078b919 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -193,21 +193,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \treturn 0;\n }\n \n-struct expand_data {\n-\tstruct object_id oid;\n-\tenum object_type type;\n-\tunsigned long size;\n-\toff_t disk_size;\n-\tstruct object_id delta_base_oid;\n-\n-\t/*\n-\t * After a mark_query run, this object_info is set up to be\n-\t * passed to oid_object_info_extended. It will point to the data\n-\t * elements above, so you can retrieve the response from there.\n-\t */\n-\tstruct object_info info;\n-};\n-\n static int is_atom(const char *atom, const char *s, int slen)\n {\n \tint alen = strlen(atom);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 46bf89b3330de..65b94ea21e54f 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -64,16 +64,7 @@ struct refname_atom {\n \tint lstrip, rstrip;\n };\n \n-static struct expand_data {\n-\tstruct object_id oid;\n-\tenum object_type type;\n-\tunsigned long size;\n-\toff_t disk_size;\n-\tstruct object_id delta_base_oid;\n-\tvoid *content;\n-\n-\tstruct object_info info;\n-} oi, oi_deref;\n+static struct expand_data oi, oi_deref;\n \n /*\n  * An atom is a valid field atom listed below, possibly prefixed with\ndiff --git a/ref-filter.h b/ref-filter.h\nindex aaeda9f324f5c..fc61457d4d660 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -5,6 +5,7 @@\n #include \"refs.h\"\n #include \"commit.h\"\n #include \"parse-options.h\"\n+#include \"object-store.h\"\n \n /* Quoting styles */\n #define QUOTE_NONE 0\n@@ -73,6 +74,17 @@ struct ref_filter {\n \t\tverbose;\n };\n \n+struct expand_data {\n+\tstruct object_id oid;\n+\tenum object_type type;\n+\tunsigned long size;\n+\toff_t disk_size;\n+\tstruct object_id delta_base_oid;\n+\tvoid *content;\n+\n+\tstruct object_info info;\n+};\n+\n struct ref_format {\n \t/*\n \t * Set these to define the format; make sure you call\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369945","messageId":"0102016915f49a4f-cdb13ec8-58ea-47aa-a64a-517db120961e-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 04/20] for-each-ref: tests for new atom %(rest) added","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:04Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add tests for new formatting atom %(rest).\nWe need this atom for cat-file command.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n t/t6300-for-each-ref.sh | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh\nindex 0ffd63071392e..fb361369a037c 100755\n--- a/t/t6300-for-each-ref.sh\n+++ b/t/t6300-for-each-ref.sh\n@@ -322,6 +322,12 @@ test_expect_success 'exercise strftime with odd fields' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'Check format %(rest) gives empty output ' '\n+\techo >expected &&\n+\tgit for-each-ref --format=\"%(rest)\" refs/heads >actual &&\n+\ttest_cmp expected actual\n+'\n+\n cat >expected <<\\EOF\n refs/heads/master\n refs/remotes/origin/master\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369946","messageId":"0102016915f49a5f-d96e159b-149d-40f9-9789-d0859dc7e2e9-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 11/20] cat-file: move filter_object to diff.c","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:04Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Move function filter_object to diff.c, like it is done with\nfunction textconv_object.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 23 -----------------------\n diff.c             | 23 +++++++++++++++++++++++\n diff.h             |  4 ++++\n 3 files changed, 27 insertions(+), 23 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex cd9a4447c8da9..41f333b73d851 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -3,7 +3,6 @@\n  *\n  * Copyright (C) Linus Torvalds, 2005\n  */\n-#define USE_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n #include \"config.h\"\n #include \"builtin.h\"\n@@ -34,28 +33,6 @@ static int mark_query;\n static int skip_object_info;\n static const char *rest;\n \n-static int filter_object(const char *path, unsigned mode,\n-\t\t\t const struct object_id *oid,\n-\t\t\t char **buf, unsigned long *size)\n-{\n-\tenum object_type type;\n-\n-\t*buf = read_object_file(oid, &type, size);\n-\tif (!*buf)\n-\t\treturn error(_(\"cannot read object %s '%s'\"),\n-\t\t\t     oid_to_hex(oid), path);\n-\tif ((type == OBJ_BLOB) && S_ISREG(mode)) {\n-\t\tstruct strbuf strbuf = STRBUF_INIT;\n-\t\tif (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf)) {\n-\t\t\tfree(*buf);\n-\t\t\t*size = strbuf.len;\n-\t\t\t*buf = strbuf_detach(&strbuf, NULL);\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\tint unknown_type)\n {\ndiff --git a/diff.c b/diff.c\nindex 5306c48652db5..fe7160c86755d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1,6 +1,7 @@\n /*\n  * Copyright (C) 2005 Junio C Hamano\n  */\n+#define USE_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n #include \"config.h\"\n #include \"tempfile.h\"\n@@ -6524,6 +6525,28 @@ int textconv_object(struct repository *r,\n \treturn 1;\n }\n \n+int filter_object(const char *path, unsigned mode,\n+\t\t  const struct object_id *oid,\n+\t\t  char **buf, unsigned long *size)\n+{\n+\tenum object_type type;\n+\n+\t*buf = read_object_file(oid, &type, size);\n+\tif (!*buf)\n+\t\treturn error(_(\"cannot read object %s '%s'\"),\n+\t\t\t     oid_to_hex(oid), path);\n+\tif ((type == OBJ_BLOB) && S_ISREG(mode)) {\n+\t\tstruct strbuf strbuf = STRBUF_INIT;\n+\t\tif (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf)) {\n+\t\t\tfree(*buf);\n+\t\t\t*size = strbuf.len;\n+\t\t\t*buf = strbuf_detach(&strbuf, NULL);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n void setup_diff_pager(struct diff_options *opt)\n {\n \t/*\ndiff --git a/diff.h b/diff.h\nindex b512d0477ac3a..c3709e611870a 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -476,6 +476,10 @@ int textconv_object(struct repository *repo,\n \t\t    const struct object_id *oid, int oid_valid,\n \t\t    char **buf, unsigned long *buf_size);\n \n+int filter_object(const char *path, unsigned mode,\n+\t\t  const struct object_id *oid,\n+\t\t  char **buf, unsigned long *size);\n+\n int parse_rename_score(const char **cp_p);\n \n long parse_algorithm_value(const char *value);\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369947","messageId":"0102016915f49a5c-cbf0d726-b7dd-4da8-9cdb-5cc78dc449e9-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 10/20] cat-file: inline stream_blob","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:04Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Inline function stream_blob, it simplifies further\nmigrating process.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 26 ++++++++++++--------------\n 1 file changed, 12 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex edf45f078b919..cd9a4447c8da9 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -56,13 +56,6 @@ static int filter_object(const char *path, unsigned mode,\n \treturn 0;\n }\n \n-static int stream_blob(const struct object_id *oid)\n-{\n-\tif (stream_blob_to_fd(1, oid, NULL, 0))\n-\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n-\treturn 0;\n-}\n-\n static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\tint unknown_type)\n {\n@@ -145,8 +138,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\treturn cmd_ls_tree(2, ls_args, NULL);\n \t\t}\n \n-\t\tif (type == OBJ_BLOB)\n-\t\t\treturn stream_blob(&oid);\n+\t\tif (type == OBJ_BLOB) {\n+\t\t\tif (stream_blob_to_fd(1, &oid, NULL, 0))\n+\t\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(&oid));\n+\t\t\treturn 0;\n+\t\t}\n \t\tbuf = read_object_file(&oid, &type, &size);\n \t\tif (!buf)\n \t\t\tdie(\"Cannot read object %s\", obj_name);\n@@ -168,8 +164,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\t} else\n \t\t\t\toidcpy(&blob_oid, &oid);\n \n-\t\t\tif (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)\n-\t\t\t\treturn stream_blob(&blob_oid);\n+\t\t\tif (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB) {\n+\t\t\t\tif (stream_blob_to_fd(1, &blob_oid, NULL, 0))\n+\t\t\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(&blob_oid));\n+\t\t\t\treturn 0;\n+\t\t\t}\n \t\t\t/*\n \t\t\t * we attempted to dereference a tag to a blob\n \t\t\t * and failed; there may be new dereference\n@@ -295,9 +294,8 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n \t\t\t\tBUG(\"invalid cmdmode: %c\", opt->cmdmode);\n \t\t\tbatch_write(opt, contents, size);\n \t\t\tfree(contents);\n-\t\t} else {\n-\t\t\tstream_blob(oid);\n-\t\t}\n+\t\t} else if (stream_blob_to_fd(1, oid, NULL, 0))\n+\t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n \t}\n \telse {\n \t\tenum object_type type;\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369948","messageId":"0102016915f49a6a-10a18ba5-b1f4-4514-b76d-9b213d6c51e8-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 15/20] ref-filter: add raw formatting option","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:07Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add new formatting option %(raw), it means that we want to print\nall the file without any changes. It will help further\nto migrate all cat-file formatting logic from cat-file\nto ref-filter. For now, we just treat it as the empty string.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n ref-filter.c | 13 +++++++++++++\n 1 file changed, 13 insertions(+)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 68d9741a56468..bb963a4110fb2 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -208,6 +208,15 @@ static int remote_ref_atom_parser(const struct ref_format *format, struct used_a\n \treturn 0;\n }\n \n+static int raw_atom_parser(const struct ref_format *format, struct used_atom *atom,\n+\t\t\t   const char *arg, struct strbuf *err)\n+{\n+\tif (arg)\n+\t\treturn strbuf_addf_ret(err, -1, _(\"%%(raw) does not take arguments\"));\n+\toi.info.typep = &oi.type;\n+\treturn 0;\n+}\n+\n static int objecttype_atom_parser(const struct ref_format *format, struct used_atom *atom,\n \t\t\t\t  const char *arg, struct strbuf *err)\n {\n@@ -478,6 +487,7 @@ static struct {\n \t{ \"then\", SOURCE_NONE },\n \t{ \"else\", SOURCE_NONE },\n \t{ \"rest\", SOURCE_NONE },\n+\t{ \"raw\", SOURCE_NONE, FIELD_STR, raw_atom_parser },\n };\n \n #define REF_FORMATTING_STATE_INIT  { 0, NULL }\n@@ -1619,6 +1629,9 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t} else if (starts_with(name, \"rest\")) {\n \t\t\tv->s = xstrdup(ref->request_rest ? ref->request_rest : \"\");\n \t\t\tcontinue;\n+\t\t} else if (!strcmp(name, \"raw\")) {\n+\t\t\tv->s = xstrdup(\"\");\n+\t\t\tcontinue;\n \t\t} else if (starts_with(name, \"align\")) {\n \t\t\tv->handler = align_atom_handler;\n \t\t\tv->s = xstrdup(\"\");\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369949","messageId":"0102016915f49a52-284c872e-17ab-4bfb-befd-2720b48fcbbe-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 07/20] cat-file: remove skip_object_info","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:13Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Get rid of skip_object_info field in struct expand_data.\nexpand_data may be global further as we use it in ref-filter also,\nso we need to remove cat-file specific fields from it.\n\nAll globals that I add through this patch will be deleted in the end,\nso treat it just as the middle step.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 14 ++++----------\n 1 file changed, 4 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 9bcb02fad1f0d..f6470380f55b3 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -29,8 +29,9 @@ struct batch_options {\n };\n \n static const char *force_path;\n-/* Will be deleted at the end of this patch */\n+/* Next 2 vars will be deleted at the end of this patch */\n static int mark_query;\n+static int skip_object_info;\n \n static int filter_object(const char *path, unsigned mode,\n \t\t\t const struct object_id *oid,\n@@ -205,13 +206,6 @@ struct expand_data {\n \t * elements above, so you can retrieve the response from there.\n \t */\n \tstruct object_info info;\n-\n-\t/*\n-\t * This flag will be true if the requested batch format and options\n-\t * don't require us to call oid_object_info, which can then be\n-\t * optimized out.\n-\t */\n-\tunsigned skip_object_info : 1;\n };\n \n static int is_atom(const char *atom, const char *s, int slen)\n@@ -343,7 +337,7 @@ static void batch_object_write(const char *obj_name,\n \t\t\t       struct batch_options *opt,\n \t\t\t       struct expand_data *data)\n {\n-\tif (!data->skip_object_info &&\n+\tif (!skip_object_info &&\n \t    oid_object_info_extended(the_repository, &data->oid, &data->info,\n \t\t\t\t     OBJECT_INFO_LOOKUP_REPLACE) < 0) {\n \t\tprintf(\"%s missing\\n\",\n@@ -494,7 +488,7 @@ static int batch_objects(struct batch_options *opt)\n \tif (opt->all_objects) {\n \t\tstruct object_info empty = OBJECT_INFO_INIT;\n \t\tif (!memcmp(&data.info, &empty, sizeof(empty)))\n-\t\t\tdata.skip_object_info = 1;\n+\t\t\tskip_object_info = 1;\n \t}\n \n \t/*\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369950","messageId":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"CAL21BmnVkKtYWa1cRL1EJAwtchGcVUzhu0136AuV8uXAi5Kuew@mail.gmail.com","subject":"[PATCH RFC 01/20] cat-file: reuse struct ref_format","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:14Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Start using ref_format struct instead of simple char*.\nNeed that for further reusing of formatting logic from ref-filter.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 17 +++++++++--------\n 1 file changed, 9 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 0f092382e175c..e5de596611800 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -15,8 +15,10 @@\n #include \"sha1-array.h\"\n #include \"packfile.h\"\n #include \"object-store.h\"\n+#include \"ref-filter.h\"\n \n struct batch_options {\n+\tstruct ref_format format;\n \tint enabled;\n \tint follow_symlinks;\n \tint print_contents;\n@@ -24,7 +26,6 @@ struct batch_options {\n \tint all_objects;\n \tint unordered;\n \tint cmdmode; /* may be 'w' or 'c' for --filters or --textconv */\n-\tconst char *format;\n };\n \n static const char *force_path;\n@@ -365,7 +366,7 @@ static void batch_object_write(const char *obj_name,\n \t}\n \n \tstrbuf_reset(scratch);\n-\tstrbuf_expand(scratch, opt->format, expand_format, data);\n+\tstrbuf_expand(scratch, opt->format.format, expand_format, data);\n \tstrbuf_addch(scratch, '\\n');\n \tbatch_write(opt, scratch->buf, scratch->len);\n \n@@ -491,9 +492,6 @@ static int batch_objects(struct batch_options *opt)\n \tint save_warning;\n \tint retval = 0;\n \n-\tif (!opt->format)\n-\t\topt->format = \"%(objectname) %(objecttype) %(objectsize)\";\n-\n \t/*\n \t * Expand once with our special mark_query flag, which will prime the\n \t * object_info to be handed to oid_object_info_extended for each\n@@ -501,7 +499,7 @@ static int batch_objects(struct batch_options *opt)\n \t */\n \tmemset(&data, 0, sizeof(data));\n \tdata.mark_query = 1;\n-\tstrbuf_expand(&output, opt->format, expand_format, &data);\n+\tstrbuf_expand(&output, opt->format.format, expand_format, &data);\n \tdata.mark_query = 0;\n \tstrbuf_release(&output);\n \tif (opt->cmdmode)\n@@ -617,7 +615,7 @@ static int batch_option_callback(const struct option *opt,\n \n \tbo->enabled = 1;\n \tbo->print_contents = !strcmp(opt->long_name, \"batch\");\n-\tbo->format = arg;\n+\tbo->format.format = arg;\n \n \treturn 0;\n }\n@@ -626,7 +624,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n {\n \tint opt = 0;\n \tconst char *exp_type = NULL, *obj_name = NULL;\n-\tstruct batch_options batch = {0};\n+\tstruct batch_options batch = { REF_FORMAT_INIT };\n \tint unknown_type = 0;\n \n \tconst struct option options[] = {\n@@ -707,6 +705,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \tif (batch.buffer_output < 0)\n \t\tbatch.buffer_output = batch.all_objects;\n \n+\tif (!batch.format.format)\n+\t\tbatch.format.format = \"%(objectname) %(objecttype) %(objectsize)\";\n+\n \tif (batch.enabled)\n \t\treturn batch_objects(&batch);\n \n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369951","messageId":"0102016915f49a4b-b346412b-752e-4068-8a25-62cac2a1f555-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 05/20] cat-file: remove split_on_whitespace","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:16Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Get rid of split_on_whitespace field in struct expand_data.\nexpand_data may be global further as we use it in ref-filter also,\nso we need to remove cat-file specific fields from it.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex e5de596611800..60f3839b06f8c 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -203,13 +203,6 @@ struct expand_data {\n \t */\n \tint mark_query;\n \n-\t/*\n-\t * Whether to split the input on whitespace before feeding it to\n-\t * get_sha1; this is decided during the mark_query phase based on\n-\t * whether we have a %(rest) token in our format.\n-\t */\n-\tint split_on_whitespace;\n-\n \t/*\n \t * After a mark_query run, this object_info is set up to be\n \t * passed to oid_object_info_extended. It will point to the data\n@@ -255,9 +248,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,\n \t\telse\n \t\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)data->disk_size);\n \t} else if (is_atom(\"rest\", atom, len)) {\n-\t\tif (data->mark_query)\n-\t\t\tdata->split_on_whitespace = 1;\n-\t\telse if (data->rest)\n+\t\tif (data->rest)\n \t\t\tstrbuf_addstr(sb, data->rest);\n \t} else if (is_atom(\"deltabase\", atom, len)) {\n \t\tif (data->mark_query)\n@@ -491,6 +482,7 @@ static int batch_objects(struct batch_options *opt)\n \tstruct expand_data data;\n \tint save_warning;\n \tint retval = 0;\n+\tint is_rest = strstr(opt->format.format, \"%(rest)\") != NULL || opt->cmdmode;\n \n \t/*\n \t * Expand once with our special mark_query flag, which will prime the\n@@ -502,8 +494,6 @@ static int batch_objects(struct batch_options *opt)\n \tstrbuf_expand(&output, opt->format.format, expand_format, &data);\n \tdata.mark_query = 0;\n \tstrbuf_release(&output);\n-\tif (opt->cmdmode)\n-\t\tdata.split_on_whitespace = 1;\n \n \tif (opt->all_objects) {\n \t\tstruct object_info empty = OBJECT_INFO_INIT;\n@@ -564,7 +554,7 @@ static int batch_objects(struct batch_options *opt)\n \twarn_on_object_refname_ambiguity = 0;\n \n \twhile (strbuf_getline(&input, stdin) != EOF) {\n-\t\tif (data.split_on_whitespace) {\n+\t\tif (is_rest) {\n \t\t\t/*\n \t\t\t * Split at first whitespace, tying off the beginning\n \t\t\t * of the string and saving the remainder (or NULL) in\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369952","messageId":"0102016915f49a3c-5b22158a-2d4f-4611-9239-8388af61fd8f-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 02/20] ref-filter: rename field in ref_array_item stuct","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:17Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Rename objectname field to oid in struct ref_array_item.\nWe usually use objectname word for string representation\nof object id, so oid explains the content better.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/ls-remote.c | 2 +-\n ref-filter.c        | 8 ++++----\n ref-filter.h        | 2 +-\n 3 files changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/ls-remote.c b/builtin/ls-remote.c\nindex 1d7f1f5ce2783..ce79aede726c7 100644\n--- a/builtin/ls-remote.c\n+++ b/builtin/ls-remote.c\n@@ -143,7 +143,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\tconst struct ref_array_item *ref = ref_array.items[i];\n \t\tif (show_symref_target && ref->symref)\n \t\t\tprintf(\"ref: %s\\t%s\\n\", ref->symref, ref->refname);\n-\t\tprintf(\"%s\\t%s\\n\", oid_to_hex(&ref->objectname), ref->refname);\n+\t\tprintf(\"%s\\t%s\\n\", oid_to_hex(&ref->oid), ref->refname);\n \t\tstatus = 0; /* we found something */\n \t}\n \ndiff --git a/ref-filter.c b/ref-filter.c\nindex 422a9c9ae3fd2..736e1f9cc38fc 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1615,7 +1615,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\t\tv->s = xstrdup(buf + 1);\n \t\t\t}\n \t\t\tcontinue;\n-\t\t} else if (!deref && grab_objectname(name, &ref->objectname, v, atom)) {\n+\t\t} else if (!deref && grab_objectname(name, &ref->oid, v, atom)) {\n \t\t\tcontinue;\n \t\t} else if (!strcmp(name, \"HEAD\")) {\n \t\t\tif (atom->u.head && !strcmp(ref->refname, atom->u.head))\n@@ -1661,7 +1661,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\tstruct atom_value *v = &ref->value[i];\n \t\tif (v->s == NULL && used_atom[i].source == SOURCE_NONE)\n \t\t\treturn strbuf_addf_ret(err, -1, _(\"missing object %s for %s\"),\n-\t\t\t\t\t       oid_to_hex(&ref->objectname), ref->refname);\n+\t\t\t\t\t       oid_to_hex(&ref->oid), ref->refname);\n \t}\n \n \tif (need_tagged)\n@@ -1671,7 +1671,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\treturn 0;\n \n \n-\toi.oid = ref->objectname;\n+\toi.oid = ref->oid;\n \tif (get_object(ref, 0, &obj, &oi, err))\n \t\treturn -1;\n \n@@ -1898,7 +1898,7 @@ static struct ref_array_item *new_ref_array_item(const char *refname,\n \tstruct ref_array_item *ref;\n \n \tFLEX_ALLOC_STR(ref, refname, refname);\n-\toidcpy(&ref->objectname, oid);\n+\toidcpy(&ref->oid, oid);\n \n \treturn ref;\n }\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 85c8ebc3b904e..4d7d36e9f522d 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -34,7 +34,7 @@ struct ref_sorting {\n };\n \n struct ref_array_item {\n-\tstruct object_id objectname;\n+\tstruct object_id oid;\n \tint flag;\n \tunsigned int kind;\n \tconst char *symref;\n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"369953","messageId":"0102016915f49a63-de2f8b31-3571-4bf8-9663-c8c576c2d5ff-000000@eu-west-1.amazonses.com","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 12/20] cat-file: remove batch_write function","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-02-22T16:05:45Z","receivedAt":"2019-02-22T16:06:18Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Correct me if I am wrong, but it was not really good idea\nto implement batch_write in cmd_cat_file. Maybe it's\na good task for newbies to add flag\n(whether we accept batch write or not) to write_or_die?\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/cat-file.c | 17 ++++-------------\n 1 file changed, 4 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 41f333b73d851..a4e56762f9e56 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -226,15 +226,6 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data)\n \treturn end - start + 1;\n }\n \n-static void batch_write(struct batch_options *opt, const void *data, int len)\n-{\n-\tif (opt->buffer_output) {\n-\t\tif (fwrite(data, 1, len, stdout) != len)\n-\t\t\tdie_errno(\"unable to write to stdout\");\n-\t} else\n-\t\twrite_or_die(1, data, len);\n-}\n-\n static void print_object_or_die(struct batch_options *opt, struct expand_data *data)\n {\n \tconst struct object_id *oid = &data->oid;\n@@ -269,7 +260,7 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n \t\t\t\t\t    oid_to_hex(oid), rest);\n \t\t\t} else\n \t\t\t\tBUG(\"invalid cmdmode: %c\", opt->cmdmode);\n-\t\t\tbatch_write(opt, contents, size);\n+\t\t\twrite_or_die(1, contents, size);\n \t\t\tfree(contents);\n \t\t} else if (stream_blob_to_fd(1, oid, NULL, 0))\n \t\t\tdie(\"unable to stream %s to stdout\", oid_to_hex(oid));\n@@ -287,7 +278,7 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n \t\tif (data->info.sizep && size != data->size)\n \t\t\tdie(\"object %s changed size!?\", oid_to_hex(oid));\n \n-\t\tbatch_write(opt, contents, size);\n+\t\twrite_or_die(1, contents, size);\n \t\tfree(contents);\n \t}\n }\n@@ -309,11 +300,11 @@ static void batch_object_write(const char *obj_name,\n \tstrbuf_reset(scratch);\n \tstrbuf_expand(scratch, opt->format.format, expand_format, data);\n \tstrbuf_addch(scratch, '\\n');\n-\tbatch_write(opt, scratch->buf, scratch->len);\n+\twrite_or_die(1, scratch->buf, scratch->len);\n \n \tif (opt->print_contents) {\n \t\tprint_object_or_die(opt, data);\n-\t\tbatch_write(opt, \"\\n\", 1);\n+\t\twrite_or_die(1, \"\\n\", 1);\n \t}\n }\n \n\n--\nhttps://github.com/git/git/pull/568\n"},{"id":"370377","messageId":"20190228210444.GA12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f499b8-5813fc52-230b-469e-b939-a1244e83a2b9-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 01/20] cat-file: reuse struct ref_format","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:04:45Z","receivedAt":"2019-02-28T21:04:48Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Start using ref_format struct instead of simple char*.\n> Need that for further reusing of formatting logic from ref-filter.\n\nMakes sense.\n\n>  struct batch_options {\n> +\tstruct ref_format format;\n>  \tint enabled;\n>  \tint follow_symlinks;\n>  \tint print_contents;\n> @@ -24,7 +26,6 @@ struct batch_options {\n>  \tint all_objects;\n>  \tint unordered;\n>  \tint cmdmode; /* may be 'w' or 'c' for --filters or --textconv */\n> -\tconst char *format;\n>  };\n\nNot a huge deal, but unless there's a compelling reason to move the\nfield around in the struct, the diff is easier to read if the deleted\nand added lines stay in the same place.\n\n> @@ -491,9 +492,6 @@ static int batch_objects(struct batch_options *opt)\n>  \tint save_warning;\n>  \tint retval = 0;\n>  \n> -\tif (!opt->format)\n> -\t\topt->format = \"%(objectname) %(objecttype) %(objectsize)\";\n> -\n\nThis assignment moves down to cmd_cat_file(). I don't see any reason\nthat shouldn't work, but it makes reviewing easier if there aren't\nunexpected changes (so if it doesn't need moved in the grand scheme of\nthings, leave it as it was; if it does, it should either come in its own\npatch, or get a note in the commit message as to why it needed to move).\n\n-Peff\n"},{"id":"370378","messageId":"20190228210633.GB12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a3c-5b22158a-2d4f-4611-9239-8388af61fd8f-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 02/20] ref-filter: rename field in ref_array_item stuct","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:06:34Z","receivedAt":"2019-02-28T21:06:40Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Rename objectname field to oid in struct ref_array_item.\n> We usually use objectname word for string representation\n> of object id, so oid explains the content better.\n\nOK. I suspect the original was selected to match the %(objectname)\nplaceholder. But I agree that \"oid\" is the more common variable name,\nand I think the connection between the placeholder and the variable\nshould be pretty clear.\n\n-Peff\n"},{"id":"370379","messageId":"20190228210753.GC12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a49-6f817c1d-5b1c-47ac-98c3-18a124a733eb-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 03/20] ref-filter: add rest formatting option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:07:53Z","receivedAt":"2019-02-28T21:07:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Add rest option that allows to add string into ref_array_item\n> and then put it into specific place of the output.\n> We are using it now in cat-file command: user could put anything\n> in the input after objectname, and it will appear in the output\n> in place of %(rest).\n\nThis would make:\n\n  git for-each-ref --format='%(rest)'\n\ndo something. But what (and could it ever be useful or meaningful)?\n\nShould we add an option to ref-filter to enable/disable this\nplaceholder?\n\n-Peff\n"},{"id":"370380","messageId":"20190228211122.GD12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a4f-cdb13ec8-58ea-47aa-a64a-517db120961e-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 04/20] for-each-ref: tests for new atom %(rest) added","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:11:23Z","receivedAt":"2019-02-28T21:11:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Add tests for new formatting atom %(rest).\n> We need this atom for cat-file command.\n\nWhile I do normally encourage splitting up commits, in this case I think\nit would make sense to squash this together with patch 3. There's\nnothing to say here about what %(rest) is that isn't already said in\nthat commit message.\n\nThat said, I'm still not sure that for-each-ref should be supporting\n%(rest) at all. We should hopefully already have coverage of cat-file\nusing \"%(rest)\" (and if not, we should add some to make sure it's not\nregressed by the conversion).\n\n-Peff\n"},{"id":"370382","messageId":"20190228212222.GE12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a4b-b346412b-752e-4068-8a25-62cac2a1f555-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 05/20] cat-file: remove split_on_whitespace","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:22:23Z","receivedAt":"2019-02-28T21:22:26Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Get rid of split_on_whitespace field in struct expand_data.\n> expand_data may be global further as we use it in ref-filter also,\n> so we need to remove cat-file specific fields from it.\n\nOK, that makes some sense.\n\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index e5de596611800..60f3839b06f8c 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -203,13 +203,6 @@ struct expand_data {\n>  \t */\n>  \tint mark_query;\n>  \n> -\t/*\n> -\t * Whether to split the input on whitespace before feeding it to\n> -\t * get_sha1; this is decided during the mark_query phase based on\n> -\t * whether we have a %(rest) token in our format.\n> -\t */\n> -\tint split_on_whitespace;\n\nIt looks like we lose this name and comment in the movement, though\n(it's now \"is_rest\"). If it's just a local variable inside\nbatch_objects(), I don't know that we need the comment. But I think it's\nmore than is_rest, isn't it?\n\nIt looks like we auto-enable it when --textconv or --filters is given.\nCan we stick with the split_on_whitespace name (which I think is also\nmore descriptive about how we intend it to be used)?\n\n> @@ -491,6 +482,7 @@ static int batch_objects(struct batch_options *opt)\n>  \tstruct expand_data data;\n>  \tint save_warning;\n>  \tint retval = 0;\n> +\tint is_rest = strstr(opt->format.format, \"%(rest)\") != NULL || opt->cmdmode;\n\nI'm not excited by this loose parsing. It would do the wrong thing in\nsome funny corner cases (e.g., \"%%(rest)\").\n\nWe should be able to ask the format parser whether the \"rest\"\nplaceholder was used. That's what the initial strbuf_expand() call is\ndoing. I see that it's hard for us to pass something to its callback\noutside of expand_data (since after all, expand_data takes up the\nvoid-pointer data slot).\n\nBut doesn't that point to this being the wrong change (or perhaps the\nwrong time to make it)?  I think we'd want to keep using our own local\nexpand_data as long as we are not using ref-filter. And then ref-filter\nwould grow its own struct to hold the data that _it_ needs. Some of that\nwould be duplicates of what we have here, but that's OK. When we cut\nover to ref-filter, that's when we'd drop the fields here.\n\nAnd eventually we'd drop that strbuf_expand(), too, as ref-filter would\ndo the parsing. But at that point we wouldn't want this strstr() either:\nwe'd have ref-filter parse the format, and then check the parsed atoms\nto see if one of them is \"rest\".\n\n-Peff\n"},{"id":"370383","messageId":"20190228212540.GF12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a4f-f02a6509-a3ba-41b0-b768-3d8ba116f526-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 06/20] cat-file: remove mark_query from expand_data","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:25:40Z","receivedAt":"2019-02-28T21:25:44Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Get rid of mark_query field in struct expand_data.\n> expand_data may be global further as we use it in ref-filter also,\n> so we need to remove cat-file specific fields from it.\n> \n> All globals that I add through this patch will be deleted in the end,\n> so treat it just as the middle step.\n\nSo this is a similar situation to the split_on_whitespace thing we have\nin the previous patch.\n\nI think many of my comments there could apply here. I.e., do we need to\nbe removing them from expand_data now, instead of just moving the bits\nfrom expand_data over to ref-filter?\n\nBut if we assume for a moment that doing it that way isn't feasible (or\nat least isn't as easy as this way), then I think what this patch does\nis preferable to the previous one. By making it a global variable, we\ncan still interact with it from the expand callback, even if it's not\npart of expand_data().\n\nSo the previous patch could make \"split_on_whitespace\" a global, and\nthen continue to set it from expand_atom() as the current code does.\n\n-Peff\n"},{"id":"370384","messageId":"20190228212637.GG12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a52-284c872e-17ab-4bfb-befd-2720b48fcbbe-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 07/20] cat-file: remove skip_object_info","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:26:37Z","receivedAt":"2019-02-28T21:26:40Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Get rid of skip_object_info field in struct expand_data.\n> expand_data may be global further as we use it in ref-filter also,\n> so we need to remove cat-file specific fields from it.\n> \n> All globals that I add through this patch will be deleted in the end,\n> so treat it just as the middle step.\n\nOK, makes sense in the same way that the previous patch does. I actually\nwonder if it would make sense to just do them all in a single patch; the\njustification is identical for all cases. But I'm also OK leaving them\nseparate.\n\n-Peff\n"},{"id":"370385","messageId":"20190228212734.GH12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a54-e28b7a40-d51c-4dd4-85a3-0eea83d4f0cb-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 08/20] cat-file: remove rest from expand_data","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:27:35Z","receivedAt":"2019-02-28T21:27:38Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Get rid of rest field in struct expand_data.\n> expand_data may be global further as we use it in ref-filter also,\n> so we need to remove cat-file specific fields from it.\n> \n> All globals that I add through this patch will be deleted in the end,\n> so treat it just as the middle step.\n\nSame comments apply as patch 7 (and 6 and 5). :)\n\n-Peff\n"},{"id":"370386","messageId":"20190228213015.GI12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a58-dc12f07d-00e6-42be-812b-3072d33910d3-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 09/20] ref-filter: make expand_data global","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:30:15Z","receivedAt":"2019-02-28T21:30:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Put struct expand_data into global scope to reuse it\n> in cat-file.\n\nSo this is the payoff for moving all those things out of expand_data.\nInstead of just replicating the bits it needs in ref-filter, we're\nmaking it globally available.\n\nAt this point in the series, I'm still unconvinced that this is the\nright direction, but I haven't read all the way to the end yet.\n\nThis probably needs a better name. In the context of cat-file,\nexpand_data is the data struct we feed to strbuf_expand(). But in the\nglobal namespace of all of Git, it needs a more descriptive name.\n\nThis likely goes away (or becomes private to ref-filter.c) in the end,\nbut it probably needs a different name there, too. We're not calling\nstrbuf_expand() from there.\n\n-Peff\n"},{"id":"370387","messageId":"20190228213351.GJ12723@sigill.intra.peff.net","threadId":"50565","inReplyTo":"0102016915f49a5c-cbf0d726-b7dd-4da8-9cdb-5cc78dc449e9-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 10/20] cat-file: inline stream_blob","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-28T21:33:51Z","receivedAt":"2019-02-28T21:33:54Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n\n> Inline function stream_blob, it simplifies further\n> migrating process.\n\nI'd have to see what exactly gets simplified later on, but I'm mildly\nnegative on this by itself. The reason this function was added in\n98f425b453 (cat-file: handle streaming failures consistently,\n2018-10-30) was to keep the outcomes consistent.\n\nThe function right now isn't _too_ long, so we're really just\nduplicating the message text. But I wonder if it might eventually get\nmore complicated, if we ever do the \"future work\" discussed in\n98f425b453. So this seems like a step in the wrong direction.\n\n-Peff\n"},{"id":"370405","messageId":"CAL21BmnWuiZtcjZMPw2M+fyx1N1qSMKqDULQzaioMaB9P95SDA@mail.gmail.com","threadId":"50565","inReplyTo":"20190228211122.GD12723@sigill.intra.peff.net","subject":"Re: [PATCH RFC 04/20] for-each-ref: tests for new atom %(rest) added","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2019-03-01T06:10:20Z","receivedAt":"2019-03-01T06:10:36Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"пт, 1 мар. 2019 г. в 00:11, Jeff King <peff@peff.net>:\n>\n> On Fri, Feb 22, 2019 at 04:05:45PM +0000, Olga Telezhnaya wrote:\n>\n> > Add tests for new formatting atom %(rest).\n> > We need this atom for cat-file command.\n>\n> While I do normally encourage splitting up commits, in this case I think\n> it would make sense to squash this together with patch 3. There's\n> nothing to say here about what %(rest) is that isn't already said in\n> that commit message.\n\nAgree, will squash.\n\n>\n> That said, I'm still not sure that for-each-ref should be supporting\n> %(rest) at all. We should hopefully already have coverage of cat-file\n> using \"%(rest)\" (and if not, we should add some to make sure it's not\n> regressed by the conversion).\n\nIf we want to use ref-filter formatting logic in cat-file, we have to\nadd this atom in ref-filter. I agree that we do not need it in\nref-filter, and that's why I left %(rest) in cat-file docs (it's in\nthe end of the patch). But in the code, I am not sure we want to make\none more array with specific cat-file atoms (or atoms for other\ncommand).\n\n>\n> -Peff\n"},{"id":"370501","messageId":"CAP8UFD1--37Z7AqiBQ2F2b3aR+pv_w1Y9CpSEYF4gHhs7KkEwg@mail.gmail.com","threadId":"50565","inReplyTo":"0102016915f49a4f-f02a6509-a3ba-41b0-b768-3d8ba116f526-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 06/20] cat-file: remove mark_query from expand_data","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2019-03-03T09:41:49Z","receivedAt":"2019-03-03T09:42:04Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Fri, Feb 22, 2019 at 5:07 PM Olga Telezhnaya\n<olyatelezhnaya@gmail.com> wrote:\n>\n> Get rid of mark_query field in struct expand_data.\n> expand_data may be global further as we use it in ref-filter also,\n> so we need to remove cat-file specific fields from it.\n>\n> All globals that I add through this patch will be deleted in the end,\n> so treat it just as the middle step.\n>\n> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n> ---\n>  builtin/cat-file.c | 22 +++++++++-------------\n>  1 file changed, 9 insertions(+), 13 deletions(-)\n>\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index 60f3839b06f8c..9bcb02fad1f0d 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -29,6 +29,8 @@ struct batch_options {\n>  };\n>\n>  static const char *force_path;\n> +/* Will be deleted at the end of this patch */\n\nWhen this patch is committed, there is no patch anymore, only a\ncommit. And of course the variable will be deleted in a following\ncommit. So instead I'd rather see something like:\n\n/* Will be deleted in a following commit */\n\nor maybe:\n\n/* TODO: delete this in a following commit */\n"}]}