{"thread":{"id":"47700","subject":"[PATCH RFC 23/24] cat-file: tests for new atoms added","startedAt":"2018-01-26T19:43:48Z","lastAt":"2018-01-31T06:39:57Z","messageCount":33,"participants":["Olga Telezhnaya","Junio C Hamano","Оля Тележная"],"isPatch":true,"patchVersion":1,"patchTotal":24},"messages":[{"id":"337520","messageId":"0102016133ff3b5d-2a898107-6989-411d-b7c5-f349e897873e-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 23/24] cat-file: tests for new atoms added","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:43:48Z","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),\nsome of them could be supported later in other patches.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\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 b19f332694620..e72fcaf0e02c5 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 tree_sha1=$(git write-tree)\n tree_size=33\n tree_pretty_content=\"100644 blob $hello_sha1\thello\"\n@@ -157,6 +183,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@@ -171,6 +208,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/452\n"},{"id":"337521","messageId":"0102016133ff3b59-b5619bdf-930f-4cf7-8dd4-e36f8e3635ff-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 18/24] ref-filter: make valid_atom general again","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:43:50Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Stop using valid_cat_file_atom, making the code more general.\nFurther commits will contain some tests, docs and\nsupport of new features.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 46 ++++++++++++----------------------------------\n 1 file changed, 12 insertions(+), 34 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex bfbc7c83fdd47..4d0d4f081227d 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -359,8 +359,8 @@ static struct valid_atom {\n \tvoid (*parser)(const struct ref_format *format, struct used_atom *atom, const char *arg);\n } valid_atom[] = {\n \t{ \"refname\" , FIELD_STR, refname_atom_parser },\n-\t{ \"objecttype\" },\n-\t{ \"objectsize\", FIELD_ULONG },\n+\t{ \"objecttype\", FIELD_STR, objecttype_atom_parser },\n+\t{ \"objectsize\", FIELD_ULONG, objectsize_atom_parser },\n \t{ \"objectname\", FIELD_STR, objectname_atom_parser },\n \t{ \"tree\" },\n \t{ \"parent\" },\n@@ -397,12 +397,6 @@ static struct valid_atom {\n \t{ \"if\", FIELD_STR, if_atom_parser },\n \t{ \"then\" },\n \t{ \"else\" },\n-};\n-\n-static struct valid_atom valid_cat_file_atom[] = {\n-\t{ \"objectname\" },\n-\t{ \"objecttype\", FIELD_STR, objecttype_atom_parser },\n-\t{ \"objectsize\", FIELD_ULONG, objectsize_atom_parser },\n \t{ \"rest\" },\n \t{ \"deltabase\", FIELD_STR, deltabase_atom_parser },\n };\n@@ -432,7 +426,6 @@ struct atom_value {\n  * Used to parse format string and sort specifiers\n  */\n static int parse_ref_filter_atom(const struct ref_format *format,\n-\t\t\t\t const struct valid_atom *valid_atom, int n_atoms,\n \t\t\t\t const char *atom, const char *ep)\n {\n \tconst char *sp;\n@@ -462,13 +455,13 @@ static int parse_ref_filter_atom(const struct ref_format *format,\n \tatom_len = (arg ? arg : ep) - sp;\n \n \t/* Is the atom a valid one? */\n-\tfor (i = 0; i < n_atoms; i++) {\n+\tfor (i = 0; i < ARRAY_SIZE(valid_atom); i++) {\n \t\tint len = strlen(valid_atom[i].name);\n \t\tif (len == atom_len && !memcmp(valid_atom[i].name, sp, len))\n \t\t\tbreak;\n \t}\n \n-\tif (n_atoms <= i)\n+\tif (ARRAY_SIZE(valid_atom) <= i)\n \t\tdie(_(\"unknown field name: %.*s\"), (int)(ep-atom), atom);\n \n \t/* Add it in, including the deref prefix */\n@@ -762,15 +755,9 @@ int verify_ref_format(struct ref_format *format)\n \t\t\treturn error(_(\"malformed format string %s\"), sp);\n \t\t/* sp points at \"%(\" and ep points at the closing \")\" */\n \n-\t\tif (is_cat) {\n-\t\t\tat = parse_ref_filter_atom(format, valid_cat_file_atom,\n-\t\t\t\t\t\t   ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);\n-\t\t} else {\n-\t\t\tat = parse_ref_filter_atom(format, valid_atom,\n-\t\t\t\t\t\t   ARRAY_SIZE(valid_atom), sp + 2, ep);\n-\t\t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n-\t\t\t\tformat->need_color_reset_at_eol = !!strcmp(color, \"reset\");\n-\t\t}\n+\t\tat = parse_ref_filter_atom(format, sp + 2, ep);\n+\t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n+\t\t\tformat->need_color_reset_at_eol = !!strcmp(color, \"reset\");\n \n \t\tcp = ep + 1;\n \t}\n@@ -2244,18 +2231,10 @@ int format_ref_array_item(struct ref_array_item *info,\n \t\tep = strchr(sp, ')');\n \t\tif (cp < sp)\n \t\t\tappend_literal(cp, sp, &state);\n-\t\tif (is_cat) {\n-\t\t\tif(get_ref_atom_value(info,\n-\t\t\t\tparse_ref_filter_atom(format, valid_cat_file_atom,\n-\t\t\t\t\tARRAY_SIZE(valid_cat_file_atom), sp + 2, ep),\n-\t\t\t\t\t&atomv))\n-\t\t\t\treturn -1;\n-\t\t} else\n-\t\t\tget_ref_atom_value(info,\n-\t\t\t\t   parse_ref_filter_atom(format, valid_atom,\n-\t\t\t\t\t\t\t ARRAY_SIZE(valid_atom),\n-\t\t\t\t\t\t\t sp + 2, ep),\n-\t\t\t\t   &atomv);\n+\t\tif(get_ref_atom_value(info,\n+\t\t\t\t      parse_ref_filter_atom(format, sp + 2, ep),\n+\t\t\t\t      &atomv))\n+\t\t\treturn -1;\n \t\tatomv->handler(atomv, &state);\n \t}\n \tif (is_cat && strlen(format->format) == 0)\n@@ -2307,8 +2286,7 @@ static int parse_sorting_atom(const char *atom)\n \t */\n \tstruct ref_format dummy = REF_FORMAT_INIT;\n \tconst char *end = atom + strlen(atom);\n-\treturn parse_ref_filter_atom(&dummy, valid_atom,\n-\t\t\t\t     ARRAY_SIZE(valid_atom), atom, end);\n+\treturn parse_ref_filter_atom(&dummy, atom, end);\n }\n \n /*  If no sorting option is given, use refname to sort as default */\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337522","messageId":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":null,"subject":"[PATCH RFC 01/24] ref-filter: get rid of goto","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:43:52Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Get rid of goto command in ref-filter for better readability.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 103 ++++++++++++++++++++++++++++++-----------------------------\n 1 file changed, 53 insertions(+), 50 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex f9e25aea7a97e..37337b57aacf4 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1354,16 +1354,60 @@ static const char *get_refname(struct used_atom *atom, struct ref_array_item *re\n \treturn show_ref(&atom->u.refname, ref->refname);\n }\n \n+static void need_object(struct ref_array_item *ref) {\n+\tstruct object *obj;\n+\tconst struct object_id *tagged;\n+\tunsigned long size;\n+\tint eaten;\n+\tvoid *buf = get_obj(&ref->objectname, &obj, &size, &eaten);\n+\tif (!buf)\n+\t\tdie(_(\"missing object %s for %s\"),\n+\t\t    oid_to_hex(&ref->objectname), ref->refname);\n+\tif (!obj)\n+\t\tdie(_(\"parse_object_buffer failed on %s for %s\"),\n+\t\t    oid_to_hex(&ref->objectname), ref->refname);\n+\n+\tgrab_values(ref->value, 0, obj, buf, size);\n+\tif (!eaten)\n+\t\tfree(buf);\n+\n+\t/*\n+\t * If there is no atom that wants to know about tagged\n+\t * object, we are done.\n+\t */\n+\tif (!need_tagged || (obj->type != OBJ_TAG))\n+\t\treturn;\n+\n+\t/*\n+\t * If it is a tag object, see if we use a value that derefs\n+\t * the object, and if we do grab the object it refers to.\n+\t */\n+\ttagged = &((struct tag *)obj)->tagged->oid;\n+\n+\t/*\n+\t * NEEDSWORK: This derefs tag only once, which\n+\t * is good to deal with chains of trust, but\n+\t * is not consistent with what deref_tag() does\n+\t * which peels the onion to the core.\n+\t */\n+\tbuf = get_obj(tagged, &obj, &size, &eaten);\n+\tif (!buf)\n+\t\tdie(_(\"missing object %s for %s\"),\n+\t\t    oid_to_hex(tagged), ref->refname);\n+\tif (!obj)\n+\t\tdie(_(\"parse_object_buffer failed on %s for %s\"),\n+\t\t    oid_to_hex(tagged), ref->refname);\n+\tgrab_values(ref->value, 1, obj, buf, size);\n+\tif (!eaten)\n+\t\tfree(buf);\n+}\n+\n /*\n  * Parse the object referred by ref, and grab needed value.\n  */\n static void populate_value(struct ref_array_item *ref)\n {\n-\tvoid *buf;\n-\tstruct object *obj;\n-\tint eaten, i;\n-\tunsigned long size;\n-\tconst struct object_id *tagged;\n+\tint i;\n \n \tref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));\n \n@@ -1477,53 +1521,12 @@ static void populate_value(struct ref_array_item *ref)\n \n \tfor (i = 0; i < used_atom_cnt; i++) {\n \t\tstruct atom_value *v = &ref->value[i];\n-\t\tif (v->s == NULL)\n-\t\t\tgoto need_obj;\n+\t\tif (v->s == NULL) {\n+\t\t\tneed_object(ref);\n+\t\t\tbreak;\n+\t\t}\n \t}\n \treturn;\n-\n- need_obj:\n-\tbuf = get_obj(&ref->objectname, &obj, &size, &eaten);\n-\tif (!buf)\n-\t\tdie(_(\"missing object %s for %s\"),\n-\t\t    oid_to_hex(&ref->objectname), ref->refname);\n-\tif (!obj)\n-\t\tdie(_(\"parse_object_buffer failed on %s for %s\"),\n-\t\t    oid_to_hex(&ref->objectname), ref->refname);\n-\n-\tgrab_values(ref->value, 0, obj, buf, size);\n-\tif (!eaten)\n-\t\tfree(buf);\n-\n-\t/*\n-\t * If there is no atom that wants to know about tagged\n-\t * object, we are done.\n-\t */\n-\tif (!need_tagged || (obj->type != OBJ_TAG))\n-\t\treturn;\n-\n-\t/*\n-\t * If it is a tag object, see if we use a value that derefs\n-\t * the object, and if we do grab the object it refers to.\n-\t */\n-\ttagged = &((struct tag *)obj)->tagged->oid;\n-\n-\t/*\n-\t * NEEDSWORK: This derefs tag only once, which\n-\t * is good to deal with chains of trust, but\n-\t * is not consistent with what deref_tag() does\n-\t * which peels the onion to the core.\n-\t */\n-\tbuf = get_obj(tagged, &obj, &size, &eaten);\n-\tif (!buf)\n-\t\tdie(_(\"missing object %s for %s\"),\n-\t\t    oid_to_hex(tagged), ref->refname);\n-\tif (!obj)\n-\t\tdie(_(\"parse_object_buffer failed on %s for %s\"),\n-\t\t    oid_to_hex(tagged), ref->refname);\n-\tgrab_values(ref->value, 1, obj, buf, size);\n-\tif (!eaten)\n-\t\tfree(buf);\n }\n \n /*\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337523","messageId":"0102016133ff3b05-802b1468-13cf-453f-801f-d5530f2f94ac-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 10/24] ref-filter: make populate_value global","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:43:54Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Make function global for further using in cat-file.\nIn the end of patch series this function becomes internal again,\nso this is a part of middle step. cat-file would use more general\nfunctions further.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 2 +-\n ref-filter.h | 3 +++\n 2 files changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 95c85009f1f58..e69dd1ff5091f 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1454,7 +1454,7 @@ static void need_object(struct ref_array_item *ref) {\n /*\n  * Parse the object referred by ref, and grab needed value.\n  */\n-static int populate_value(struct ref_array_item *ref)\n+int populate_value(struct ref_array_item *ref)\n {\n \tint i;\n \ndiff --git a/ref-filter.h b/ref-filter.h\nindex 7aaf82799ec2d..6373167aaacd7 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -176,4 +176,7 @@ void setup_ref_filter_porcelain_msg(void);\n void pretty_print_ref(const char *name, const unsigned char *sha1,\n \t\t      const struct ref_format *format);\n \n+/* Fill the values of request and prepare all data for final string creation */\n+int populate_value(struct ref_array_item *ref);\n+\n #endif /*  REF_FILTER_H  */\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337524","messageId":"0102016133ff3b7d-d733e1b6-eb98-4033-ba86-83fc6323887b-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 22/24] for-each-ref: tests for new atoms added","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:43:57Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add tests for new formatting atoms: rest, deltabase, objectsize:disk.\nrest means nothing and we expand it into empty string.\nWe need this atom for cat-file command.\nHave plans to support deltabase and objectsize:disk further\n(as it is done in cat-file), now also expand it to empty string.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n t/t6300-for-each-ref.sh | 18 ++++++++++++++++++\n 1 file changed, 18 insertions(+)\n\ndiff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh\nindex c128dfc579079..eee656a6abba9 100755\n--- a/t/t6300-for-each-ref.sh\n+++ b/t/t6300-for-each-ref.sh\n@@ -316,6 +316,24 @@ test_expect_success 'exercise strftime with odd fields' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'Check format %(objectsize:disk) gives empty output ' '\n+\techo >expected &&\n+\tgit for-each-ref --format=\"%(objectsize:disk)\" refs/heads >actual &&\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+test_expect_success 'Check format %(deltabase) gives empty output ' '\n+\techo >expected &&\n+\tgit for-each-ref --format=\"%(deltabase)\" 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/452\n"},{"id":"337525","messageId":"0102016133ff3b28-9969f573-5976-45d9-a51a-4edba26d95c2-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 09/24] cat-file: start use ref_array_item struct","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:00Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Moving from using expand_data to ref_array_item structure.\nThat helps us to reuse functions from ref-filter easier.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 32 ++++++++++++++++++++------------\n ref-filter.h       |  5 +++++\n 2 files changed, 25 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 909412747cbd2..61b7acc79155d 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -183,27 +183,27 @@ static int is_atom(const char *atom, const char *s, int slen)\n }\n \n static void expand_atom(struct strbuf *sb, const char *atom, int len,\n-\t\t\t struct expand_data *data)\n+\t\t\t struct ref_array_item *item)\n {\n \tif (is_atom(\"objectname\", atom, len))\n-\t\tstrbuf_addstr(sb, oid_to_hex(&data->oid));\n+\t\tstrbuf_addstr(sb, oid_to_hex(&item->objectname));\n \telse if (is_atom(\"objecttype\", atom, len))\n-\t\tstrbuf_addstr(sb, typename(data->type));\n+\t\tstrbuf_addstr(sb, typename(item->type));\n \telse if (is_atom(\"objectsize\", atom, len))\n-\t\tstrbuf_addf(sb, \"%lu\", data->size);\n+\t\tstrbuf_addf(sb, \"%lu\", item->size);\n \telse if (is_atom(\"objectsize:disk\", atom, len))\n-\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)data->disk_size);\n+\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)item->disk_size);\n \telse if (is_atom(\"rest\", atom, len)) {\n-\t\tif (data->rest)\n-\t\t\tstrbuf_addstr(sb, data->rest);\n+\t\tif (item->rest)\n+\t\t\tstrbuf_addstr(sb, item->rest);\n \t} else if (is_atom(\"deltabase\", atom, len))\n-\t\tstrbuf_addstr(sb, oid_to_hex(&data->delta_base_oid));\n+\t\tstrbuf_addstr(sb, oid_to_hex(item->delta_base_oid));\n }\n \n-static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)\n+static size_t expand_format(struct strbuf *sb, const char *start, void *data)\n {\n \tconst char *end;\n-\tstruct expand_data *data = vdata;\n+\tstruct ref_array_item *item = data;\n \n \tif (*start != '(')\n \t\treturn 0;\n@@ -211,7 +211,7 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)\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+\texpand_atom(sb, start + 1, end - start - 1, item);\n \treturn end - start + 1;\n }\n \n@@ -283,6 +283,7 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,\n \t\t\t       struct expand_data *data)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n+\tstruct ref_array_item item = {0};\n \n \tif (!data->skip_object_info &&\n \t    sha1_object_info_extended(data->oid.hash, &data->info,\n@@ -293,7 +294,14 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,\n \t\treturn;\n \t}\n \n-\tstrbuf_expand(&buf, opt->format.format, expand_format, data);\n+\titem.objectname = data->oid;\n+\titem.type = data->type;\n+\titem.size = data->size;\n+\titem.disk_size = data->disk_size;\n+\titem.rest = data->rest;\n+\titem.delta_base_oid = &data->delta_base_oid;\n+\n+\tstrbuf_expand(&buf, opt->format.format, expand_format, &item);\n \tstrbuf_addch(&buf, '\\n');\n \tbatch_write(opt, buf.buf, buf.len);\n \tstrbuf_release(&buf);\ndiff --git a/ref-filter.h b/ref-filter.h\nindex b50c8e6aaf2c4..7aaf82799ec2d 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -40,6 +40,11 @@ struct ref_array_item {\n \tconst char *symref;\n \tstruct commit *commit;\n \tstruct atom_value *value;\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 \tchar refname[FLEX_ARRAY];\n };\n \n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337526","messageId":"0102016133ff3b4c-a68ff848-85c3-40e0-acf1-3539e263bcd2-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 19/24] ref-filter: make populate_value internal again","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:03Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Remove populate_value from header file. We needed that\nfor interim step, now it could be returned back.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 2 +-\n ref-filter.h | 3 ---\n 2 files changed, 1 insertion(+), 4 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 4d0d4f081227d..c3a5c3897295f 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1476,7 +1476,7 @@ static int check_and_fill_for_cat(struct ref_array_item *ref)\n /*\n  * Parse the object referred by ref, and grab needed value.\n  */\n-int populate_value(struct ref_array_item *ref)\n+static int populate_value(struct ref_array_item *ref)\n {\n \tint i;\n \ndiff --git a/ref-filter.h b/ref-filter.h\nindex d8064086f36a9..285a2311f6cc9 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -172,9 +172,6 @@ void setup_ref_filter_porcelain_msg(void);\n void pretty_print_ref(const char *name, const unsigned char *sha1,\n \t\t      const struct ref_format *format);\n \n-/* Fill the values of request and prepare all data for final string creation */\n-int populate_value(struct ref_array_item *ref);\n-\n /* Search for atom \"rest\" in given format. */\n int is_rest_atom_used(const struct ref_format *format);\n \n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337527","messageId":"0102016133ff3afb-6bab2c11-e0f3-4bef-9626-fbcc826bcb15-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 03/24] cat-file: split expand_atom into 2 functions","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:07Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Split expand_atom function into 2 different functions,\nexpand_atom_into_fields prepares variable for further filling,\n(new) expand_atom creates resulting string.\nNeed that for further reusing of formatting logic from ref-filter.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 73 +++++++++++++++++++++++++++++-------------------------\n 1 file changed, 39 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex f5fa4fd75af26..f783b39b9bd5c 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -217,47 +217,49 @@ static int is_atom(const char *atom, const char *s, int slen)\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+static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int len,\n+\t\t\tstruct expand_data *data)\n {\n-\tstruct expand_data *data = vdata;\n+\tif (is_atom(\"objectname\", atom, len))\n+\t\t; /* do nothing */\n+\telse if (is_atom(\"objecttype\", atom, len))\n+\t\tdata->info.typep = &data->type;\n+\telse if (is_atom(\"objectsize\", atom, len))\n+\t\tdata->info.sizep = &data->size;\n+\telse if (is_atom(\"objectsize:disk\", atom, len))\n+\t\tdata->info.disk_sizep = &data->disk_size;\n+\telse if (is_atom(\"rest\", atom, len))\n+\t\tdata->split_on_whitespace = 1;\n+\telse if (is_atom(\"deltabase\", atom, len))\n+\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n+\telse\n+\t\tdie(\"unknown format element: %.*s\", len, atom);\n+}\n \n-\tif (is_atom(\"objectname\", atom, len)) {\n-\t\tif (!data->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\t\tdata->info.typep = &data->type;\n-\t\telse\n-\t\t\tstrbuf_addstr(sb, typename(data->type));\n-\t} else if (is_atom(\"objectsize\", atom, len)) {\n-\t\tif (data->mark_query)\n-\t\t\tdata->info.sizep = &data->size;\n-\t\telse\n-\t\t\tstrbuf_addf(sb, \"%lu\", data->size);\n-\t} else if (is_atom(\"objectsize:disk\", atom, len)) {\n-\t\tif (data->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 (data->mark_query)\n-\t\t\tdata->split_on_whitespace = 1;\n-\t\telse if (data->rest)\n+static void expand_atom(struct strbuf *sb, const char *atom, int len,\n+\t\t\t struct expand_data *data)\n+{\n+\tif (is_atom(\"objectname\", atom, len))\n+\t\tstrbuf_addstr(sb, oid_to_hex(&data->oid));\n+\telse if (is_atom(\"objecttype\", atom, len))\n+\t\tstrbuf_addstr(sb, typename(data->type));\n+\telse if (is_atom(\"objectsize\", atom, len))\n+\t\tstrbuf_addf(sb, \"%lu\", data->size);\n+\telse if (is_atom(\"objectsize:disk\", atom, len))\n+\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)data->disk_size);\n+\telse if (is_atom(\"rest\", atom, 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\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} else if (is_atom(\"deltabase\", atom, len))\n+\t\tstrbuf_addstr(sb, oid_to_hex(&data->delta_base_oid));\n+\telse\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+static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)\n {\n \tconst char *end;\n+\tstruct expand_data *data = vdata;\n \n \tif (*start != '(')\n \t\treturn 0;\n@@ -265,7 +267,10 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data)\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+\tif (data->mark_query)\n+\t\texpand_atom_into_fields(sb, start + 1, end - start - 1, data);\n+\telse\n+\t\texpand_atom(sb, start + 1, end - start - 1, data);\n \n \treturn end - start + 1;\n }\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337528","messageId":"0102016133ff3af0-0ebed14d-deb5-4744-9267-4c5b0c6a30c8-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 04/24] cat-file: reuse struct ref_format","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:11Z","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>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 15 ++++++++-------\n 1 file changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex f783b39b9bd5c..65c300184cab8 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -13,15 +13,16 @@\n #include \"tree-walk.h\"\n #include \"sha1-array.h\"\n #include \"packfile.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 \tint buffer_output;\n \tint all_objects;\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@@ -353,7 +354,7 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,\n \t\treturn;\n \t}\n \n-\tstrbuf_expand(&buf, opt->format, expand_format, data);\n+\tstrbuf_expand(&buf, opt->format.format, expand_format, data);\n \tstrbuf_addch(&buf, '\\n');\n \tbatch_write(opt, buf.buf, buf.len);\n \tstrbuf_release(&buf);\n@@ -446,8 +447,8 @@ 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+\tif (!opt->format.format)\n+\t\topt->format.format = \"%(objectname) %(objecttype) %(objectsize)\";\n \n \t/*\n \t * Expand once with our special mark_query flag, which will prime the\n@@ -456,7 +457,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(&buf, opt->format, expand_format, &data);\n+\tstrbuf_expand(&buf, opt->format.format, expand_format, &data);\n \tdata.mark_query = 0;\n \tif (opt->cmdmode)\n \t\tdata.split_on_whitespace = 1;\n@@ -548,7 +549,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@@ -557,7 +558,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\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337529","messageId":"0102016133ff3b58-dd205bee-24b9-4827-907c-eaf4a15c6f00-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 24/24] cat-file: update of docs","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:12Z","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.\nWe do not support cat-file atoms in general formatting logic\n(there is just the support for cat-file), that is why some of the atoms\nare still explained in cat-file docs.\nWe need to move these explanations when atoms will be supported\nby other commands.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n Documentation/git-cat-file.txt | 13 ++-----------\n 1 file changed, 2 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt\nindex f90f09b03fae5..90639ac21d0e8 100644\n--- a/Documentation/git-cat-file.txt\n+++ b/Documentation/git-cat-file.txt\n@@ -187,17 +187,8 @@ linkgit:git-rev-parse[1].\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+newline. The available atoms are the same as that of\n+linkgit:git-for-each-ref[1], but there are some additional ones:\n \n `objectsize:disk`::\n \tThe size, in bytes, that the object takes up on disk. See the\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337530","messageId":"0102016133ff3b49-fe78f01d-12a2-4f53-afae-fe88d9d73754-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 20/24] ref-filter: unifying formatting of cat-file opts","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:15Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"cat-file options are now filled by general logic.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 31 ++++++++++++++-----------------\n 1 file changed, 14 insertions(+), 17 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex c3a5c3897295f..2cac394e93f52 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -825,8 +825,10 @@ static void grab_common_values(struct atom_value *val, int deref, struct object\n \t\telse if (!strcmp(name, \"objectsize\")) {\n \t\t\tv->value = sz;\n \t\t\tv->s = xstrfmt(\"%lu\", sz);\n-\t\t}\n-\t\telse if (deref)\n+\t\t} else if (!strcmp(name, \"objectsize:disk\")) {\n+\t\t\tv->value = cat_file_info.disk_size;\n+\t\t\tv->s = xstrfmt(\"%\"PRIuMAX, (uintmax_t)v->value);\n+\t\t} else if (deref)\n \t\t\tgrab_objectname(name, obj->oid.hash, v, &used_atom[i]);\n \t}\n }\n@@ -1509,21 +1511,7 @@ static int populate_value(struct ref_array_item *ref)\n \t\t\tname++;\n \t\t}\n \n-\t\tif (is_cat) {\n-\t\t\tif (starts_with(name, \"objectname\"))\n-\t\t\t\tv->s = oid_to_hex(&ref->objectname);\n-\t\t\telse if (starts_with(name, \"objecttype\"))\n-\t\t\t\tv->s = typename(ref->type);\n-\t\t\telse if (starts_with(name, \"objectsize\")) {\n-\t\t\t\tv->s = xstrfmt(\"%lu\", ref->size);\n-\t\t\t} else if (starts_with(name, \"objectsize:disk\")) {\n-\t\t\t\tv->s = xstrfmt(\"%\"PRIuMAX, (uintmax_t)ref->disk_size);\n-\t\t\t} else if (starts_with(name, \"rest\"))\n-\t\t\t\tv->s = ref->rest;\n-\t\t\telse if (starts_with(name, \"deltabase\"))\n-\t\t\t\tv->s = xstrdup(oid_to_hex(ref->delta_base_oid));\n-\t\t\tcontinue;\n-\t\t} else if (starts_with(name, \"refname\"))\n+\t\tif (starts_with(name, \"refname\"))\n \t\t\trefname = get_refname(atom, ref);\n \t\telse if (starts_with(name, \"symref\"))\n \t\t\trefname = get_symref(atom, ref);\n@@ -1579,6 +1567,15 @@ static int populate_value(struct ref_array_item *ref)\n \t\t\telse\n \t\t\t\tv->s = \" \";\n \t\t\tcontinue;\n+\t\t} else if (starts_with(name, \"rest\")) {\n+\t\t\tv->s = ref->rest ? ref->rest : \"\";\n+\t\t\tcontinue;\n+\t\t} else if (starts_with(name, \"deltabase\")) {\n+\t\t\tif (ref->delta_base_oid)\n+\t\t\t\tv->s = xstrdup(oid_to_hex(ref->delta_base_oid));\n+\t\t\telse\n+\t\t\t\tv->s = \"\";\n+\t\t\tcontinue;\n \t\t} else if (starts_with(name, \"align\")) {\n \t\t\tv->handler = align_atom_handler;\n \t\t\tcontinue;\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337531","messageId":"0102016133ff3b3b-a0ab669e-bc4b-4a25-ac66-5365c56856b1-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 13/24] ref-filter: add is_cat flag","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:18Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add is_cat flag, further it helps to get rid of cat_file_data field\nin ref_format.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 1 +\n ref-filter.c       | 8 +++++---\n ref-filter.h       | 1 +\n 3 files changed, 7 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex c2ca645662ae7..8f34d085962ed 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -394,6 +394,7 @@ static int batch_objects(struct batch_options *opt)\n \t */\n \tmemset(&data, 0, sizeof(data));\n \topt->format.cat_file_data = &data;\n+\topt->format.is_cat = 1;\n \tverify_ref_format(&opt->format);\n \tif (opt->cmdmode)\n \t\tdata.split_on_whitespace = 1;\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 8d10d356609e7..3b61e790e90d1 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -101,6 +101,7 @@ static struct used_atom {\n } *used_atom;\n static int used_atom_cnt, need_tagged, need_symref;\n struct expand_data *cat_file_info;\n+static int is_cat = 0;\n \n static void color_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *color_value)\n {\n@@ -493,7 +494,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,\n \t\tneed_tagged = 1;\n \tif (!strcmp(valid_atom[i].name, \"symref\"))\n \t\tneed_symref = 1;\n-\tif (cat_file_info && !strcmp(valid_atom[i].name, \"rest\"))\n+\tif (is_cat && !strcmp(valid_atom[i].name, \"rest\"))\n \t\tcat_file_info->split_on_whitespace = 1;\n \treturn at;\n }\n@@ -739,6 +740,7 @@ int verify_ref_format(struct ref_format *format)\n \tconst char *cp, *sp;\n \n \tcat_file_info = format->cat_file_data;\n+\tis_cat = format->is_cat;\n \tformat->need_color_reset_at_eol = 0;\n \tfor (cp = format->format; *cp && (sp = find_next(cp)); ) {\n \t\tconst char *color, *ep = strchr(sp, ')');\n@@ -748,7 +750,7 @@ int verify_ref_format(struct ref_format *format)\n \t\t\treturn error(_(\"malformed format string %s\"), sp);\n \t\t/* sp points at \"%(\" and ep points at the closing \")\" */\n \n-\t\tif (format->cat_file_data) {\n+\t\tif (is_cat) {\n \t\t\tat = parse_ref_filter_atom(format, valid_cat_file_atom,\n \t\t\t\t\t\t   ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);\n \t\t} else {\n@@ -1481,7 +1483,7 @@ int populate_value(struct ref_array_item *ref)\n \t\t\tref->symref = \"\";\n \t}\n \n-\tif (cat_file_info && check_and_fill_for_cat(ref))\n+\tif (is_cat && check_and_fill_for_cat(ref))\n \t\treturn -1;\n \n \t/* Fill in specials first */\ndiff --git a/ref-filter.h b/ref-filter.h\nindex e41d2913c0fff..c848370bed84a 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -126,6 +126,7 @@ struct ref_format {\n \t * hopefully would be reduced later.\n \t */\n \tstruct expand_data *cat_file_data;\n+\tint is_cat;\n };\n \n #define REF_FORMAT_INIT { NULL, 0, -1 }\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337532","messageId":"0102016133ff3b3f-26fceb2a-c1ef-447b-9013-caccccc052f9-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 17/24] cat-file: reuse printing logic from ref-filter","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:20Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Reuse code from ref-filter to print resulting message.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 52 +++++-----------------------------------------------\n ref-filter.c       | 30 +++++++++++++++++++++++++++---\n 2 files changed, 32 insertions(+), 50 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex bd803856537b8..26b35bef4ba02 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -176,45 +176,6 @@ 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\t struct ref_array_item *item)\n-{\n-\tif (is_atom(\"objectname\", atom, len))\n-\t\tstrbuf_addstr(sb, oid_to_hex(&item->objectname));\n-\telse if (is_atom(\"objecttype\", atom, len))\n-\t\tstrbuf_addstr(sb, typename(item->type));\n-\telse if (is_atom(\"objectsize\", atom, len))\n-\t\tstrbuf_addf(sb, \"%lu\", item->size);\n-\telse if (is_atom(\"objectsize:disk\", atom, len))\n-\t\tstrbuf_addf(sb, \"%\"PRIuMAX, (uintmax_t)item->disk_size);\n-\telse if (is_atom(\"rest\", atom, len)) {\n-\t\tif (item->rest)\n-\t\t\tstrbuf_addstr(sb, item->rest);\n-\t} else if (is_atom(\"deltabase\", atom, len))\n-\t\tstrbuf_addstr(sb, oid_to_hex(item->delta_base_oid));\n-}\n-\n-static size_t expand_format(struct strbuf *sb, const char *start, void *data)\n-{\n-\tconst char *end;\n-\tstruct ref_array_item *item = data;\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, item);\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@@ -282,22 +243,19 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d\n static void batch_object_write(const char *obj_name, struct batch_options *opt,\n \t\t\t       struct expand_data *data)\n {\n-\tstruct strbuf buf = STRBUF_INIT;\n \tstruct ref_array_item item = {0};\n \n \titem.objectname = data->oid;\n \titem.rest = data->rest;\n \titem.start_of_request = obj_name;\n \n-\tif (populate_value(&item)) return;\n-\tdata->type = item.type;\n-\n-\tstrbuf_expand(&buf, opt->format.format, expand_format, &item);\n-\tstrbuf_addch(&buf, '\\n');\n-\tbatch_write(opt, buf.buf, buf.len);\n-\tstrbuf_release(&buf);\n+\tif (show_ref_array_item(&item, &opt->format))\n+\t\treturn;\n+\tif (!opt->buffer_output)\n+\t\tfflush(stdout);\n \n \tif (opt->print_contents) {\n+\t\tdata->type = item.type;\n \t\tprint_object_or_die(opt, data);\n \t\tbatch_write(opt, \"\\n\", 1);\n \t}\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 906a5344949f7..bfbc7c83fdd47 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1522,7 +1522,21 @@ int populate_value(struct ref_array_item *ref)\n \t\t\tname++;\n \t\t}\n \n-\t\tif (starts_with(name, \"refname\"))\n+\t\tif (is_cat) {\n+\t\t\tif (starts_with(name, \"objectname\"))\n+\t\t\t\tv->s = oid_to_hex(&ref->objectname);\n+\t\t\telse if (starts_with(name, \"objecttype\"))\n+\t\t\t\tv->s = typename(ref->type);\n+\t\t\telse if (starts_with(name, \"objectsize\")) {\n+\t\t\t\tv->s = xstrfmt(\"%lu\", ref->size);\n+\t\t\t} else if (starts_with(name, \"objectsize:disk\")) {\n+\t\t\t\tv->s = xstrfmt(\"%\"PRIuMAX, (uintmax_t)ref->disk_size);\n+\t\t\t} else if (starts_with(name, \"rest\"))\n+\t\t\t\tv->s = ref->rest;\n+\t\t\telse if (starts_with(name, \"deltabase\"))\n+\t\t\t\tv->s = xstrdup(oid_to_hex(ref->delta_base_oid));\n+\t\t\tcontinue;\n+\t\t} else if (starts_with(name, \"refname\"))\n \t\t\trefname = get_refname(atom, ref);\n \t\telse if (starts_with(name, \"symref\"))\n \t\t\trefname = get_symref(atom, ref);\n@@ -2219,6 +2233,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+\tint retval = 0;\n \n \tstate.quote_style = format->quote_style;\n \tpush_stack_element(&state.stack);\n@@ -2229,13 +2244,22 @@ int format_ref_array_item(struct ref_array_item *info,\n \t\tep = strchr(sp, ')');\n \t\tif (cp < sp)\n \t\t\tappend_literal(cp, sp, &state);\n-\t\tget_ref_atom_value(info,\n+\t\tif (is_cat) {\n+\t\t\tif(get_ref_atom_value(info,\n+\t\t\t\tparse_ref_filter_atom(format, valid_cat_file_atom,\n+\t\t\t\t\tARRAY_SIZE(valid_cat_file_atom), sp + 2, ep),\n+\t\t\t\t\t&atomv))\n+\t\t\t\treturn -1;\n+\t\t} else\n+\t\t\tget_ref_atom_value(info,\n \t\t\t\t   parse_ref_filter_atom(format, valid_atom,\n \t\t\t\t\t\t\t ARRAY_SIZE(valid_atom),\n \t\t\t\t\t\t\t sp + 2, ep),\n \t\t\t\t   &atomv);\n \t\tatomv->handler(atomv, &state);\n \t}\n+\tif (is_cat && strlen(format->format) == 0)\n+\t\tretval = check_and_fill_for_cat(info);\n \tif (*cp) {\n \t\tsp = cp + strlen(cp);\n \t\tappend_literal(cp, sp, &state);\n@@ -2249,7 +2273,7 @@ int format_ref_array_item(struct ref_array_item *info,\n \t\tdie(_(\"format: %%(end) atom missing\"));\n \tstrbuf_addbuf(final_buf, &state.stack->output);\n \tpop_stack_element(&state.stack);\n-\treturn 0;\n+\treturn retval;\n }\n \n int show_ref_array_item(struct ref_array_item *info,\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337533","messageId":"0102016133ff3b3d-001897ca-5d18-45e6-bd4c-118aa9a3d659-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 16/24] ref-filter: make cat_file_info independent","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:23Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Remove connection between expand_data variable\nin cat-file and in ref-filter.\nIt will help further to get rid of using expand_data in cat-file.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c |  2 +-\n ref-filter.c       | 29 +++++++++++++++--------------\n ref-filter.h       |  1 -\n 3 files changed, 16 insertions(+), 16 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 3a52c551f366a..bd803856537b8 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -290,6 +290,7 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,\n \titem.start_of_request = obj_name;\n \n \tif (populate_value(&item)) return;\n+\tdata->type = item.type;\n \n \tstrbuf_expand(&buf, opt->format.format, expand_format, &item);\n \tstrbuf_addch(&buf, '\\n');\n@@ -392,7 +393,6 @@ static int batch_objects(struct batch_options *opt)\n \t * object.\n \t */\n \tmemset(&data, 0, sizeof(data));\n-\topt->format.cat_file_data = &data;\n \topt->format.is_cat = 1;\n \topt->format.all_objects = opt->all_objects;\n \tverify_ref_format(&opt->format);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 29a1b75c93181..906a5344949f7 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -100,7 +100,7 @@ static struct used_atom {\n \t} u;\n } *used_atom;\n static int used_atom_cnt, need_tagged, need_symref;\n-struct expand_data *cat_file_info;\n+struct expand_data cat_file_info;\n static int is_cat = 0;\n \n static void color_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *color_value)\n@@ -256,9 +256,9 @@ static void objectname_atom_parser(const struct ref_format *format, struct used_\n static void objectsize_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n {\n \tif (!arg)\n-\t\tcat_file_info->info.sizep = &cat_file_info->size;\n+\t\tcat_file_info.info.sizep = &cat_file_info.size;\n \telse if (!strcmp(arg, \"disk\"))\n-\t\tcat_file_info->info.disk_sizep = &cat_file_info->disk_size;\n+\t\tcat_file_info.info.disk_sizep = &cat_file_info.disk_size;\n \telse\n \t\tdie(_(\"urecognized %%(objectsize) argument: %s\"), arg);\n }\n@@ -266,7 +266,7 @@ static void objectsize_atom_parser(const struct ref_format *format, struct used_\n static void objecttype_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n {\n \tif (!arg)\n-\t\tcat_file_info->info.typep = &cat_file_info->type;\n+\t\tcat_file_info.info.typep = &cat_file_info.type;\n \telse\n \t\tdie(_(\"urecognized %%(objecttype) argument: %s\"), arg);\n }\n@@ -274,7 +274,7 @@ static void objecttype_atom_parser(const struct ref_format *format, struct used_\n static void deltabase_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n {\n \tif (!arg)\n-\t\tcat_file_info->info.delta_base_sha1 = cat_file_info->delta_base_oid.hash;\n+\t\tcat_file_info.info.delta_base_sha1 = cat_file_info.delta_base_oid.hash;\n \telse\n \t\tdie(_(\"urecognized %%(deltabase) argument: %s\"), arg);\n }\n@@ -752,7 +752,6 @@ int verify_ref_format(struct ref_format *format)\n {\n \tconst char *cp, *sp;\n \n-\tcat_file_info = format->cat_file_data;\n \tis_cat = format->is_cat;\n \tformat->need_color_reset_at_eol = 0;\n \tfor (cp = format->format; *cp && (sp = find_next(cp)); ) {\n@@ -779,8 +778,8 @@ int verify_ref_format(struct ref_format *format)\n \t\tformat->need_color_reset_at_eol = 0;\n \tif (is_cat && format->all_objects) {\n \t\tstruct object_info empty = OBJECT_INFO_INIT;\n-\t\tif (!memcmp(&cat_file_info->info, &empty, sizeof(empty)))\n-\t\t\tcat_file_info->skip_object_info = 1;\n+\t\tif (!memcmp(&cat_file_info.info, &empty, sizeof(empty)))\n+\t\t\tcat_file_info.skip_object_info = 1;\n \t}\n \treturn 0;\n }\n@@ -1470,18 +1469,20 @@ static void need_object(struct ref_array_item *ref) {\n \n static int check_and_fill_for_cat(struct ref_array_item *ref)\n {\n-\tif (!cat_file_info->skip_object_info &&\n-\t    sha1_object_info_extended(ref->objectname.hash, &cat_file_info->info,\n+\tif (!cat_file_info.info.typep)\n+\t\tcat_file_info.info.typep = &cat_file_info.type;\n+\tif (!cat_file_info.skip_object_info &&\n+\t    sha1_object_info_extended(ref->objectname.hash, &cat_file_info.info,\n \t\t\t\t      OBJECT_INFO_LOOKUP_REPLACE) < 0) {\n \t\tconst char *e = ref->start_of_request;\n \t\tprintf(\"%s missing\\n\", e ? e : oid_to_hex(&ref->objectname));\n \t\tfflush(stdout);\n \t\treturn -1;\n \t}\n-\tref->type = cat_file_info->type;\n-\tref->size = cat_file_info->size;\n-\tref->disk_size = cat_file_info->disk_size;\n-\tref->delta_base_oid = &cat_file_info->delta_base_oid;\n+\tref->type = cat_file_info.type;\n+\tref->size = cat_file_info.size;\n+\tref->disk_size = cat_file_info.disk_size;\n+\tref->delta_base_oid = &cat_file_info.delta_base_oid;\n \treturn 0;\n }\n \ndiff --git a/ref-filter.h b/ref-filter.h\nindex 4af89c4c86bee..d8064086f36a9 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -118,7 +118,6 @@ struct ref_format {\n \t * Helps to move all formatting logic from cat-file to ref-filter,\n \t * hopefully would be reduced later.\n \t */\n-\tstruct expand_data *cat_file_data;\n \tint is_cat;\n \tint all_objects;\n };\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337534","messageId":"0102016133ff3b3d-58cb3635-e54a-4473-a12c-78351f613c2c-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 14/24] ref_filter: add is_rest_atom_used function","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:26Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Delete all items related to split_on_whitespace from ref-filter\nand add new function for handling the logic.\nNow cat-file could invoke that function to implementing its logic.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c |  8 +++-----\n ref-filter.c       | 17 +++++++++++++++--\n ref-filter.h       | 10 +++-------\n 3 files changed, 21 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 8f34d085962ed..601a87d9b5f7c 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -381,8 +381,7 @@ static int batch_objects(struct batch_options *opt)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct expand_data data;\n-\tint save_warning;\n-\tint retval = 0;\n+\tint save_warning, is_rest, retval = 0;\n \n \tif (!opt->format.format)\n \t\topt->format.format = \"%(objectname) %(objecttype) %(objectsize)\";\n@@ -396,8 +395,6 @@ static int batch_objects(struct batch_options *opt)\n \topt->format.cat_file_data = &data;\n \topt->format.is_cat = 1;\n \tverify_ref_format(&opt->format);\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@@ -436,9 +433,10 @@ static int batch_objects(struct batch_options *opt)\n \t */\n \tsave_warning = warn_on_object_refname_ambiguity;\n \twarn_on_object_refname_ambiguity = 0;\n+\tis_rest = opt->cmdmode || is_rest_atom_used(&opt->format);\n \n \twhile (strbuf_getline(&buf, 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\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 3b61e790e90d1..51da76dc21136 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -494,8 +494,6 @@ static int parse_ref_filter_atom(const struct ref_format *format,\n \t\tneed_tagged = 1;\n \tif (!strcmp(valid_atom[i].name, \"symref\"))\n \t\tneed_symref = 1;\n-\tif (is_cat && !strcmp(valid_atom[i].name, \"rest\"))\n-\t\tcat_file_info->split_on_whitespace = 1;\n \treturn at;\n }\n \n@@ -731,6 +729,21 @@ static const char *find_next(const char *cp)\n \treturn NULL;\n }\n \n+/* Search for atom \"rest\" in given format. */\n+int is_rest_atom_used(const struct ref_format *format)\n+{\n+\tconst char *cp, *sp;\n+\tfor (cp = format->format; *cp && (sp = find_next(cp)); ) {\n+\t\tconst char *ep = strchr(sp, ')');\n+\t\tint atom_len = ep - sp - 2;\n+\t\tsp += 2;\n+\t\tif (atom_len == 4 && !memcmp(sp, \"rest\", atom_len))\n+\t\t\treturn 1;\n+\t\tcp = ep + 1;\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * Make sure the format string is well formed, and parse out\n  * the used atoms.\ndiff --git a/ref-filter.h b/ref-filter.h\nindex c848370bed84a..276de387f3bd0 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -87,13 +87,6 @@ struct expand_data {\n \tconst char *rest;\n \tstruct object_id delta_base_oid;\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 sha1_object_info_extended. It will point to the data\n@@ -182,4 +175,7 @@ void pretty_print_ref(const char *name, const unsigned char *sha1,\n /* Fill the values of request and prepare all data for final string creation */\n int populate_value(struct ref_array_item *ref);\n \n+/* Search for atom \"rest\" in given format. */\n+int is_rest_atom_used(const struct ref_format *format);\n+\n #endif /*  REF_FILTER_H  */\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337535","messageId":"0102016133ff3b27-2758b620-815d-4289-9714-9c6aea69e3ab-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 12/24] ref-filter: get rid of expand_atom_into_fields","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:29Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Remove expand_atom_into_fields function and create same logic\nin terms of ref-filter style.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 45 +++++++++++++++++++++------------------------\n 1 file changed, 21 insertions(+), 24 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 12ca236815411..8d10d356609e7 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -255,13 +255,29 @@ static void objectname_atom_parser(const struct ref_format *format, struct used_\n static void objectsize_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n {\n \tif (!arg)\n-\t\t; /* default to normal object size */\n+\t\tcat_file_info->info.sizep = &cat_file_info->size;\n \telse if (!strcmp(arg, \"disk\"))\n \t\tcat_file_info->info.disk_sizep = &cat_file_info->disk_size;\n \telse\n \t\tdie(_(\"urecognized %%(objectsize) argument: %s\"), arg);\n }\n \n+static void objecttype_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n+{\n+\tif (!arg)\n+\t\tcat_file_info->info.typep = &cat_file_info->type;\n+\telse\n+\t\tdie(_(\"urecognized %%(objecttype) argument: %s\"), arg);\n+}\n+\n+static void deltabase_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n+{\n+\tif (!arg)\n+\t\tcat_file_info->info.delta_base_sha1 = cat_file_info->delta_base_oid.hash;\n+\telse\n+\t\tdie(_(\"urecognized %%(deltabase) argument: %s\"), arg);\n+}\n+\n static void refname_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n {\n \trefname_atom_parser_internal(&atom->u.refname, arg, atom->name);\n@@ -384,10 +400,10 @@ static struct valid_atom {\n \n static struct valid_atom valid_cat_file_atom[] = {\n \t{ \"objectname\" },\n-\t{ \"objecttype\" },\n+\t{ \"objecttype\", FIELD_STR, objecttype_atom_parser },\n \t{ \"objectsize\", FIELD_ULONG, objectsize_atom_parser },\n \t{ \"rest\" },\n-\t{ \"deltabase\" },\n+\t{ \"deltabase\", FIELD_STR, deltabase_atom_parser },\n };\n \n #define REF_FORMATTING_STATE_INIT  { 0, NULL }\n@@ -411,25 +427,6 @@ struct atom_value {\n \tstruct used_atom *atom;\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_into_fields(const char *atom, int len,\n-\t\t\t\t    struct expand_data *data)\n-{\n-\tif (is_atom(\"objecttype\", atom, len))\n-\t\tdata->info.typep = &data->type;\n-\telse if (is_atom(\"objectsize\", atom, len))\n-\t\tdata->info.sizep = &data->size;\n-\telse if (is_atom(\"rest\", atom, len))\n-\t\tdata->split_on_whitespace = 1;\n-\telse if (is_atom(\"deltabase\", atom, len))\n-\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n-}\n-\n /*\n  * Used to parse format string and sort specifiers\n  */\n@@ -496,8 +493,8 @@ static int parse_ref_filter_atom(const struct ref_format *format,\n \t\tneed_tagged = 1;\n \tif (!strcmp(valid_atom[i].name, \"symref\"))\n \t\tneed_symref = 1;\n-\tif (cat_file_info)\n-\t\texpand_atom_into_fields(atom, atom_len, cat_file_info);\n+\tif (cat_file_info && !strcmp(valid_atom[i].name, \"rest\"))\n+\t\tcat_file_info->split_on_whitespace = 1;\n \treturn at;\n }\n \n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337536","messageId":"0102016133ff3b1b-dcaaf82b-b21b-49b9-b21c-85f55873bd09-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 11/24] cat-file: start reusing populate_value","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:32Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Move logic related to getting object info from cat-file to ref-filter.\nIt will help to reuse whole formatting logic from ref-filter further.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 16 +++-------------\n ref-filter.c       | 20 ++++++++++++++++++++\n ref-filter.h       |  2 ++\n 3 files changed, 25 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 61b7acc79155d..c2ca645662ae7 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -285,21 +285,11 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct ref_array_item item = {0};\n \n-\tif (!data->skip_object_info &&\n-\t    sha1_object_info_extended(data->oid.hash, &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-\t\tfflush(stdout);\n-\t\treturn;\n-\t}\n-\n \titem.objectname = data->oid;\n-\titem.type = data->type;\n-\titem.size = data->size;\n-\titem.disk_size = data->disk_size;\n \titem.rest = data->rest;\n-\titem.delta_base_oid = &data->delta_base_oid;\n+\titem.start_of_request = obj_name;\n+\n+\tif (populate_value(&item)) return;\n \n \tstrbuf_expand(&buf, opt->format.format, expand_format, &item);\n \tstrbuf_addch(&buf, '\\n');\ndiff --git a/ref-filter.c b/ref-filter.c\nindex e69dd1ff5091f..12ca236815411 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1451,6 +1451,23 @@ static void need_object(struct ref_array_item *ref) {\n \t\tfree(buf);\n }\n \n+static int check_and_fill_for_cat(struct ref_array_item *ref)\n+{\n+\tif (!cat_file_info->skip_object_info &&\n+\t    sha1_object_info_extended(ref->objectname.hash, &cat_file_info->info,\n+\t\t\t\t      OBJECT_INFO_LOOKUP_REPLACE) < 0) {\n+\t\tconst char *e = ref->start_of_request;\n+\t\tprintf(\"%s missing\\n\", e ? e : oid_to_hex(&ref->objectname));\n+\t\tfflush(stdout);\n+\t\treturn -1;\n+\t}\n+\tref->type = cat_file_info->type;\n+\tref->size = cat_file_info->size;\n+\tref->disk_size = cat_file_info->disk_size;\n+\tref->delta_base_oid = &cat_file_info->delta_base_oid;\n+\treturn 0;\n+}\n+\n /*\n  * Parse the object referred by ref, and grab needed value.\n  */\n@@ -1467,6 +1484,9 @@ int populate_value(struct ref_array_item *ref)\n \t\t\tref->symref = \"\";\n \t}\n \n+\tif (cat_file_info && check_and_fill_for_cat(ref))\n+\t\treturn -1;\n+\n \t/* Fill in specials first */\n \tfor (i = 0; i < used_atom_cnt; i++) {\n \t\tstruct used_atom *atom = &used_atom[i];\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 6373167aaacd7..e41d2913c0fff 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -45,6 +45,8 @@ struct ref_array_item {\n \toff_t disk_size;\n \tconst char *rest;\n \tstruct object_id *delta_base_oid;\n+\t/* Need it for better explanation in error log. */\n+\tconst char *start_of_request;\n \tchar refname[FLEX_ARRAY];\n };\n \n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337537","messageId":"0102016133ff3ad8-abf99952-4df0-42a4-9ae9-06f602e84f3b-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 02/24] ref-filter: add return value to some functions","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:37Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Add return flag to format_ref_array_item, show_ref_array_item,\nget_ref_array_info and populate_value for further using.\nNeed it to handle situations when item is broken but we can not invoke\ndie() because we are in batch mode and all items need to be processed.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 21 +++++++++++++--------\n ref-filter.h |  4 ++--\n 2 files changed, 15 insertions(+), 10 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 37337b57aacf4..7030d35c84a81 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1405,7 +1405,7 @@ static void need_object(struct ref_array_item *ref) {\n /*\n  * Parse the object referred by ref, and grab needed value.\n  */\n-static void populate_value(struct ref_array_item *ref)\n+static int populate_value(struct ref_array_item *ref)\n {\n \tint i;\n \n@@ -1526,20 +1526,22 @@ static void populate_value(struct ref_array_item *ref)\n \t\t\tbreak;\n \t\t}\n \t}\n-\treturn;\n+\treturn 0;\n }\n \n /*\n  * Given a ref, return the value for the atom.  This lazily gets value\n  * out of the object by calling populate value.\n  */\n-static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom_value **v)\n+static int get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom_value **v)\n {\n+\tint retval = 0;\n \tif (!ref->value) {\n-\t\tpopulate_value(ref);\n+\t\tretval = populate_value(ref);\n \t\tfill_missing_values(ref->value);\n \t}\n \t*v = &ref->value[atom];\n+\treturn retval;\n }\n \n /*\n@@ -2124,7 +2126,7 @@ static void append_literal(const char *cp, const char *ep, struct ref_formatting\n \t}\n }\n \n-void format_ref_array_item(struct ref_array_item *info,\n+int format_ref_array_item(struct ref_array_item *info,\n \t\t\t   const struct ref_format *format,\n \t\t\t   struct strbuf *final_buf)\n {\n@@ -2158,17 +2160,20 @@ void format_ref_array_item(struct ref_array_item *info,\n \t\tdie(_(\"format: %%(end) atom missing\"));\n \tstrbuf_addbuf(final_buf, &state.stack->output);\n \tpop_stack_element(&state.stack);\n+\treturn 0;\n }\n \n-void show_ref_array_item(struct ref_array_item *info,\n+int show_ref_array_item(struct ref_array_item *info,\n \t\t\t const struct ref_format *format)\n {\n \tstruct strbuf final_buf = STRBUF_INIT;\n+\tint retval = format_ref_array_item(info, format, &final_buf);\n \n-\tformat_ref_array_item(info, format, &final_buf);\n \tfwrite(final_buf.buf, 1, final_buf.len, stdout);\n \tstrbuf_release(&final_buf);\n-\tputchar('\\n');\n+\tif (!retval)\n+\t\tputchar('\\n');\n+\treturn retval;\n }\n \n void pretty_print_ref(const char *name, const unsigned char *sha1,\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 0d98342b34319..ff416b733b4b1 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -110,11 +110,11 @@ int verify_ref_format(struct ref_format *format);\n /*  Sort the given ref_array as per the ref_sorting provided */\n void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);\n /*  Based on the given format and quote_style, fill the strbuf */\n-void format_ref_array_item(struct ref_array_item *info,\n+int format_ref_array_item(struct ref_array_item *info,\n \t\t\t   const struct ref_format *format,\n \t\t\t   struct strbuf *final_buf);\n /*  Print the ref using the given format and quote_style */\n-void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format);\n+int show_ref_array_item(struct ref_array_item *info, const struct ref_format *format);\n /*  Parse a single sort specifier and add it to the list */\n void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *atom);\n /*  Callback function for parsing the sort option */\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337538","messageId":"0102016133ff3b0d-d1f39e25-3569-4703-92ef-49355ea03aa2-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 08/24] ref-filter: reuse parse_ref_filter_atom","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:39Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Continue migrating formatting logic from cat-file to ref-filter.\nReuse parse_ref_filter_atom for unifying all processes in ref-filter\nand further reducing of expand_atom_into_fields function.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 38 +++++++++++++++++++++++++++-----------\n 1 file changed, 27 insertions(+), 11 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 8e384b2818b22..95c85009f1f58 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -100,6 +100,7 @@ static struct used_atom {\n \t} u;\n } *used_atom;\n static int used_atom_cnt, need_tagged, need_symref;\n+struct expand_data *cat_file_info;\n \n static void color_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *color_value)\n {\n@@ -251,6 +252,16 @@ static void objectname_atom_parser(const struct ref_format *format, struct used_\n \t\tdie(_(\"unrecognized %%(objectname) argument: %s\"), arg);\n }\n \n+static void objectsize_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n+{\n+\tif (!arg)\n+\t\t; /* default to normal object size */\n+\telse if (!strcmp(arg, \"disk\"))\n+\t\tcat_file_info->info.disk_sizep = &cat_file_info->disk_size;\n+\telse\n+\t\tdie(_(\"urecognized %%(objectsize) argument: %s\"), arg);\n+}\n+\n static void refname_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)\n {\n \trefname_atom_parser_internal(&atom->u.refname, arg, atom->name);\n@@ -371,6 +382,14 @@ static struct valid_atom {\n \t{ \"else\" },\n };\n \n+static struct valid_atom valid_cat_file_atom[] = {\n+\t{ \"objectname\" },\n+\t{ \"objecttype\" },\n+\t{ \"objectsize\", FIELD_ULONG, objectsize_atom_parser },\n+\t{ \"rest\" },\n+\t{ \"deltabase\" },\n+};\n+\n #define REF_FORMATTING_STATE_INIT  { 0, NULL }\n \n struct ref_formatting_stack {\n@@ -401,20 +420,14 @@ static int is_atom(const char *atom, const char *s, int slen)\n static void expand_atom_into_fields(const char *atom, int len,\n \t\t\t\t    struct expand_data *data)\n {\n-\tif (is_atom(\"objectname\", atom, len))\n-\t\t; /* do nothing */\n-\telse if (is_atom(\"objecttype\", atom, len))\n+\tif (is_atom(\"objecttype\", atom, len))\n \t\tdata->info.typep = &data->type;\n \telse if (is_atom(\"objectsize\", atom, len))\n \t\tdata->info.sizep = &data->size;\n-\telse if (is_atom(\"objectsize:disk\", atom, len))\n-\t\tdata->info.disk_sizep = &data->disk_size;\n \telse if (is_atom(\"rest\", atom, len))\n \t\tdata->split_on_whitespace = 1;\n \telse if (is_atom(\"deltabase\", atom, len))\n \t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n-\telse\n-\t\tdie(\"unknown format element: %.*s\", len, atom);\n }\n \n /*\n@@ -483,6 +496,8 @@ static int parse_ref_filter_atom(const struct ref_format *format,\n \t\tneed_tagged = 1;\n \tif (!strcmp(valid_atom[i].name, \"symref\"))\n \t\tneed_symref = 1;\n+\tif (cat_file_info)\n+\t\texpand_atom_into_fields(atom, atom_len, cat_file_info);\n \treturn at;\n }\n \n@@ -726,6 +741,7 @@ int verify_ref_format(struct ref_format *format)\n {\n \tconst char *cp, *sp;\n \n+\tcat_file_info = format->cat_file_data;\n \tformat->need_color_reset_at_eol = 0;\n \tfor (cp = format->format; *cp && (sp = find_next(cp)); ) {\n \t\tconst char *color, *ep = strchr(sp, ')');\n@@ -735,10 +751,10 @@ int verify_ref_format(struct ref_format *format)\n \t\t\treturn error(_(\"malformed format string %s\"), sp);\n \t\t/* sp points at \"%(\" and ep points at the closing \")\" */\n \n-\t\tif (format->cat_file_data)\n-\t\t\texpand_atom_into_fields(sp + 2, ep - sp - 2,\n-\t\t\t\t\t\tformat->cat_file_data);\n-\t\telse {\n+\t\tif (format->cat_file_data) {\n+\t\t\tat = parse_ref_filter_atom(format, valid_cat_file_atom,\n+\t\t\t\t\t\t   ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);\n+\t\t} else {\n \t\t\tat = parse_ref_filter_atom(format, valid_atom,\n \t\t\t\t\t\t   ARRAY_SIZE(valid_atom), sp + 2, ep);\n \t\t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337539","messageId":"0102016133ff3b0c-042864ef-1f19-4991-a240-7358c56daec9-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 06/24] cat-file: move struct expand_data into ref-filter","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:42Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Need that for further reusing of formatting logic in cat-file.\nHave plans to get rid of using expand_data in cat-file at all,\nand use it only in ref-filter for collecting, formatting and printing\nneeded data.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 36 ------------------------------------\n ref-filter.h       | 36 ++++++++++++++++++++++++++++++++++++\n 2 files changed, 36 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 65c300184cab8..490d9f8a8a922 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -176,42 +176,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-\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 * 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 sha1_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-\t/*\n-\t * This flag will be true if the requested batch format and options\n-\t * don't require us to call sha1_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 {\n \tint alen = strlen(atom);\ndiff --git a/ref-filter.h b/ref-filter.h\nindex ff416b733b4b1..56093a85d52b8 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -72,6 +72,42 @@ 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+\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 * 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 sha1_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+\t/*\n+\t * This flag will be true if the requested batch format and options\n+\t * don't require us to call sha1_object_info, which can then be\n+\t * optimized out.\n+\t */\n+\tunsigned skip_object_info : 1;\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/452\n"},{"id":"337540","messageId":"0102016133ff3b53-0d7be81e-3350-4d32-bbb1-b108a1b27c41-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 21/24] ref-filter: work with objectsize:disk","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:44Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Make a temporary solution for commands that could use\nobjectsize:disk atom.\nIt's better to fill it with value or give an error if there is no value\nfor this atom, but as a first solution we do dothing.\nIt means that if objectsize:disk is used, we put an empty string there.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 2cac394e93f52..bf49ed21eaac5 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -826,8 +826,10 @@ static void grab_common_values(struct atom_value *val, int deref, struct object\n \t\t\tv->value = sz;\n \t\t\tv->s = xstrfmt(\"%lu\", sz);\n \t\t} else if (!strcmp(name, \"objectsize:disk\")) {\n-\t\t\tv->value = cat_file_info.disk_size;\n-\t\t\tv->s = xstrfmt(\"%\"PRIuMAX, (uintmax_t)v->value);\n+\t\t\tif (is_cat) {\n+\t\t\t\tv->value = cat_file_info.disk_size;\n+\t\t\t\tv->s = xstrfmt(\"%\"PRIuMAX, (uintmax_t)v->value);\n+\t\t\t}\n \t\t} else if (deref)\n \t\t\tgrab_objectname(name, obj->oid.hash, v, &used_atom[i]);\n \t}\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337541","messageId":"0102016133ff3afa-721294ba-c691-4b45-b3a8-622525285902-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 05/24] ref-filter: make valid_atom as function parameter","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:47Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Make valid_atom as a function parameter,\nthere could be another variable further.\nNeed that for further reusing of formatting logic in cat-file.c.\n\nWe do not need to allow users to pass their own valid_atom variable in\nglobal functions like verify_ref_format because in the end we want to\nhave same set of valid atoms for all commands. But, as a first step\nof migrating, I create further another version of valid_atom\nfor cat-file.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n ref-filter.c | 17 +++++++++++------\n 1 file changed, 11 insertions(+), 6 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 7030d35c84a81..ee2aa7d6d072b 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -325,7 +325,7 @@ static void head_atom_parser(const struct ref_format *format, struct used_atom *\n \tatom->u.head = resolve_refdup(\"HEAD\", RESOLVE_REF_READING, NULL, NULL);\n }\n \n-static struct {\n+static struct valid_atom {\n \tconst char *name;\n \tcmp_type cmp_type;\n \tvoid (*parser)(const struct ref_format *format, struct used_atom *atom, const char *arg);\n@@ -396,6 +396,7 @@ struct atom_value {\n  * Used to parse format string and sort specifiers\n  */\n static int parse_ref_filter_atom(const struct ref_format *format,\n+\t\t\t\t const struct valid_atom *valid_atom, int n_atoms,\n \t\t\t\t const char *atom, const char *ep)\n {\n \tconst char *sp;\n@@ -425,13 +426,13 @@ static int parse_ref_filter_atom(const struct ref_format *format,\n \tatom_len = (arg ? arg : ep) - sp;\n \n \t/* Is the atom a valid one? */\n-\tfor (i = 0; i < ARRAY_SIZE(valid_atom); i++) {\n+\tfor (i = 0; i < n_atoms; i++) {\n \t\tint len = strlen(valid_atom[i].name);\n \t\tif (len == atom_len && !memcmp(valid_atom[i].name, sp, len))\n \t\t\tbreak;\n \t}\n \n-\tif (ARRAY_SIZE(valid_atom) <= i)\n+\tif (n_atoms <= i)\n \t\tdie(_(\"unknown field name: %.*s\"), (int)(ep-atom), atom);\n \n \t/* Add it in, including the deref prefix */\n@@ -708,7 +709,8 @@ int verify_ref_format(struct ref_format *format)\n \t\tif (!ep)\n \t\t\treturn error(_(\"malformed format string %s\"), sp);\n \t\t/* sp points at \"%(\" and ep points at the closing \")\" */\n-\t\tat = parse_ref_filter_atom(format, sp + 2, ep);\n+\t\tat = parse_ref_filter_atom(format, valid_atom,\n+\t\t\t\t\t   ARRAY_SIZE(valid_atom), sp + 2, ep);\n \t\tcp = ep + 1;\n \n \t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n@@ -2143,7 +2145,9 @@ int format_ref_array_item(struct ref_array_item *info,\n \t\tif (cp < sp)\n \t\t\tappend_literal(cp, sp, &state);\n \t\tget_ref_atom_value(info,\n-\t\t\t\t   parse_ref_filter_atom(format, sp + 2, ep),\n+\t\t\t\t   parse_ref_filter_atom(format, valid_atom,\n+\t\t\t\t\t\t\t ARRAY_SIZE(valid_atom),\n+\t\t\t\t\t\t\t sp + 2, ep),\n \t\t\t\t   &atomv);\n \t\tatomv->handler(atomv, &state);\n \t}\n@@ -2194,7 +2198,8 @@ static int parse_sorting_atom(const char *atom)\n \t */\n \tstruct ref_format dummy = REF_FORMAT_INIT;\n \tconst char *end = atom + strlen(atom);\n-\treturn parse_ref_filter_atom(&dummy, atom, end);\n+\treturn parse_ref_filter_atom(&dummy, valid_atom,\n+\t\t\t\t     ARRAY_SIZE(valid_atom), atom, end);\n }\n \n /*  If no sorting option is given, use refname to sort as default */\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337542","messageId":"0102016133ff3b0a-d7e5bf0c-4d99-41e4-882b-47a875c528fb-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 07/24] cat-file: start migrating to ref-filter","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:54Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Start moving formatting stuff related to data preparation\nfrom cat-file to ref-filter.\nStart from simple moving, it would be integrated into\nall ref-filter processes further.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 32 +++-----------------------------\n ref-filter.c       | 41 ++++++++++++++++++++++++++++++++++++-----\n ref-filter.h       | 12 ++++++------\n 3 files changed, 45 insertions(+), 40 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 490d9f8a8a922..909412747cbd2 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -182,25 +182,6 @@ static int is_atom(const char *atom, const char *s, int slen)\n \treturn alen == slen && !memcmp(atom, s, alen);\n }\n \n-static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int len,\n-\t\t\tstruct expand_data *data)\n-{\n-\tif (is_atom(\"objectname\", atom, len))\n-\t\t; /* do nothing */\n-\telse if (is_atom(\"objecttype\", atom, len))\n-\t\tdata->info.typep = &data->type;\n-\telse if (is_atom(\"objectsize\", atom, len))\n-\t\tdata->info.sizep = &data->size;\n-\telse if (is_atom(\"objectsize:disk\", atom, len))\n-\t\tdata->info.disk_sizep = &data->disk_size;\n-\telse if (is_atom(\"rest\", atom, len))\n-\t\tdata->split_on_whitespace = 1;\n-\telse if (is_atom(\"deltabase\", atom, len))\n-\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n-\telse\n-\t\tdie(\"unknown format element: %.*s\", len, atom);\n-}\n-\n static void expand_atom(struct strbuf *sb, const char *atom, int len,\n \t\t\t struct expand_data *data)\n {\n@@ -217,8 +198,6 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,\n \t\t\tstrbuf_addstr(sb, data->rest);\n \t} else if (is_atom(\"deltabase\", atom, len))\n \t\tstrbuf_addstr(sb, oid_to_hex(&data->delta_base_oid));\n-\telse\n-\t\tdie(\"unknown format element: %.*s\", len, atom);\n }\n \n static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)\n@@ -232,11 +211,7 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)\n \tif (!end)\n \t\tdie(\"format element '%s' does not end in ')'\", start);\n \n-\tif (data->mark_query)\n-\t\texpand_atom_into_fields(sb, start + 1, end - start - 1, data);\n-\telse\n-\t\texpand_atom(sb, start + 1, end - start - 1, data);\n-\n+\texpand_atom(sb, start + 1, end - start - 1, data);\n \treturn end - start + 1;\n }\n \n@@ -420,9 +395,8 @@ 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-\tstrbuf_expand(&buf, opt->format.format, expand_format, &data);\n-\tdata.mark_query = 0;\n+\topt->format.cat_file_data = &data;\n+\tverify_ref_format(&opt->format);\n \tif (opt->cmdmode)\n \t\tdata.split_on_whitespace = 1;\n \ndiff --git a/ref-filter.c b/ref-filter.c\nindex ee2aa7d6d072b..8e384b2818b22 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -392,6 +392,31 @@ struct atom_value {\n \tstruct used_atom *atom;\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_into_fields(const char *atom, int len,\n+\t\t\t\t    struct expand_data *data)\n+{\n+\tif (is_atom(\"objectname\", atom, len))\n+\t\t; /* do nothing */\n+\telse if (is_atom(\"objecttype\", atom, len))\n+\t\tdata->info.typep = &data->type;\n+\telse if (is_atom(\"objectsize\", atom, len))\n+\t\tdata->info.sizep = &data->size;\n+\telse if (is_atom(\"objectsize:disk\", atom, len))\n+\t\tdata->info.disk_sizep = &data->disk_size;\n+\telse if (is_atom(\"rest\", atom, len))\n+\t\tdata->split_on_whitespace = 1;\n+\telse if (is_atom(\"deltabase\", atom, len))\n+\t\tdata->info.delta_base_sha1 = data->delta_base_oid.hash;\n+\telse\n+\t\tdie(\"unknown format element: %.*s\", len, atom);\n+}\n+\n /*\n  * Used to parse format string and sort specifiers\n  */\n@@ -709,12 +734,18 @@ int verify_ref_format(struct ref_format *format)\n \t\tif (!ep)\n \t\t\treturn error(_(\"malformed format string %s\"), sp);\n \t\t/* sp points at \"%(\" and ep points at the closing \")\" */\n-\t\tat = parse_ref_filter_atom(format, valid_atom,\n-\t\t\t\t\t   ARRAY_SIZE(valid_atom), sp + 2, ep);\n-\t\tcp = ep + 1;\n \n-\t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n-\t\t\tformat->need_color_reset_at_eol = !!strcmp(color, \"reset\");\n+\t\tif (format->cat_file_data)\n+\t\t\texpand_atom_into_fields(sp + 2, ep - sp - 2,\n+\t\t\t\t\t\tformat->cat_file_data);\n+\t\telse {\n+\t\t\tat = parse_ref_filter_atom(format, valid_atom,\n+\t\t\t\t\t\t   ARRAY_SIZE(valid_atom), sp + 2, ep);\n+\t\t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n+\t\t\t\tformat->need_color_reset_at_eol = !!strcmp(color, \"reset\");\n+\t\t}\n+\n+\t\tcp = ep + 1;\n \t}\n \tif (format->need_color_reset_at_eol && !want_color(format->use_color))\n \t\tformat->need_color_reset_at_eol = 0;\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 56093a85d52b8..b50c8e6aaf2c4 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -80,12 +80,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 * 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@@ -119,6 +113,12 @@ struct ref_format {\n \n \t/* Internal state to ref-filter */\n \tint need_color_reset_at_eol;\n+\n+\t/*\n+\t * Helps to move all formatting logic from cat-file to ref-filter,\n+\t * hopefully would be reduced later.\n+\t */\n+\tstruct expand_data *cat_file_data;\n };\n \n #define REF_FORMAT_INIT { NULL, 0, -1 }\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337543","messageId":"0102016133ff3b41-c77d5053-8546-4b12-831e-135f3025a2ea-000000@eu-west-1.amazonses.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"[PATCH RFC 15/24] cat-file: move skip_object_info into ref-filter","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-26T19:43:40Z","receivedAt":"2018-01-26T19:44:55Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Move logic related to skip_object_info into ref-filter,\nso that cat-file does not use that field at all.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored by: Jeff King <peff@peff.net>\n---\n builtin/cat-file.c | 7 +------\n ref-filter.c       | 5 +++++\n ref-filter.h       | 1 +\n 3 files changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 601a87d9b5f7c..3a52c551f366a 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -394,14 +394,9 @@ static int batch_objects(struct batch_options *opt)\n \tmemset(&data, 0, sizeof(data));\n \topt->format.cat_file_data = &data;\n \topt->format.is_cat = 1;\n+\topt->format.all_objects = opt->all_objects;\n \tverify_ref_format(&opt->format);\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\tdata.skip_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.\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 51da76dc21136..29a1b75c93181 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -777,6 +777,11 @@ int verify_ref_format(struct ref_format *format)\n \t}\n \tif (format->need_color_reset_at_eol && !want_color(format->use_color))\n \t\tformat->need_color_reset_at_eol = 0;\n+\tif (is_cat && format->all_objects) {\n+\t\tstruct object_info empty = OBJECT_INFO_INIT;\n+\t\tif (!memcmp(&cat_file_info->info, &empty, sizeof(empty)))\n+\t\t\tcat_file_info->skip_object_info = 1;\n+\t}\n \treturn 0;\n }\n \ndiff --git a/ref-filter.h b/ref-filter.h\nindex 276de387f3bd0..4af89c4c86bee 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -120,6 +120,7 @@ struct ref_format {\n \t */\n \tstruct expand_data *cat_file_data;\n \tint is_cat;\n+\tint all_objects;\n };\n \n #define REF_FORMAT_INIT { NULL, 0, -1 }\n\n--\nhttps://github.com/git/git/pull/452\n"},{"id":"337545","messageId":"xmqqfu6s74pf.fsf@gitster.mtv.corp.google.com","threadId":"47700","inReplyTo":"0102016133ff3a86-44d354ec-13c6-4c38-bc75-1ba4422db5a7-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 01/24] ref-filter: get rid of goto","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-01-26T20:19:56Z","receivedAt":"2018-01-26T20:20:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n\n> Get rid of goto command in ref-filter for better readability.\n>\n> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored by: Jeff King <peff@peff.net>\n> ---\n\nHow was this patch \"mentored by\" these two folks?  Have they already\nreviewed and gave you OK, or are you asking them to also help reviewing\nwith this message?  Mostly just being curious.\n\nIt is not convincning that this splitting the last part of a single\nfunction into a separate helper function that is called from only\none place improves readability.  If better readability is the\npurpose, I would even say\n\n         for (i = 0; i < used_atom_cnt; i++) {\n\t\tif (...)\n-\t\t\tgoto need_obj;\n+\t\t\tbreak;\n\t}\n-\treturn;\n+\tif (used_atom_cnt <= i)\n\t\treturn;\n\n-need_obj:\n\nwould make the result easier to follow with a much less impact.\n\nIf we later in the series will use this new helper function from\nother places, it certainly makes sense to create a new helper like\nthis patch does, but then \"get rid of goto for readability\" is not\nthe justification for such a change.\n\n>  ref-filter.c | 103 ++++++++++++++++++++++++++++++-----------------------------\n>  1 file changed, 53 insertions(+), 50 deletions(-)\n>\n> diff --git a/ref-filter.c b/ref-filter.c\n> index f9e25aea7a97e..37337b57aacf4 100644\n> --- a/ref-filter.c\n> +++ b/ref-filter.c\n> @@ -1354,16 +1354,60 @@ static const char *get_refname(struct used_atom *atom, struct ref_array_item *re\n>  \treturn show_ref(&atom->u.refname, ref->refname);\n>  }\n>  \n> +static void need_object(struct ref_array_item *ref) {\n\nStyle.  The opening brace at the beginning of the function sits on\nits own line alone.\n"},{"id":"337550","messageId":"xmqq1sic72ku.fsf@gitster.mtv.corp.google.com","threadId":"47700","inReplyTo":"0102016133ff3ad8-abf99952-4df0-42a4-9ae9-06f602e84f3b-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 02/24] ref-filter: add return value to some functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-01-26T21:05:53Z","receivedAt":"2018-01-26T21:06:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n\n> Add return flag to format_ref_array_item, show_ref_array_item,\n> get_ref_array_info and populate_value for further using.\n> Need it to handle situations when item is broken but we can not invoke\n> die() because we are in batch mode and all items need to be processed.\n>\n> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored by: Jeff King <peff@peff.net>\n> ---\n>  ref-filter.c | 21 +++++++++++++--------\n>  ref-filter.h |  4 ++--\n>  2 files changed, 15 insertions(+), 10 deletions(-)\n\nMakes sense as a preparatory step to pass the return status\nthroughout the call chain.  The functions that actually will detect\nissues should probably gain\n\n\t/*\n\t * a comment before the function\n\t * that documents what it does and what values it returns\n\t * to signal the failure.\n\t */\n\nbefore them; those that only pass the errorcode through to the\ncaller do not necessarily have to, though.\n\n> -void show_ref_array_item(struct ref_array_item *info,\n> +int show_ref_array_item(struct ref_array_item *info,\n>  \t\t\t const struct ref_format *format)\n>  {\n>  \tstruct strbuf final_buf = STRBUF_INIT;\n> +\tint retval = format_ref_array_item(info, format, &final_buf);\n>  \n> -\tformat_ref_array_item(info, format, &final_buf);\n>  \tfwrite(final_buf.buf, 1, final_buf.len, stdout);\n>  \tstrbuf_release(&final_buf);\n> -\tputchar('\\n');\n> +\tif (!retval)\n> +\t\tputchar('\\n');\n> +\treturn retval;\n\nThis is questionable.  Why does it write final_buf out regardless of\nthe return value, even though it refrains from writing terminating LF\nupon non-zero return from the same function that prepared final_buf?\n\n\"Because final_buf is left unmodified when formatter returns an\nerror, and calling fwrite on an empty buffer ends up being a no-op\"\nis a wrong answer---it relies on having too intimate knowledge on\nhow the callee happens to work currently.\n"},{"id":"337553","messageId":"xmqqvafo5m5h.fsf@gitster.mtv.corp.google.com","threadId":"47700","inReplyTo":"0102016133ff3afb-6bab2c11-e0f3-4bef-9626-fbcc826bcb15-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 03/24] cat-file: split expand_atom into 2 functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-01-26T21:46:02Z","receivedAt":"2018-01-26T21:46:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n\n> Split expand_atom function into 2 different functions,\n> expand_atom_into_fields prepares variable for further filling,\n> (new) expand_atom creates resulting string.\n> Need that for further reusing of formatting logic from ref-filter.\n>\n> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored by: Jeff King <peff@peff.net>\n> ---\n>  builtin/cat-file.c | 73 +++++++++++++++++++++++++++++-------------------------\n>  1 file changed, 39 insertions(+), 34 deletions(-)\n\nAs expand_atom() is file-scope static and its callers are well\nisolated, it is OK to change its meaning while restructuring the\ncode like this patch does (as opposed to a public function to which\nnew callers may be added on other topics in flight).\n\nThe split itself looks sensible, but expand_atom_into_fields() is a\nquestionable name.  expand_atom() does fill the data in sb, but\ncalling expand_atom_into_fields() does not fill any data into\nseparated fields---it merely prepares somebody else to do so.\n\nHelped by this comment:\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\nwe can guess that a better name would mention or hint \"object_info\",\n\"query\" and probably \"prepare\" (because we would do so before\nactually querying).\n\nI am not sure if separating the logic into these two functions is a\ngood way to organize things.  When a new %(atom) is introduced, it\nis more likely that a programmer adds it to one but forgets to make\na matching change to the other, no?  (here, \"I am not sure\" is just\nthat.  It is very different from \"I am sure this is wrong\").\n\nThanks.\n"},{"id":"337556","messageId":"xmqq4ln8qn5g.fsf@gitster-ct.c.googlers.com","threadId":"47700","inReplyTo":"0102016133ff3af0-0ebed14d-deb5-4744-9267-4c5b0c6a30c8-000000@eu-west-1.amazonses.com","subject":"Re: [PATCH RFC 04/24] cat-file: reuse struct ref_format","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-01-26T22:18:51Z","receivedAt":"2018-01-26T22:18:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n\n> Start using ref_format struct instead of simple char*.\n> Need that for further reusing of formatting logic from ref-filter.\n>\n> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored by: Jeff King <peff@peff.net>\n> ---\n>  builtin/cat-file.c | 15 ++++++++-------\n>  1 file changed, 8 insertions(+), 7 deletions(-)\n\nOK, so at this stage we only use its .format field (which happens to\nbe the same simple \"char *\"), but we can later extend the functions\non the callchain this thing is passed through.\n\nMakes sense.\n\nThanks.\n\n\n>\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index f783b39b9bd5c..65c300184cab8 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -13,15 +13,16 @@\n>  #include \"tree-walk.h\"\n>  #include \"sha1-array.h\"\n>  #include \"packfile.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>  \tint buffer_output;\n>  \tint all_objects;\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> @@ -353,7 +354,7 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,\n>  \t\treturn;\n>  \t}\n>  \n> -\tstrbuf_expand(&buf, opt->format, expand_format, data);\n> +\tstrbuf_expand(&buf, opt->format.format, expand_format, data);\n>  \tstrbuf_addch(&buf, '\\n');\n>  \tbatch_write(opt, buf.buf, buf.len);\n>  \tstrbuf_release(&buf);\n> @@ -446,8 +447,8 @@ 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> +\tif (!opt->format.format)\n> +\t\topt->format.format = \"%(objectname) %(objecttype) %(objectsize)\";\n>  \n>  \t/*\n>  \t * Expand once with our special mark_query flag, which will prime the\n> @@ -456,7 +457,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(&buf, opt->format, expand_format, &data);\n> +\tstrbuf_expand(&buf, opt->format.format, expand_format, &data);\n>  \tdata.mark_query = 0;\n>  \tif (opt->cmdmode)\n>  \t\tdata.split_on_whitespace = 1;\n> @@ -548,7 +549,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> @@ -557,7 +558,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>\n> --\n> https://github.com/git/git/pull/452\n"},{"id":"337649","messageId":"CAL21BmkOGE6UZQJTFQjq3qnmywwBJQOUXE7jSwP1_Vn6PZ8ezA@mail.gmail.com","threadId":"47700","inReplyTo":"xmqqfu6s74pf.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH RFC 01/24] ref-filter: get rid of goto","fromName":"Оля Тележная","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-29T07:13:45Z","receivedAt":"2018-01-29T07:13:51Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"2018-01-26 23:19 GMT+03:00 Junio C Hamano <gitster@pobox.com>:\n> Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n>\n>> Get rid of goto command in ref-filter for better readability.\n>>\n>> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n>> Mentored-by: Christian Couder <christian.couder@gmail.com>\n>> Mentored by: Jeff King <peff@peff.net>\n>> ---\n>\n> How was this patch \"mentored by\" these two folks?  Have they already\n> reviewed and gave you OK, or are you asking them to also help reviewing\n> with this message?  Mostly just being curious.\n\nChristian and Jeff help me when I have different sort of difficulties.\nNot sure that they were helping me with that commit separately.\nBoth of them reviewed my code and said that it's ready for a final\nreview (actually, Christian said, but it's usual situation when I ask\nfor help/review and one of them helps me. The other one could add\nsomething, but, as I understand, if he totally agree, he will keep\nsilence, and I find that behavior logical).\nDo I need to delete these lines from some of commits where I do not\nremember help from them?\n\n>\n> It is not convincning that this splitting the last part of a single\n> function into a separate helper function that is called from only\n> one place improves readability.  If better readability is the\n> purpose, I would even say\n>\n>          for (i = 0; i < used_atom_cnt; i++) {\n>                 if (...)\n> -                       goto need_obj;\n> +                       break;\n>         }\n> -       return;\n> +       if (used_atom_cnt <= i)\n>                 return;\n>\n> -need_obj:\n>\n> would make the result easier to follow with a much less impact.\n\nIt's hard for me to read the code with goto, and as I know, it's not\nonly my problem, it's usual situation to try to get rid of gotos. I\nalways need to re-check whether we use that piece of code somewhere\nelse or not, and how we do that. I also think that it's good that most\nof variables in the beginning of the function populate_value go to new\nfunction.\n\n>\n> If we later in the series will use this new helper function from\n> other places, it certainly makes sense to create a new helper like\n> this patch does, but then \"get rid of goto for readability\" is not\n> the justification for such a change.\n\nWe don't use that new function anywhere else further. So, I can delete\nthis commit or I can change commit message (if so, please give me some\nideas what I need to mention there).\n\n>\n>>  ref-filter.c | 103 ++++++++++++++++++++++++++++++-----------------------------\n>>  1 file changed, 53 insertions(+), 50 deletions(-)\n>>\n>> diff --git a/ref-filter.c b/ref-filter.c\n>> index f9e25aea7a97e..37337b57aacf4 100644\n>> --- a/ref-filter.c\n>> +++ b/ref-filter.c\n>> @@ -1354,16 +1354,60 @@ static const char *get_refname(struct used_atom *atom, struct ref_array_item *re\n>>       return show_ref(&atom->u.refname, ref->refname);\n>>  }\n>>\n>> +static void need_object(struct ref_array_item *ref) {\n>\n> Style.  The opening brace at the beginning of the function sits on\n> its own line alone.\n\nThanks, I will fix that when we decide how to finally improve that commit.\n\nOlga\n"},{"id":"337650","messageId":"CAL21BmmAq+FRx2F8eiQj+jHhR-Y=Vdr26hC5T1F_9Ga8TyWJPQ@mail.gmail.com","threadId":"47700","inReplyTo":"xmqqvafo5m5h.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH RFC 03/24] cat-file: split expand_atom into 2 functions","fromName":"Оля Тележная","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-29T07:26:20Z","receivedAt":"2018-01-29T07:26:26Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"2018-01-27 0:46 GMT+03:00 Junio C Hamano <gitster@pobox.com>:\n> Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n>\n>> Split expand_atom function into 2 different functions,\n>> expand_atom_into_fields prepares variable for further filling,\n>> (new) expand_atom creates resulting string.\n>> Need that for further reusing of formatting logic from ref-filter.\n>>\n>> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n>> Mentored-by: Christian Couder <christian.couder@gmail.com>\n>> Mentored by: Jeff King <peff@peff.net>\n>> ---\n>>  builtin/cat-file.c | 73 +++++++++++++++++++++++++++++-------------------------\n>>  1 file changed, 39 insertions(+), 34 deletions(-)\n>\n> As expand_atom() is file-scope static and its callers are well\n> isolated, it is OK to change its meaning while restructuring the\n> code like this patch does (as opposed to a public function to which\n> new callers may be added on other topics in flight).\n>\n> The split itself looks sensible, but expand_atom_into_fields() is a\n> questionable name.  expand_atom() does fill the data in sb, but\n> calling expand_atom_into_fields() does not fill any data into\n> separated fields---it merely prepares somebody else to do so.\n>\n> Helped by this comment:\n>\n>         /*\n>          * If mark_query is true, we do not expand anything, but rather\n>          * just mark the object_info with items we wish to query.\n>          */\n>         int mark_query;\n>\n> we can guess that a better name would mention or hint \"object_info\",\n> \"query\" and probably \"prepare\" (because we would do so before\n> actually querying).\n\nOK, I will rename that function. Actually, not sure that we really\nneed to have ideal name here because both functions will be deleted by\nthe end of this patch.\n\"mark_atom_in_object_info\"?\n\n>\n> I am not sure if separating the logic into these two functions is a\n> good way to organize things.  When a new %(atom) is introduced, it\n> is more likely that a programmer adds it to one but forgets to make\n> a matching change to the other, no?  (here, \"I am not sure\" is just\n> that.  It is very different from \"I am sure this is wrong\").\n\nIn the end of the patch we don't have both of those functions, so\nthere would not be such problem.\nBut, I need that split, it helps me to go further and apply new\nchanges step-by-step.\n\n>\n> Thanks.\n"},{"id":"337652","messageId":"CAL21BmmWvrUjH3WESeMq45=ByhQ1cZhmZetUM6C2H7mGuFp84Q@mail.gmail.com","threadId":"47700","inReplyTo":"xmqq1sic72ku.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH RFC 02/24] ref-filter: add return value to some functions","fromName":"Оля Тележная","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-29T07:36:31Z","receivedAt":"2018-01-29T07:36:36Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"2018-01-27 0:05 GMT+03:00 Junio C Hamano <gitster@pobox.com>:\n> Olga Telezhnaya <olyatelezhnaya@gmail.com> writes:\n>\n>> Add return flag to format_ref_array_item, show_ref_array_item,\n>> get_ref_array_info and populate_value for further using.\n>> Need it to handle situations when item is broken but we can not invoke\n>> die() because we are in batch mode and all items need to be processed.\n>>\n>> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n>> Mentored-by: Christian Couder <christian.couder@gmail.com>\n>> Mentored by: Jeff King <peff@peff.net>\n>> ---\n>>  ref-filter.c | 21 +++++++++++++--------\n>>  ref-filter.h |  4 ++--\n>>  2 files changed, 15 insertions(+), 10 deletions(-)\n>\n> Makes sense as a preparatory step to pass the return status\n> throughout the call chain.  The functions that actually will detect\n> issues should probably gain\n>\n>         /*\n>          * a comment before the function\n>          * that documents what it does and what values it returns\n>          * to signal the failure.\n>          */\n>\n> before them; those that only pass the errorcode through to the\n> caller do not necessarily have to, though.\n\nI will add comments, agree, thank you.\n\n>\n>> -void show_ref_array_item(struct ref_array_item *info,\n>> +int show_ref_array_item(struct ref_array_item *info,\n>>                        const struct ref_format *format)\n>>  {\n>>       struct strbuf final_buf = STRBUF_INIT;\n>> +     int retval = format_ref_array_item(info, format, &final_buf);\n>>\n>> -     format_ref_array_item(info, format, &final_buf);\n>>       fwrite(final_buf.buf, 1, final_buf.len, stdout);\n>>       strbuf_release(&final_buf);\n>> -     putchar('\\n');\n>> +     if (!retval)\n>> +             putchar('\\n');\n>> +     return retval;\n>\n> This is questionable.  Why does it write final_buf out regardless of\n> the return value, even though it refrains from writing terminating LF\n> upon non-zero return from the same function that prepared final_buf?\n>\n> \"Because final_buf is left unmodified when formatter returns an\n> error, and calling fwrite on an empty buffer ends up being a no-op\"\n> is a wrong answer---it relies on having too intimate knowledge on\n> how the callee happens to work currently.\n\nI will change that piece of code by putting fwrite into if statement\nalso, thank you. We really do not put anything to buffer if retval is\nnot equal to zero (checked that).\n\nThank you for all your comments, waiting for further review.\nOlga\n"},{"id":"337809","messageId":"xmqqd11rt6ks.fsf@gitster-ct.c.googlers.com","threadId":"47700","inReplyTo":"CAL21BmkOGE6UZQJTFQjq3qnmywwBJQOUXE7jSwP1_Vn6PZ8ezA@mail.gmail.com","subject":"Re: [PATCH RFC 01/24] ref-filter: get rid of goto","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-01-30T20:49:55Z","receivedAt":"2018-01-30T20:50:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Оля Тележная  <olyatelezhnaya@gmail.com> writes:\n\n>> one place improves readability.  If better readability is the\n>> purpose, I would even say\n>>\n>>          for (i = 0; i < used_atom_cnt; i++) {\n>>                 if (...)\n>> -                       goto need_obj;\n>> +                       break;\n>>         }\n>> -       return;\n>> +       if (used_atom_cnt <= i)\n>>                 return;\n>>\n>> -need_obj:\n>>\n>> would make the result easier to follow with a much less impact.\n>\n> It's hard for me to read the code with goto, and as I know, it's not\n> only my problem,...\n\nThat sounds as if you are complaining \"I wanted to get rid of goto\nand you tell me not to do so???\", but read what I showed above again\nand notice that it is also getting rid of \"goto\".\n\nThe main difference from your version is that the original function\nis still kept as a single unit of work, instead of two.\n"},{"id":"337900","messageId":"CAL21Bm=cMQ-dx1v9rRhEuZQW7BrHGsCMTmvy=ONrv0weLM+JJg@mail.gmail.com","threadId":"47700","inReplyTo":"xmqqd11rt6ks.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH RFC 01/24] ref-filter: get rid of goto","fromName":"Оля Тележная","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-01-31T06:39:51Z","receivedAt":"2018-01-31T06:39:57Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"2018-01-30 23:49 GMT+03:00 Junio C Hamano <gitster@pobox.com>:\n> Оля Тележная  <olyatelezhnaya@gmail.com> writes:\n>\n>>> one place improves readability.  If better readability is the\n>>> purpose, I would even say\n>>>\n>>>          for (i = 0; i < used_atom_cnt; i++) {\n>>>                 if (...)\n>>> -                       goto need_obj;\n>>> +                       break;\n>>>         }\n>>> -       return;\n>>> +       if (used_atom_cnt <= i)\n>>>                 return;\n>>>\n>>> -need_obj:\n>>>\n>>> would make the result easier to follow with a much less impact.\n>>\n>> It's hard for me to read the code with goto, and as I know, it's not\n>> only my problem,...\n>\n> That sounds as if you are complaining \"I wanted to get rid of goto\n> and you tell me not to do so???\", but read what I showed above again\n> and notice that it is also getting rid of \"goto\".\n\nNo, I am not complaining. I tried to explain why I did everything that\nway. Sorry if it was not clear enough.\n\n>\n> The main difference from your version is that the original function\n> is still kept as a single unit of work, instead of two.\n\nAnd I am not sure that it is good, the function is too big and it\nactually does so many different separate pieces. If it is possible to\nshorten long function by getting some separate logic (that's our case,\nwe do not request object until that final goto statement), I think\nit's good idea and we need to do so and simplify future reading. But,\nif you do not agree with this fact, please explain your position in\ndetail, and I will change that place as you want.\n\nThanks.\n"}]}