log --graph: customize the graph lines with config log.graphColors

If you have a 256 colors terminal (or one with true color support), then the predefined 12 colors seem limited. On the other hand, you don't want to draw graph lines with every single color in this mode because the two colors could look extremely similar. This option allows you to hand pick the colors you want. Even with standard terminal, if your background color is neither black or white, then the graph line may match your background and become hidden. You can exclude your background color (or simply the colors you hate) with this. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jan 19, 2017 at 18:41 UTC 73c727d69f47572bf7f21fa31831f9a3fdad944c
3 files changed +63 -3
Documentation/config.txt
+4
@@ -2003,6 +2003,10 @@ log.follow::
2003 i.e. it cannot be used to follow multiple files and does not work well
2004 on non-linear history.
2005
2006 +log.graphColors::
2007 + A list of colors, separated by commas, that can be used to draw
2008 + history lines in `git log --graph`.
2009 +
2010 log.showRoot::
2011 If true, the initial commit will be shown as a big creation event.
2012 This is equivalent to a diff against an empty tree.
graph.c
+37 -3
@@ -4,6 +4,7 @@
4 #include "graph.h"
5 #include "diff.h"
6 #include "revision.h"
7 +#include "argv-array.h"
8
9 /* Internal API */
10
@@ -62,6 +63,26 @@ enum graph_state {
63 static const char **column_colors;
64 static unsigned short column_colors_max;
65
66 +static void parse_graph_colors_config(struct argv_array *colors, const char *string)
67 +{
68 + const char *end, *start;
69 +
70 + start = string;
71 + end = string + strlen(string);
72 + while (start < end) {
73 + const char *comma = strchrnul(start, ',');
74 + char color[COLOR_MAXLEN];
75 +
76 + if (!color_parse_mem(start, comma - start, color))
77 + argv_array_push(colors, color);
78 + else
79 + warning(_("ignore invalid color '%.*s' in log.graphColors"),
80 + (int)(comma - start), start);
81 + start = comma + 1;
82 + }
83 + argv_array_push(colors, GIT_COLOR_RESET);
84 +}
85 +
86 void graph_set_column_colors(const char **colors, unsigned short colors_max)
87 {
88 column_colors = colors;
@@ -207,9 +228,22 @@ struct git_graph *graph_init(struct rev_info *opt)
228 {
229 struct git_graph *graph = xmalloc(sizeof(struct git_graph));
230
210 - if (!column_colors)
211 - graph_set_column_colors(column_colors_ansi,
212 - column_colors_ansi_max);
231 + if (!column_colors) {
232 + char *string;
233 + if (git_config_get_string("log.graphcolors", &string)) {
234 + /* not configured -- use default */
235 + graph_set_column_colors(column_colors_ansi,
236 + column_colors_ansi_max);
237 + } else {
238 + static struct argv_array custom_colors = ARGV_ARRAY_INIT;
239 + argv_array_clear(&custom_colors);
240 + parse_graph_colors_config(&custom_colors, string);
241 + free(string);
242 + /* graph_set_column_colors takes a max-index, not a count */
243 + graph_set_column_colors(custom_colors.argv,
244 + custom_colors.argc - 1);
245 + }
246 + }
247
248 graph->commit = NULL;
249 graph->revs = opt;
t/t4202-log.sh
+22
@@ -313,6 +313,28 @@ test_expect_success 'log --graph with merge' '
313 test_cmp expect actual
314 '
315
316 +cat > expect.colors <<\EOF
317 +* Merge branch 'side'
318 +<BLUE>|<RESET><CYAN>\<RESET>
319 +<BLUE>|<RESET> * side-2
320 +<BLUE>|<RESET> * side-1
321 +* <CYAN>|<RESET> Second
322 +* <CYAN>|<RESET> sixth
323 +* <CYAN>|<RESET> fifth
324 +* <CYAN>|<RESET> fourth
325 +<CYAN>|<RESET><CYAN>/<RESET>
326 +* third
327 +* second
328 +* initial
329 +EOF
330 +
331 +test_expect_success 'log --graph with merge with log.graphColors' '
332 + test_config log.graphColors ",, blue,invalid-color, cyan, red , " &&
333 + git log --color=always --graph --date-order --pretty=tformat:%s |
334 + test_decode_color | sed "s/ *\$//" >actual &&
335 + test_cmp expect.colors actual
336 +'
337 +
338 test_expect_success 'log --raw --graph -m with merge' '
339 git log --raw --graph --oneline -m master | head -n 500 >actual &&
340 grep "initial" actual