{"thread":{"id":"48978","subject":"[PATCH 1/2] Document git config getter return value.","startedAt":"2018-07-30T12:18:10Z","lastAt":"2018-07-30T12:18:18Z","messageCount":2,"participants":["Han-Wen Nienhuys"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"353863","messageId":"20180730121801.53727-1-hanwen@google.com","threadId":"48978","inReplyTo":null,"subject":"[PATCH 1/2] Document git config getter return value.","fromName":"Han-Wen Nienhuys","fromEmail":"hanwen@google.com","sentAt":"2018-07-30T12:18:00Z","receivedAt":"2018-07-30T12:18:10Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"---\n config.h | 10 ++++++++--\n 1 file changed, 8 insertions(+), 2 deletions(-)\n\ndiff --git a/config.h b/config.h\nindex b95bb7649..d39256eb1 100644\n--- a/config.h\n+++ b/config.h\n@@ -178,11 +178,16 @@ struct config_set {\n };\n\n extern void git_configset_init(struct config_set *cs);\n-extern int git_configset_add_file(struct config_set *cs, const char *filename);\n-extern int git_configset_get_value(struct config_set *cs, const char *key, const char **value);\n+\n extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);\n extern void git_configset_clear(struct config_set *cs);\n+\n+/*\n+ * The int return values in these functions is 1 if not found, 0 if found, leaving\n+ * the found value in the 'dest' pointer.\n+ */\n+extern int git_configset_add_file(struct config_set *cs, const char *filename);\n+extern int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);\n extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);\n extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);\n extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);\n--\n2.18.0.345.g5c9ce644c3-goog\n"},{"id":"353864","messageId":"20180730121801.53727-2-hanwen@google.com","threadId":"48978","inReplyTo":"20180730121801.53727-1-hanwen@google.com","subject":"[PATCH 2/2] Highlight keywords in remote sideband output.","fromName":"Han-Wen Nienhuys","fromEmail":"hanwen@google.com","sentAt":"2018-07-30T12:18:01Z","receivedAt":"2018-07-30T12:18:18Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"The highlighting is done on the client-side. Supported keywords are\n\"error\", \"warning\", \"hint\" and \"success\".\n\nThe colorization is controlled with the config setting \"color.remote\".\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\nChange-Id: I090412a1288bc2caef0916447e28c2d0199da47d\n---\n sideband.c                          | 79 +++++++++++++++++++++++++----\n t/t5409-colorize-remote-messages.sh | 34 +++++++++++++\n 2 files changed, 104 insertions(+), 9 deletions(-)\n create mode 100644 t/t5409-colorize-remote-messages.sh\n\ndiff --git a/sideband.c b/sideband.c\nindex 325bf0e97..15213a7c1 100644\n--- a/sideband.c\n+++ b/sideband.c\n@@ -1,6 +1,63 @@\n #include \"cache.h\"\n #include \"pkt-line.h\"\n #include \"sideband.h\"\n+#include \"color.h\"\n+\n+static int sideband_use_color = -1;\n+\n+/*\n+ * Optionally highlight some keywords in remote output if they appear at the\n+ * start of the line.\n+ */\n+void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)\n+{\n+\tif (sideband_use_color < 0) {\n+\t\tconst char *key = \"color.remote\";\n+\t\tchar *value = NULL;\n+\t\tif (!git_config_get_string(key, &value))\n+\t\t\tsideband_use_color = git_config_colorbool(key, value);\n+\t}\n+\n+\tint want_color = want_color_stderr(sideband_use_color);\n+\tint i;\n+\n+\tif (!want_color) {\n+\t\tstrbuf_add(dest, src, n);\n+\t\treturn;\n+\t}\n+\n+\tstruct kwtable {\n+\t\tconst char *keyword;\n+\t\tconst char *color;\n+\t} keywords[] = {\n+\t\t{\"hint\", GIT_COLOR_YELLOW},\n+\t\t{\"warning\", GIT_COLOR_BOLD_YELLOW},\n+\t\t{\"success\", GIT_COLOR_BOLD_GREEN},\n+\t\t{\"error\", GIT_COLOR_BOLD_RED},\n+\t};\n+\n+\twhile (isspace(*src)) {\n+\t\tstrbuf_addch(dest, *src);\n+\t\tsrc++;\n+\t\tn--;\n+\t}\n+\n+\tfor (i = 0; i < ARRAY_SIZE(keywords); i++) {\n+\t\tstruct kwtable* p = keywords + i;\n+\t\tint len = strlen(p->keyword);\n+\t\tif (!strncasecmp(p->keyword, src, len) && !isalnum(src[len])) {\n+\t\t\tstrbuf_addstr(dest, p->color);\n+\t\t\tstrbuf_add(dest, src, len);\n+\t\t\tstrbuf_addstr(dest, GIT_COLOR_RESET);\n+\t\t\tn -= len;\n+\t\t\tsrc += len;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tstrbuf_add(dest, src, n);\n+}\n+\n \n /*\n  * Receive multiplexed output stream over git native protocol.\n@@ -48,8 +105,10 @@ int recv_sideband(const char *me, int in_stream, int out)\n \t\tlen--;\n \t\tswitch (band) {\n \t\tcase 3:\n-\t\t\tstrbuf_addf(&outbuf, \"%s%s%s\", outbuf.len ? \"\\n\" : \"\",\n-\t\t\t\t    DISPLAY_PREFIX, buf + 1);\n+\t\t\tstrbuf_addf(&outbuf, \"%s%s\", outbuf.len ? \"\\n\" : \"\",\n+\t\t\t\t    DISPLAY_PREFIX);\n+\t\t\tmaybe_colorize_sideband(&outbuf, buf + 1, len);\n+\n \t\t\tretval = SIDEBAND_REMOTE_ERROR;\n \t\t\tbreak;\n \t\tcase 2:\n@@ -69,20 +128,22 @@ int recv_sideband(const char *me, int in_stream, int out)\n \t\t\t\tif (!outbuf.len)\n \t\t\t\t\tstrbuf_addstr(&outbuf, DISPLAY_PREFIX);\n \t\t\t\tif (linelen > 0) {\n-\t\t\t\t\tstrbuf_addf(&outbuf, \"%.*s%s%c\",\n-\t\t\t\t\t\t    linelen, b, suffix, *brk);\n-\t\t\t\t} else {\n-\t\t\t\t\tstrbuf_addch(&outbuf, *brk);\n+\t\t\t\t\tmaybe_colorize_sideband(&outbuf, b, linelen);\n+\t\t\t\t\tstrbuf_addstr(&outbuf, suffix);\n \t\t\t\t}\n+\n+\t\t\t\tstrbuf_addch(&outbuf, *brk);\n \t\t\t\txwrite(2, outbuf.buf, outbuf.len);\n \t\t\t\tstrbuf_reset(&outbuf);\n \n \t\t\t\tb = brk + 1;\n \t\t\t}\n \n-\t\t\tif (*b)\n-\t\t\t\tstrbuf_addf(&outbuf, \"%s%s\", outbuf.len ?\n-\t\t\t\t\t    \"\" : DISPLAY_PREFIX, b);\n+\t\t\tif (*b) {\n+\t\t\t\tstrbuf_addstr(&outbuf, outbuf.len ?\n+\t\t\t\t\t    \"\" : DISPLAY_PREFIX);\n+\t\t\t\tmaybe_colorize_sideband(&outbuf, b, strlen(b));\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase 1:\n \t\t\twrite_or_die(out, buf + 1, len);\ndiff --git a/t/t5409-colorize-remote-messages.sh b/t/t5409-colorize-remote-messages.sh\nnew file mode 100644\nindex 000000000..1620cffbe\n--- /dev/null\n+++ b/t/t5409-colorize-remote-messages.sh\n@@ -0,0 +1,34 @@\n+#!/bin/sh\n+\n+test_description='remote messages are colorized on the client'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tmkdir .git/hooks &&\n+        cat << EOF > .git/hooks/update &&\n+#!/bin/sh\n+echo error: error\n+echo hint: hint\n+echo success: success\n+echo warning: warning\n+exit 0\n+EOF\n+\tchmod +x .git/hooks/update &&\n+\techo 1 >file &&\n+\tgit add file &&\n+\tgit commit -m 1 &&\n+        git clone . child &&\n+        cd child &&\n+        echo 2 > file &&\n+        git commit -a -m 2\n+'\n+\n+test_expect_success 'push' 'git -c color.remote push origin HEAD:refs/heads/newbranch 2>output &&\n+  test_decode_color < output > decoded &&\n+  test_i18ngrep \"<BOLD;RED>error<RESET>:\" decoded &&\n+  test_i18ngrep \"<YELLOW>hint<RESET>:\" decoded &&\n+  test_i18ngrep \"<BOLD;GREEN>success<RESET>:\" decoded &&\n+  test_i18ngrep \"<BOLD;YELLOW>warning<RESET>:\" decoded'\n+\n+test_done\n-- \n2.18.0.345.g5c9ce644c3-goog\n\n"}]}