{"thread":{"id":"55531","subject":"[PATCH v2] object-info: support for retrieving object info","startedAt":"2021-04-20T23:40:06Z","lastAt":"2021-06-09T17:21:50Z","messageCount":5,"participants":["Bruno Albuquerque","Junio C Hamano","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"422504","messageId":"20210420233830.2181153-1-bga@google.com","threadId":"55531","inReplyTo":null,"subject":"[PATCH v2] object-info: support for retrieving object info","fromName":"Bruno Albuquerque","fromEmail":"bga@google.com","sentAt":"2021-04-20T23:38:31Z","receivedAt":"2021-04-20T23:40:06Z","isPatch":true,"sender":{"key":"bga@google.com","avatar":"https://avatars.githubusercontent.com/u/80971974?v=4"},"body":"Sometimes it is useful to get information of an object without having to\ndownload it completely.\n\nAdd the \"object-info\" capability that lets the client ask for\nobject-related information with their full hexadecimal object names.\n\nOnly sizes are returned for now.\n\nSigned-off-by: Bruno Albuquerque <bga@google.com>\n---\n\nThis version is a small change with just style fixes.\n\n Documentation/technical/protocol-v2.txt |  31 +++++++\n Makefile                                |   1 +\n protocol-caps.c                         | 113 ++++++++++++++++++++++++\n protocol-caps.h                         |  10 +++\n serve.c                                 |   2 +\n t/t5701-git-serve.sh                    |  26 ++++++\n 6 files changed, 183 insertions(+)\n create mode 100644 protocol-caps.c\n create mode 100644 protocol-caps.h\n\ndiff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt\nindex a7c806a73e..f4ed141774 100644\n--- a/Documentation/technical/protocol-v2.txt\n+++ b/Documentation/technical/protocol-v2.txt\n@@ -514,3 +514,34 @@ packet-line, and must not contain non-printable or whitespace characters. The\n current implementation uses trace2 session IDs (see\n link:api-trace2.html[api-trace2] for details), but this may change and users of\n the session ID should not rely on this fact.\n+\n+object-info\n+~~~~~~~~~~~\n+\n+`object-info` is the command to retrieve information about one or more objects.\n+Its main purpose is to allow a client to make decisions based on this\n+information without having to fully fetch objects. Object size is the only\n+information that is currently supported.\n+\n+An `object-info` request takes the following arguments:\n+\n+\tsize\n+\tRequests size information to be returned for each listed object id.\n+\n+\toid <oid>\n+\tIndicates to the server an object which the client wants to obtain\n+\tinformation for.\n+\n+The response of `object-info` is a list of the the requested object ids\n+and associated requested information, each separated by a single space.\n+\n+\toutput = info flush-pkt\n+\n+\tinfo = PKT-LINE(attrs) LF)\n+\t\t*PKT-LINE(obj-info LF)\n+\n+\tattrs = attr | attrs SP attrs\n+\n+\tattr = \"size\"\n+\n+\tobj-info = obj-id SP obj-size\ndiff --git a/Makefile b/Makefile\nindex 21c0bf1667..3225e37b63 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -961,6 +961,7 @@ LIB_OBJS += progress.o\n LIB_OBJS += promisor-remote.o\n LIB_OBJS += prompt.o\n LIB_OBJS += protocol.o\n+LIB_OBJS += protocol-caps.o\n LIB_OBJS += prune-packed.o\n LIB_OBJS += quote.o\n LIB_OBJS += range-diff.o\ndiff --git a/protocol-caps.c b/protocol-caps.c\nnew file mode 100644\nindex 0000000000..13a9e63a04\n--- /dev/null\n+++ b/protocol-caps.c\n@@ -0,0 +1,113 @@\n+#include \"git-compat-util.h\"\n+#include \"protocol-caps.h\"\n+#include \"gettext.h\"\n+#include \"pkt-line.h\"\n+#include \"strvec.h\"\n+#include \"hash.h\"\n+#include \"object.h\"\n+#include \"object-store.h\"\n+#include \"string-list.h\"\n+#include \"strbuf.h\"\n+\n+struct requested_info {\n+\tunsigned size : 1;\n+};\n+\n+/*\n+ * Parses oids from the given line and collects them in the given\n+ * oid_str_list. Returns 1 if parsing was successful and 0 otherwise.\n+ */\n+static int parse_oid(const char *line, struct string_list *oid_str_list)\n+{\n+\tconst char *arg;\n+\n+\tif (!skip_prefix(line, \"oid \", &arg))\n+\t\treturn 0;\n+\n+\tstring_list_append(oid_str_list, arg);\n+\n+\treturn 1;\n+}\n+\n+/*\n+ * Validates and send requested info back to the client. Any errors detected\n+ * are returned as they are detected.\n+ */\n+static void send_info(struct repository *r, struct packet_writer *writer,\n+\t\t      struct string_list *oid_str_list,\n+\t\t      struct requested_info *info)\n+{\n+\tstruct string_list_item *item;\n+\tstruct strbuf send_buffer = STRBUF_INIT;\n+\n+\tif (!oid_str_list->nr)\n+\t\treturn;\n+\n+\tif (info->size)\n+\t\tpacket_writer_write(writer, \"size\");\n+\n+\tfor_each_string_list_item (item, oid_str_list) {\n+\t\tconst char *oid_str = item->string;\n+\t\tstruct object_id oid;\n+\t\tunsigned long object_size;\n+\n+\t\tif (get_oid_hex(oid_str, &oid) < 0) {\n+\t\t\tpacket_writer_error(\n+\t\t\t\twriter,\n+\t\t\t\t\"object-info: protocol error, expected to get oid, not '%s'\",\n+\t\t\t\toid_str);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tstrbuf_addstr(&send_buffer, oid_str);\n+\n+\t\tif (info->size) {\n+\t\t\tif (oid_object_info(r, &oid, &object_size) < 0) {\n+\t\t\t\tstrbuf_addstr(&send_buffer, \" \");\n+\t\t\t} else {\n+\t\t\t\tstrbuf_addf(&send_buffer, \" %lu\", object_size);\n+\t\t\t}\n+\t\t}\n+\n+\t\tpacket_writer_write(writer, \"%s\",\n+\t\t\t\t    strbuf_detach(&send_buffer, NULL));\n+\t}\n+}\n+\n+int cap_object_info(struct repository *r, struct strvec *keys,\n+\t\t    struct packet_reader *request)\n+{\n+\tstruct requested_info info;\n+\tstruct packet_writer writer;\n+\tstruct string_list oid_str_list = STRING_LIST_INIT_DUP;\n+\n+\tpacket_writer_init(&writer, 1);\n+\n+\twhile (packet_reader_read(request) == PACKET_READ_NORMAL) {\n+\t\tif (!strcmp(\"size\", request->line)) {\n+\t\t\tinfo.size = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (parse_oid(request->line, &oid_str_list))\n+\t\t\tcontinue;\n+\n+\t\tpacket_writer_error(&writer,\n+\t\t\t\t    \"object-info: unexpected line: '%s'\",\n+\t\t\t\t    request->line);\n+\t}\n+\n+\tif (request->status != PACKET_READ_FLUSH) {\n+\t\tpacket_writer_error(\n+\t\t\t&writer, \"object-info: expected flush after arguments\");\n+\t\tdie(_(\"object-info: expected flush after arguments\"));\n+\t}\n+\n+\tsend_info(r, &writer, &oid_str_list, &info);\n+\n+\tstring_list_clear(&oid_str_list, 1);\n+\n+\tpacket_flush(1);\n+\n+\treturn 0;\n+}\ndiff --git a/protocol-caps.h b/protocol-caps.h\nnew file mode 100644\nindex 0000000000..6351648e37\n--- /dev/null\n+++ b/protocol-caps.h\n@@ -0,0 +1,10 @@\n+#ifndef PROTOCOL_CAPS_H\n+#define PROTOCOL_CAPS_H\n+\n+struct repository;\n+struct strvec;\n+struct packet_reader;\n+int cap_object_info(struct repository *r, struct strvec *keys,\n+\t\t    struct packet_reader *request);\n+\n+#endif /* PROTOCOL_CAPS_H */\n\\ No newline at end of file\ndiff --git a/serve.c b/serve.c\nindex ac20c72763..aa8209f147 100644\n--- a/serve.c\n+++ b/serve.c\n@@ -5,6 +5,7 @@\n #include \"version.h\"\n #include \"strvec.h\"\n #include \"ls-refs.h\"\n+#include \"protocol-caps.h\"\n #include \"serve.h\"\n #include \"upload-pack.h\"\n \n@@ -78,6 +79,7 @@ static struct protocol_capability capabilities[] = {\n \t{ \"server-option\", always_advertise, NULL },\n \t{ \"object-format\", object_format_advertise, NULL },\n \t{ \"session-id\", session_id_advertise, NULL },\n+\t{ \"object-info\", always_advertise, cap_object_info },\n };\n \n static void advertise_capabilities(void)\ndiff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh\nindex 509f379d49..73e74a9c54 100755\n--- a/t/t5701-git-serve.sh\n+++ b/t/t5701-git-serve.sh\n@@ -19,6 +19,7 @@ test_expect_success 'test capability advertisement' '\n \tfetch=shallow\n \tserver-option\n \tobject-format=$(test_oid algo)\n+\tobject-info\n \t0000\n \tEOF\n \n@@ -240,4 +241,29 @@ test_expect_success 'unexpected lines are not allowed in fetch request' '\n \tgrep \"unexpected line: .this-is-not-a-command.\" err\n '\n \n+# Test the basics of object-info\n+#\n+test_expect_success 'basics of object-info' '\n+\ttest-tool pkt-line pack >in <<-EOF &&\n+\tcommand=object-info\n+\tobject-format=$(test_oid algo)\n+\t0001\n+\tsize\n+\toid $(git rev-parse two:two.t)\n+\toid $(git rev-parse two:two.t)\n+\t0000\n+\tEOF\n+\n+\tcat >expect <<-EOF &&\n+\tsize\n+\t$(git rev-parse two:two.t) $(wc -c <two.t | xargs)\n+\t$(git rev-parse two:two.t) $(wc -c <two.t | xargs)\n+\t0000\n+\tEOF\n+\n+\ttest-tool serve-v2 --stateless-rpc <in >out &&\n+\ttest-tool pkt-line unpack <out >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.31.1.368.gbe11c130af-goog\n\n"},{"id":"422509","messageId":"xmqq35vk1n97.fsf@gitster.g","threadId":"55531","inReplyTo":"20210420233830.2181153-1-bga@google.com","subject":"Re: [PATCH v2] object-info: support for retrieving object info","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-04-21T00:42:44Z","receivedAt":"2021-04-21T00:42:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bruno Albuquerque <bga@google.com> writes:\n\n> Sometimes it is useful to get information of an object without having to\n> download it completely.\n>\n> Add the \"object-info\" capability that lets the client ask for\n> object-related information with their full hexadecimal object names.\n>\n> Only sizes are returned for now.\n>\n> Signed-off-by: Bruno Albuquerque <bga@google.com>\n> ---\n>\n> This version is a small change with just style fixes.\n\nWill queue.  Thanks.\n"},{"id":"423321","messageId":"xmqqpmyccokx.fsf@gitster.g","threadId":"55531","inReplyTo":"20210420233830.2181153-1-bga@google.com","subject":"Re: [PATCH v2] object-info: support for retrieving object info","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-04-30T05:45:50Z","receivedAt":"2021-04-30T05:45:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bruno Albuquerque <bga@google.com> writes:\n\n> Sometimes it is useful to get information of an object without having to\n> download it completely.\n>\n> Add the \"object-info\" capability that lets the client ask for\n> object-related information with their full hexadecimal object names.\n>\n> Only sizes are returned for now.\n>\n> Signed-off-by: Bruno Albuquerque <bga@google.com>\n> ---\n\nI recall seeing a comment that this would probably not help the vfs\nusecase all that much, but does anybody else have further comment on\nthis change?  Otherwise let me mark the topic to be merged to 'next'\nin a few days.\n\nThanks.\n\n> This version is a small change with just style fixes.\n>\n>  Documentation/technical/protocol-v2.txt |  31 +++++++\n>  Makefile                                |   1 +\n>  protocol-caps.c                         | 113 ++++++++++++++++++++++++\n>  protocol-caps.h                         |  10 +++\n>  serve.c                                 |   2 +\n>  t/t5701-git-serve.sh                    |  26 ++++++\n>  6 files changed, 183 insertions(+)\n>  create mode 100644 protocol-caps.c\n>  create mode 100644 protocol-caps.h\n>\n> diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt\n> index a7c806a73e..f4ed141774 100644\n> --- a/Documentation/technical/protocol-v2.txt\n> +++ b/Documentation/technical/protocol-v2.txt\n> @@ -514,3 +514,34 @@ packet-line, and must not contain non-printable or whitespace characters. The\n>  current implementation uses trace2 session IDs (see\n>  link:api-trace2.html[api-trace2] for details), but this may change and users of\n>  the session ID should not rely on this fact.\n> +\n> +object-info\n> +~~~~~~~~~~~\n> +\n> +`object-info` is the command to retrieve information about one or more objects.\n> +Its main purpose is to allow a client to make decisions based on this\n> +information without having to fully fetch objects. Object size is the only\n> +information that is currently supported.\n> +\n> +An `object-info` request takes the following arguments:\n> +\n> +\tsize\n> +\tRequests size information to be returned for each listed object id.\n> +\n> +\toid <oid>\n> +\tIndicates to the server an object which the client wants to obtain\n> +\tinformation for.\n> +\n> +The response of `object-info` is a list of the the requested object ids\n> +and associated requested information, each separated by a single space.\n> +\n> +\toutput = info flush-pkt\n> +\n> +\tinfo = PKT-LINE(attrs) LF)\n> +\t\t*PKT-LINE(obj-info LF)\n> +\n> +\tattrs = attr | attrs SP attrs\n> +\n> +\tattr = \"size\"\n> +\n> +\tobj-info = obj-id SP obj-size\n> diff --git a/Makefile b/Makefile\n> index 21c0bf1667..3225e37b63 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -961,6 +961,7 @@ LIB_OBJS += progress.o\n>  LIB_OBJS += promisor-remote.o\n>  LIB_OBJS += prompt.o\n>  LIB_OBJS += protocol.o\n> +LIB_OBJS += protocol-caps.o\n>  LIB_OBJS += prune-packed.o\n>  LIB_OBJS += quote.o\n>  LIB_OBJS += range-diff.o\n> diff --git a/protocol-caps.c b/protocol-caps.c\n> new file mode 100644\n> index 0000000000..13a9e63a04\n> --- /dev/null\n> +++ b/protocol-caps.c\n> @@ -0,0 +1,113 @@\n> +#include \"git-compat-util.h\"\n> +#include \"protocol-caps.h\"\n> +#include \"gettext.h\"\n> +#include \"pkt-line.h\"\n> +#include \"strvec.h\"\n> +#include \"hash.h\"\n> +#include \"object.h\"\n> +#include \"object-store.h\"\n> +#include \"string-list.h\"\n> +#include \"strbuf.h\"\n> +\n> +struct requested_info {\n> +\tunsigned size : 1;\n> +};\n> +\n> +/*\n> + * Parses oids from the given line and collects them in the given\n> + * oid_str_list. Returns 1 if parsing was successful and 0 otherwise.\n> + */\n> +static int parse_oid(const char *line, struct string_list *oid_str_list)\n> +{\n> +\tconst char *arg;\n> +\n> +\tif (!skip_prefix(line, \"oid \", &arg))\n> +\t\treturn 0;\n> +\n> +\tstring_list_append(oid_str_list, arg);\n> +\n> +\treturn 1;\n> +}\n> +\n> +/*\n> + * Validates and send requested info back to the client. Any errors detected\n> + * are returned as they are detected.\n> + */\n> +static void send_info(struct repository *r, struct packet_writer *writer,\n> +\t\t      struct string_list *oid_str_list,\n> +\t\t      struct requested_info *info)\n> +{\n> +\tstruct string_list_item *item;\n> +\tstruct strbuf send_buffer = STRBUF_INIT;\n> +\n> +\tif (!oid_str_list->nr)\n> +\t\treturn;\n> +\n> +\tif (info->size)\n> +\t\tpacket_writer_write(writer, \"size\");\n> +\n> +\tfor_each_string_list_item (item, oid_str_list) {\n> +\t\tconst char *oid_str = item->string;\n> +\t\tstruct object_id oid;\n> +\t\tunsigned long object_size;\n> +\n> +\t\tif (get_oid_hex(oid_str, &oid) < 0) {\n> +\t\t\tpacket_writer_error(\n> +\t\t\t\twriter,\n> +\t\t\t\t\"object-info: protocol error, expected to get oid, not '%s'\",\n> +\t\t\t\toid_str);\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tstrbuf_addstr(&send_buffer, oid_str);\n> +\n> +\t\tif (info->size) {\n> +\t\t\tif (oid_object_info(r, &oid, &object_size) < 0) {\n> +\t\t\t\tstrbuf_addstr(&send_buffer, \" \");\n> +\t\t\t} else {\n> +\t\t\t\tstrbuf_addf(&send_buffer, \" %lu\", object_size);\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tpacket_writer_write(writer, \"%s\",\n> +\t\t\t\t    strbuf_detach(&send_buffer, NULL));\n> +\t}\n> +}\n> +\n> +int cap_object_info(struct repository *r, struct strvec *keys,\n> +\t\t    struct packet_reader *request)\n> +{\n> +\tstruct requested_info info;\n> +\tstruct packet_writer writer;\n> +\tstruct string_list oid_str_list = STRING_LIST_INIT_DUP;\n> +\n> +\tpacket_writer_init(&writer, 1);\n> +\n> +\twhile (packet_reader_read(request) == PACKET_READ_NORMAL) {\n> +\t\tif (!strcmp(\"size\", request->line)) {\n> +\t\t\tinfo.size = 1;\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tif (parse_oid(request->line, &oid_str_list))\n> +\t\t\tcontinue;\n> +\n> +\t\tpacket_writer_error(&writer,\n> +\t\t\t\t    \"object-info: unexpected line: '%s'\",\n> +\t\t\t\t    request->line);\n> +\t}\n> +\n> +\tif (request->status != PACKET_READ_FLUSH) {\n> +\t\tpacket_writer_error(\n> +\t\t\t&writer, \"object-info: expected flush after arguments\");\n> +\t\tdie(_(\"object-info: expected flush after arguments\"));\n> +\t}\n> +\n> +\tsend_info(r, &writer, &oid_str_list, &info);\n> +\n> +\tstring_list_clear(&oid_str_list, 1);\n> +\n> +\tpacket_flush(1);\n> +\n> +\treturn 0;\n> +}\n> diff --git a/protocol-caps.h b/protocol-caps.h\n> new file mode 100644\n> index 0000000000..6351648e37\n> --- /dev/null\n> +++ b/protocol-caps.h\n> @@ -0,0 +1,10 @@\n> +#ifndef PROTOCOL_CAPS_H\n> +#define PROTOCOL_CAPS_H\n> +\n> +struct repository;\n> +struct strvec;\n> +struct packet_reader;\n> +int cap_object_info(struct repository *r, struct strvec *keys,\n> +\t\t    struct packet_reader *request);\n> +\n> +#endif /* PROTOCOL_CAPS_H */\n> \\ No newline at end of file\n> diff --git a/serve.c b/serve.c\n> index ac20c72763..aa8209f147 100644\n> --- a/serve.c\n> +++ b/serve.c\n> @@ -5,6 +5,7 @@\n>  #include \"version.h\"\n>  #include \"strvec.h\"\n>  #include \"ls-refs.h\"\n> +#include \"protocol-caps.h\"\n>  #include \"serve.h\"\n>  #include \"upload-pack.h\"\n>  \n> @@ -78,6 +79,7 @@ static struct protocol_capability capabilities[] = {\n>  \t{ \"server-option\", always_advertise, NULL },\n>  \t{ \"object-format\", object_format_advertise, NULL },\n>  \t{ \"session-id\", session_id_advertise, NULL },\n> +\t{ \"object-info\", always_advertise, cap_object_info },\n>  };\n>  \n>  static void advertise_capabilities(void)\n> diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh\n> index 509f379d49..73e74a9c54 100755\n> --- a/t/t5701-git-serve.sh\n> +++ b/t/t5701-git-serve.sh\n> @@ -19,6 +19,7 @@ test_expect_success 'test capability advertisement' '\n>  \tfetch=shallow\n>  \tserver-option\n>  \tobject-format=$(test_oid algo)\n> +\tobject-info\n>  \t0000\n>  \tEOF\n>  \n> @@ -240,4 +241,29 @@ test_expect_success 'unexpected lines are not allowed in fetch request' '\n>  \tgrep \"unexpected line: .this-is-not-a-command.\" err\n>  '\n>  \n> +# Test the basics of object-info\n> +#\n> +test_expect_success 'basics of object-info' '\n> +\ttest-tool pkt-line pack >in <<-EOF &&\n> +\tcommand=object-info\n> +\tobject-format=$(test_oid algo)\n> +\t0001\n> +\tsize\n> +\toid $(git rev-parse two:two.t)\n> +\toid $(git rev-parse two:two.t)\n> +\t0000\n> +\tEOF\n> +\n> +\tcat >expect <<-EOF &&\n> +\tsize\n> +\t$(git rev-parse two:two.t) $(wc -c <two.t | xargs)\n> +\t$(git rev-parse two:two.t) $(wc -c <two.t | xargs)\n> +\t0000\n> +\tEOF\n> +\n> +\ttest-tool serve-v2 --stateless-rpc <in >out &&\n> +\ttest-tool pkt-line unpack <out >actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_done\n"},{"id":"426607","messageId":"patch-1.1-2302c9d522-20210607T143157Z-avarab@gmail.com","threadId":"55531","inReplyTo":"20210420233830.2181153-1-bga@google.com","subject":"[PATCH] protocol-caps.h: add newline at end of file","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-06-07T14:33:05Z","receivedAt":"2021-06-07T14:34:26Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a trailing newline to the protocol-caps.h file added in the recent\na2ba162cda (object-info: support for retrieving object info,\n2021-04-20). Various editors add this implicitly, and some compilers\nwarn about the lack of a \\n here.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n protocol-caps.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/protocol-caps.h b/protocol-caps.h\nindex 6351648e37..0a9f49df11 100644\n--- a/protocol-caps.h\n+++ b/protocol-caps.h\n@@ -7,4 +7,4 @@ struct packet_reader;\n int cap_object_info(struct repository *r, struct strvec *keys,\n \t\t    struct packet_reader *request);\n \n-#endif /* PROTOCOL_CAPS_H */\n\\ No newline at end of file\n+#endif /* PROTOCOL_CAPS_H */\n-- \n2.32.0.rc3.434.gd8aed1f08a7\n\n"},{"id":"426906","messageId":"CAPeR6H4bqTjSxieWVbWQGG+vg3=6DA62JQRrpLaG_xKuhf4ADQ@mail.gmail.com","threadId":"55531","inReplyTo":"patch-1.1-2302c9d522-20210607T143157Z-avarab@gmail.com","subject":"Re: [PATCH] protocol-caps.h: add newline at end of file","fromName":"Bruno Albuquerque","fromEmail":"bga@google.com","sentAt":"2021-06-09T17:20:36Z","receivedAt":"2021-06-09T17:21:50Z","isPatch":true,"sender":{"key":"bga@google.com","avatar":"https://avatars.githubusercontent.com/u/80971974?v=4"},"body":"On Mon, Jun 7, 2021 at 7:33 AM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n>\n> Add a trailing newline to the protocol-caps.h file added in the recent\n> a2ba162cda (object-info: support for retrieving object info,\n> 2021-04-20). Various editors add this implicitly, and some compilers\n> warn about the lack of a \\n here.\n\nThanks for cleaning this up.\n"}]}