Skip to content

Commit 85279e8

Browse files
committed
Merge branch 'nd/log-graph-configurable-colors'
Some people feel the default set of colors used by "git log --graph" rather limiting. A mechanism to customize the set of colors has been introduced. * nd/log-graph-configurable-colors: document behavior of empty color name color_parse_mem: allow empty color spec log --graph: customize the graph lines with config log.graphColors color.c: trim leading spaces in color_parse_mem() color.c: fix color_parse_mem() with value_len == 0
2 parents cc8364c + 512aba2 commit 85279e8

File tree

6 files changed

+97
-5
lines changed

6 files changed

+97
-5
lines changed

Documentation/config.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ The position of any attributes with respect to the colors
170170
be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
171171
`no-ul`, etc).
172172
+
173+
An empty color string produces no color effect at all. This can be used
174+
to avoid coloring specific elements without disabling color entirely.
175+
+
173176
For git's pre-defined color slots, the attributes are meant to be reset
174177
at the beginning of each item in the colored output. So setting
175178
`color.decorate.branch` to `black` will paint that branch name in a
@@ -2036,6 +2039,10 @@ log.follow::
20362039
i.e. it cannot be used to follow multiple files and does not work well
20372040
on non-linear history.
20382041

2042+
log.graphColors::
2043+
A list of colors, separated by commas, that can be used to draw
2044+
history lines in `git log --graph`.
2045+
20392046
log.showRoot::
20402047
If true, the initial commit will be shown as a big creation event.
20412048
This is equivalent to a diff against an empty tree.

color.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,17 @@ int color_parse_mem(const char *value, int value_len, char *dst)
207207
struct color fg = { COLOR_UNSPECIFIED };
208208
struct color bg = { COLOR_UNSPECIFIED };
209209

210-
if (!strncasecmp(value, "reset", len)) {
210+
while (len > 0 && isspace(*ptr)) {
211+
ptr++;
212+
len--;
213+
}
214+
215+
if (!len) {
216+
dst[0] = '\0';
217+
return 0;
218+
}
219+
220+
if (!strncasecmp(ptr, "reset", len)) {
211221
xsnprintf(dst, end - dst, GIT_COLOR_RESET);
212222
return 0;
213223
}

graph.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "color.h"
44
#include "graph.h"
55
#include "revision.h"
6+
#include "argv-array.h"
67

78
/* Internal API */
89

@@ -79,6 +80,26 @@ static void graph_show_line_prefix(const struct diff_options *diffopt)
7980
static const char **column_colors;
8081
static unsigned short column_colors_max;
8182

83+
static void parse_graph_colors_config(struct argv_array *colors, const char *string)
84+
{
85+
const char *end, *start;
86+
87+
start = string;
88+
end = string + strlen(string);
89+
while (start < end) {
90+
const char *comma = strchrnul(start, ',');
91+
char color[COLOR_MAXLEN];
92+
93+
if (!color_parse_mem(start, comma - start, color))
94+
argv_array_push(colors, color);
95+
else
96+
warning(_("ignore invalid color '%.*s' in log.graphColors"),
97+
(int)(comma - start), start);
98+
start = comma + 1;
99+
}
100+
argv_array_push(colors, GIT_COLOR_RESET);
101+
}
102+
82103
void graph_set_column_colors(const char **colors, unsigned short colors_max)
83104
{
84105
column_colors = colors;
@@ -238,9 +259,22 @@ struct git_graph *graph_init(struct rev_info *opt)
238259
{
239260
struct git_graph *graph = xmalloc(sizeof(struct git_graph));
240261

241-
if (!column_colors)
242-
graph_set_column_colors(column_colors_ansi,
243-
column_colors_ansi_max);
262+
if (!column_colors) {
263+
char *string;
264+
if (git_config_get_string("log.graphcolors", &string)) {
265+
/* not configured -- use default */
266+
graph_set_column_colors(column_colors_ansi,
267+
column_colors_ansi_max);
268+
} else {
269+
static struct argv_array custom_colors = ARGV_ARRAY_INIT;
270+
argv_array_clear(&custom_colors);
271+
parse_graph_colors_config(&custom_colors, string);
272+
free(string);
273+
/* graph_set_column_colors takes a max-index, not a count */
274+
graph_set_column_colors(custom_colors.argv,
275+
custom_colors.argc - 1);
276+
}
277+
}
244278

245279
graph->commit = NULL;
246280
graph->revs = opt;

t/t3701-add-interactive.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,4 +380,18 @@ test_expect_success 'patch mode ignores unmerged entries' '
380380
test_cmp expected diff
381381
'
382382

383+
test_expect_success 'diffs can be colorized' '
384+
git reset --hard &&
385+
386+
# force color even though the test script has no terminal
387+
test_config color.ui always &&
388+
389+
echo content >test &&
390+
printf y | git add -p >output 2>&1 &&
391+
392+
# We do not want to depend on the exact coloring scheme
393+
# git uses for diffs, so just check that we saw some kind of color.
394+
grep "$(printf "\\033")" output
395+
'
396+
383397
test_done

t/t4026-color.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
test_description='Test diff/status color escape codes'
77
. ./test-lib.sh
88

9+
ESC=$(printf '\033')
910
color()
1011
{
1112
actual=$(git config --get-color no.such.slot "$1") &&
12-
test "$actual" = "$2"
13+
test "$actual" = "${2:+$ESC}$2"
1314
}
1415

1516
invalid_color()
@@ -21,6 +22,10 @@ test_expect_success 'reset' '
2122
color "reset" "[m"
2223
'
2324

25+
test_expect_success 'empty color is empty' '
26+
color "" ""
27+
'
28+
2429
test_expect_success 'attribute before color name' '
2530
color "bold red" "[1;31m"
2631
'

t/t4202-log.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,28 @@ test_expect_success 'log --graph --line-prefix="| | | " with merge' '
359359
test_cmp expect actual
360360
'
361361

362+
cat > expect.colors <<\EOF
363+
* Merge branch 'side'
364+
<BLUE>|<RESET><CYAN>\<RESET>
365+
<BLUE>|<RESET> * side-2
366+
<BLUE>|<RESET> * side-1
367+
* <CYAN>|<RESET> Second
368+
* <CYAN>|<RESET> sixth
369+
* <CYAN>|<RESET> fifth
370+
* <CYAN>|<RESET> fourth
371+
<CYAN>|<RESET><CYAN>/<RESET>
372+
* third
373+
* second
374+
* initial
375+
EOF
376+
377+
test_expect_success 'log --graph with merge with log.graphColors' '
378+
test_config log.graphColors " blue,invalid-color, cyan, red , " &&
379+
git log --color=always --graph --date-order --pretty=tformat:%s |
380+
test_decode_color | sed "s/ *\$//" >actual &&
381+
test_cmp expect.colors actual
382+
'
383+
362384
test_expect_success 'log --raw --graph -m with merge' '
363385
git log --raw --graph --oneline -m master | head -n 500 >actual &&
364386
grep "initial" actual

0 commit comments

Comments
 (0)