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
This commit is contained in:
Junio C Hamano 2017-02-02 13:36:58 -08:00
commit 85279e8649
6 changed files with 97 additions and 5 deletions

View File

@ -170,6 +170,9 @@ The position of any attributes with respect to the colors
be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`, be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
`no-ul`, etc). `no-ul`, etc).
+ +
An empty color string produces no color effect at all. This can be used
to avoid coloring specific elements without disabling color entirely.
+
For git's pre-defined color slots, the attributes are meant to be reset For git's pre-defined color slots, the attributes are meant to be reset
at the beginning of each item in the colored output. So setting at the beginning of each item in the colored output. So setting
`color.decorate.branch` to `black` will paint that branch name in a `color.decorate.branch` to `black` will paint that branch name in a
@ -2036,6 +2039,10 @@ log.follow::
i.e. it cannot be used to follow multiple files and does not work well i.e. it cannot be used to follow multiple files and does not work well
on non-linear history. on non-linear history.
log.graphColors::
A list of colors, separated by commas, that can be used to draw
history lines in `git log --graph`.
log.showRoot:: log.showRoot::
If true, the initial commit will be shown as a big creation event. If true, the initial commit will be shown as a big creation event.
This is equivalent to a diff against an empty tree. This is equivalent to a diff against an empty tree.

12
color.c
View File

@ -207,7 +207,17 @@ int color_parse_mem(const char *value, int value_len, char *dst)
struct color fg = { COLOR_UNSPECIFIED }; struct color fg = { COLOR_UNSPECIFIED };
struct color bg = { COLOR_UNSPECIFIED }; struct color bg = { COLOR_UNSPECIFIED };
if (!strncasecmp(value, "reset", len)) { while (len > 0 && isspace(*ptr)) {
ptr++;
len--;
}
if (!len) {
dst[0] = '\0';
return 0;
}
if (!strncasecmp(ptr, "reset", len)) {
xsnprintf(dst, end - dst, GIT_COLOR_RESET); xsnprintf(dst, end - dst, GIT_COLOR_RESET);
return 0; return 0;
} }

40
graph.c
View File

@ -3,6 +3,7 @@
#include "color.h" #include "color.h"
#include "graph.h" #include "graph.h"
#include "revision.h" #include "revision.h"
#include "argv-array.h"
/* Internal API */ /* Internal API */
@ -79,6 +80,26 @@ static void graph_show_line_prefix(const struct diff_options *diffopt)
static const char **column_colors; static const char **column_colors;
static unsigned short column_colors_max; static unsigned short column_colors_max;
static void parse_graph_colors_config(struct argv_array *colors, const char *string)
{
const char *end, *start;
start = string;
end = string + strlen(string);
while (start < end) {
const char *comma = strchrnul(start, ',');
char color[COLOR_MAXLEN];
if (!color_parse_mem(start, comma - start, color))
argv_array_push(colors, color);
else
warning(_("ignore invalid color '%.*s' in log.graphColors"),
(int)(comma - start), start);
start = comma + 1;
}
argv_array_push(colors, GIT_COLOR_RESET);
}
void graph_set_column_colors(const char **colors, unsigned short colors_max) void graph_set_column_colors(const char **colors, unsigned short colors_max)
{ {
column_colors = colors; column_colors = colors;
@ -238,9 +259,22 @@ struct git_graph *graph_init(struct rev_info *opt)
{ {
struct git_graph *graph = xmalloc(sizeof(struct git_graph)); struct git_graph *graph = xmalloc(sizeof(struct git_graph));
if (!column_colors) if (!column_colors) {
graph_set_column_colors(column_colors_ansi, char *string;
column_colors_ansi_max); if (git_config_get_string("log.graphcolors", &string)) {
/* not configured -- use default */
graph_set_column_colors(column_colors_ansi,
column_colors_ansi_max);
} else {
static struct argv_array custom_colors = ARGV_ARRAY_INIT;
argv_array_clear(&custom_colors);
parse_graph_colors_config(&custom_colors, string);
free(string);
/* graph_set_column_colors takes a max-index, not a count */
graph_set_column_colors(custom_colors.argv,
custom_colors.argc - 1);
}
}
graph->commit = NULL; graph->commit = NULL;
graph->revs = opt; graph->revs = opt;

View File

@ -380,4 +380,18 @@ test_expect_success 'patch mode ignores unmerged entries' '
test_cmp expected diff test_cmp expected diff
' '
test_expect_success 'diffs can be colorized' '
git reset --hard &&
# force color even though the test script has no terminal
test_config color.ui always &&
echo content >test &&
printf y | git add -p >output 2>&1 &&
# We do not want to depend on the exact coloring scheme
# git uses for diffs, so just check that we saw some kind of color.
grep "$(printf "\\033")" output
'
test_done test_done

View File

@ -6,10 +6,11 @@
test_description='Test diff/status color escape codes' test_description='Test diff/status color escape codes'
. ./test-lib.sh . ./test-lib.sh
ESC=$(printf '\033')
color() color()
{ {
actual=$(git config --get-color no.such.slot "$1") && actual=$(git config --get-color no.such.slot "$1") &&
test "$actual" = "$2" test "$actual" = "${2:+$ESC}$2"
} }
invalid_color() invalid_color()
@ -21,6 +22,10 @@ test_expect_success 'reset' '
color "reset" "[m" color "reset" "[m"
' '
test_expect_success 'empty color is empty' '
color "" ""
'
test_expect_success 'attribute before color name' ' test_expect_success 'attribute before color name' '
color "bold red" "[1;31m" color "bold red" "[1;31m"
' '

View File

@ -359,6 +359,28 @@ test_expect_success 'log --graph --line-prefix="| | | " with merge' '
test_cmp expect actual test_cmp expect actual
' '
cat > expect.colors <<\EOF
* Merge branch 'side'
<BLUE>|<RESET><CYAN>\<RESET>
<BLUE>|<RESET> * side-2
<BLUE>|<RESET> * side-1
* <CYAN>|<RESET> Second
* <CYAN>|<RESET> sixth
* <CYAN>|<RESET> fifth
* <CYAN>|<RESET> fourth
<CYAN>|<RESET><CYAN>/<RESET>
* third
* second
* initial
EOF
test_expect_success 'log --graph with merge with log.graphColors' '
test_config log.graphColors " blue,invalid-color, cyan, red , " &&
git log --color=always --graph --date-order --pretty=tformat:%s |
test_decode_color | sed "s/ *\$//" >actual &&
test_cmp expect.colors actual
'
test_expect_success 'log --raw --graph -m with merge' ' test_expect_success 'log --raw --graph -m with merge' '
git log --raw --graph --oneline -m master | head -n 500 >actual && git log --raw --graph --oneline -m master | head -n 500 >actual &&
grep "initial" actual grep "initial" actual