Skip to content

Commit 31804ed

Browse files
gitsterdscho
authored andcommitted
Merge branch 'jk/add-i-color'
Some among "git add -p" and friends ignored color.diff and/or color.ui configuration variables, which is an old regression, which has been corrected. * jk/add-i-color: contrib/diff-highlight: mention interactive.diffFilter add-interactive: manually fall back color config to color.ui add-interactive: respect color.diff for diff coloring stash: pass --no-color to diff plumbing child processes
2 parents 1d6c60e + 1092cd6 commit 31804ed

File tree

7 files changed

+150
-42
lines changed

7 files changed

+150
-42
lines changed

add-interactive.c

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020
#include "prompt.h"
2121
#include "tree.h"
2222

23-
static void init_color(struct repository *r, struct add_i_state *s,
23+
static void init_color(struct repository *r, int use_color,
2424
const char *section_and_slot, char *dst,
2525
const char *default_color)
2626
{
2727
char *key = xstrfmt("color.%s", section_and_slot);
2828
const char *value;
2929

30-
if (!s->use_color)
30+
if (!use_color)
3131
dst[0] = '\0';
3232
else if (repo_config_get_value(r, key, &value) ||
3333
color_parse(value, dst))
@@ -36,42 +36,63 @@ static void init_color(struct repository *r, struct add_i_state *s,
3636
free(key);
3737
}
3838

39-
void init_add_i_state(struct add_i_state *s, struct repository *r,
40-
struct add_p_opt *add_p_opt)
39+
static int check_color_config(struct repository *r, const char *var)
4140
{
4241
const char *value;
42+
int ret;
43+
44+
if (repo_config_get_value(r, var, &value))
45+
ret = -1;
46+
else
47+
ret = git_config_colorbool(var, value);
48+
49+
/*
50+
* Do not rely on want_color() to fall back to color.ui for us. It uses
51+
* the value parsed by git_color_config(), which may not have been
52+
* called by the main command.
53+
*/
54+
if (ret < 0 && !repo_config_get_value(r, "color.ui", &value))
55+
ret = git_config_colorbool("color.ui", value);
4356

57+
return want_color(ret);
58+
}
59+
60+
void init_add_i_state(struct add_i_state *s, struct repository *r,
61+
struct add_p_opt *add_p_opt)
62+
{
4463
s->r = r;
4564
s->context = -1;
4665
s->interhunkcontext = -1;
4766

48-
if (repo_config_get_value(r, "color.interactive", &value))
49-
s->use_color = -1;
50-
else
51-
s->use_color =
52-
git_config_colorbool("color.interactive", value);
53-
s->use_color = want_color(s->use_color);
54-
55-
init_color(r, s, "interactive.header", s->header_color, GIT_COLOR_BOLD);
56-
init_color(r, s, "interactive.help", s->help_color, GIT_COLOR_BOLD_RED);
57-
init_color(r, s, "interactive.prompt", s->prompt_color,
58-
GIT_COLOR_BOLD_BLUE);
59-
init_color(r, s, "interactive.error", s->error_color,
60-
GIT_COLOR_BOLD_RED);
61-
62-
init_color(r, s, "diff.frag", s->fraginfo_color,
63-
diff_get_color(s->use_color, DIFF_FRAGINFO));
64-
init_color(r, s, "diff.context", s->context_color, "fall back");
67+
s->use_color_interactive = check_color_config(r, "color.interactive");
68+
69+
init_color(r, s->use_color_interactive, "interactive.header",
70+
s->header_color, GIT_COLOR_BOLD);
71+
init_color(r, s->use_color_interactive, "interactive.help",
72+
s->help_color, GIT_COLOR_BOLD_RED);
73+
init_color(r, s->use_color_interactive, "interactive.prompt",
74+
s->prompt_color, GIT_COLOR_BOLD_BLUE);
75+
init_color(r, s->use_color_interactive, "interactive.error",
76+
s->error_color, GIT_COLOR_BOLD_RED);
77+
strlcpy(s->reset_color_interactive,
78+
s->use_color_interactive ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
79+
80+
s->use_color_diff = check_color_config(r, "color.diff");
81+
82+
init_color(r, s->use_color_diff, "diff.frag", s->fraginfo_color,
83+
diff_get_color(s->use_color_diff, DIFF_FRAGINFO));
84+
init_color(r, s->use_color_diff, "diff.context", s->context_color,
85+
"fall back");
6586
if (!strcmp(s->context_color, "fall back"))
66-
init_color(r, s, "diff.plain", s->context_color,
67-
diff_get_color(s->use_color, DIFF_CONTEXT));
68-
init_color(r, s, "diff.old", s->file_old_color,
69-
diff_get_color(s->use_color, DIFF_FILE_OLD));
70-
init_color(r, s, "diff.new", s->file_new_color,
71-
diff_get_color(s->use_color, DIFF_FILE_NEW));
72-
73-
strlcpy(s->reset_color,
74-
s->use_color ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
87+
init_color(r, s->use_color_diff, "diff.plain",
88+
s->context_color,
89+
diff_get_color(s->use_color_diff, DIFF_CONTEXT));
90+
init_color(r, s->use_color_diff, "diff.old", s->file_old_color,
91+
diff_get_color(s->use_color_diff, DIFF_FILE_OLD));
92+
init_color(r, s->use_color_diff, "diff.new", s->file_new_color,
93+
diff_get_color(s->use_color_diff, DIFF_FILE_NEW));
94+
strlcpy(s->reset_color_diff,
95+
s->use_color_diff ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
7596

7697
FREE_AND_NULL(s->interactive_diff_filter);
7798
repo_config_get_string(r, "interactive.difffilter",
@@ -109,7 +130,8 @@ void clear_add_i_state(struct add_i_state *s)
109130
FREE_AND_NULL(s->interactive_diff_filter);
110131
FREE_AND_NULL(s->interactive_diff_algorithm);
111132
memset(s, 0, sizeof(*s));
112-
s->use_color = -1;
133+
s->use_color_interactive = -1;
134+
s->use_color_diff = -1;
113135
}
114136

115137
/*
@@ -1188,9 +1210,9 @@ int run_add_i(struct repository *r, const struct pathspec *ps,
11881210
* When color was asked for, use the prompt color for
11891211
* highlighting, otherwise use square brackets.
11901212
*/
1191-
if (s.use_color) {
1213+
if (s.use_color_interactive) {
11921214
data.color = s.prompt_color;
1193-
data.reset = s.reset_color;
1215+
data.reset = s.reset_color_interactive;
11941216
}
11951217
print_file_item_data.color = data.color;
11961218
print_file_item_data.reset = data.reset;

add-interactive.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@ struct add_p_opt {
1212

1313
struct add_i_state {
1414
struct repository *r;
15-
int use_color;
15+
int use_color_interactive;
16+
int use_color_diff;
1617
char header_color[COLOR_MAXLEN];
1718
char help_color[COLOR_MAXLEN];
1819
char prompt_color[COLOR_MAXLEN];
1920
char error_color[COLOR_MAXLEN];
20-
char reset_color[COLOR_MAXLEN];
21+
char reset_color_interactive[COLOR_MAXLEN];
22+
2123
char fraginfo_color[COLOR_MAXLEN];
2224
char context_color[COLOR_MAXLEN];
2325
char file_old_color[COLOR_MAXLEN];
2426
char file_new_color[COLOR_MAXLEN];
27+
char reset_color_diff[COLOR_MAXLEN];
2528

2629
int use_single_key;
2730
char *interactive_diff_filter, *interactive_diff_algorithm;

add-patch.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static void err(struct add_p_state *s, const char *fmt, ...)
300300
va_start(args, fmt);
301301
fputs(s->s.error_color, stdout);
302302
vprintf(fmt, args);
303-
puts(s->s.reset_color);
303+
puts(s->s.reset_color_interactive);
304304
va_end(args);
305305
}
306306

@@ -457,7 +457,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
457457
}
458458
strbuf_complete_line(plain);
459459

460-
if (want_color_fd(1, -1)) {
460+
if (want_color_fd(1, s->s.use_color_diff)) {
461461
struct child_process colored_cp = CHILD_PROCESS_INIT;
462462
const char *diff_filter = s->s.interactive_diff_filter;
463463

@@ -714,7 +714,7 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
714714
if (len)
715715
strbuf_add(out, p, len);
716716
else if (colored)
717-
strbuf_addf(out, "%s\n", s->s.reset_color);
717+
strbuf_addf(out, "%s\n", s->s.reset_color_diff);
718718
else
719719
strbuf_addch(out, '\n');
720720
}
@@ -1107,7 +1107,7 @@ static void recolor_hunk(struct add_p_state *s, struct hunk *hunk)
11071107
s->s.file_new_color :
11081108
s->s.context_color);
11091109
strbuf_add(&s->colored, plain + current, eol - current);
1110-
strbuf_addstr(&s->colored, s->s.reset_color);
1110+
strbuf_addstr(&s->colored, s->s.reset_color_diff);
11111111
if (next > eol)
11121112
strbuf_add(&s->colored, plain + eol, next - eol);
11131113
current = next;
@@ -1528,8 +1528,8 @@ static int patch_update_file(struct add_p_state *s,
15281528
: 1));
15291529
printf(_(s->mode->prompt_mode[prompt_mode_type]),
15301530
s->buf.buf);
1531-
if (*s->s.reset_color)
1532-
fputs(s->s.reset_color, stdout);
1531+
if (*s->s.reset_color_interactive)
1532+
fputs(s->s.reset_color_interactive, stdout);
15331533
fflush(stdout);
15341534
if (read_single_character(s) == EOF)
15351535
break;

builtin/stash.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
377377
* however it should be done together with apply_cached.
378378
*/
379379
cp.git_cmd = 1;
380-
strvec_pushl(&cp.args, "diff-tree", "--binary", NULL);
380+
strvec_pushl(&cp.args, "diff-tree", "--binary", "--no-color", NULL);
381381
strvec_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
382382

383383
return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
@@ -1283,6 +1283,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
12831283

12841284
cp_diff_tree.git_cmd = 1;
12851285
strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "--binary",
1286+
"--no-color",
12861287
"-U1", "HEAD", oid_to_hex(&info->w_tree), "--", NULL);
12871288
if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
12881289
ret = -1;
@@ -1345,6 +1346,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
13451346

13461347
cp_diff_tree.git_cmd = 1;
13471348
strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD",
1349+
"--no-color",
13481350
oid_to_hex(&info->w_tree), "--", NULL);
13491351
if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
13501352
ret = -1;
@@ -1719,6 +1721,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
17191721

17201722
cp_diff.git_cmd = 1;
17211723
strvec_pushl(&cp_diff.args, "diff-index", "-p",
1724+
"--no-color",
17221725
"--cached", "--binary", "HEAD", "--",
17231726
NULL);
17241727
add_pathspecs(&cp_diff.args, ps);

contrib/diff-highlight/README

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ following in your git configuration:
5858
diff = diff-highlight | less
5959
---------------------------------------------
6060

61+
If you use the interactive patch mode of `git add -p`, `git checkout
62+
-p`, etc, you may also want to configure it to be used there:
63+
64+
---------------------------------------------
65+
[interactive]
66+
diffFilter = diff-highlight
67+
---------------------------------------------
68+
6169

6270
Color Config
6371
------------

t/t3701-add-interactive.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,44 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' '
866866
test_grep "old<" output
867867
'
868868

869+
test_expect_success 'diff color respects color.diff' '
870+
git reset --hard &&
871+
872+
echo old >test &&
873+
git add test &&
874+
echo new >test &&
875+
876+
printf n >n &&
877+
force_color git \
878+
-c color.interactive=auto \
879+
-c color.interactive.prompt=blue \
880+
-c color.diff=false \
881+
-c color.diff.old=red \
882+
add -p >output.raw 2>&1 <n &&
883+
test_decode_color <output.raw >output &&
884+
test_grep "BLUE.*Stage this hunk" output &&
885+
test_grep ! "RED" output
886+
'
887+
888+
test_expect_success 're-coloring diff without color.interactive' '
889+
git reset --hard &&
890+
891+
test_write_lines 1 2 3 >test &&
892+
git add test &&
893+
test_write_lines one 2 three >test &&
894+
895+
test_write_lines s n n |
896+
force_color git \
897+
-c color.interactive=false \
898+
-c color.interactive.prompt=blue \
899+
-c color.diff=true \
900+
-c color.diff.frag="bold magenta" \
901+
add -p >output.raw 2>&1 &&
902+
test_decode_color <output.raw >output &&
903+
test_grep "<BOLD;MAGENTA>@@" output &&
904+
test_grep ! "BLUE" output
905+
'
906+
869907
test_expect_success 'diffFilter filters diff' '
870908
git reset --hard &&
871909
@@ -1304,6 +1342,12 @@ test_expect_success 'stash accepts -U and --inter-hunk-context' '
13041342
test_grep "@@ -2,20 +2,20 @@" actual
13051343
'
13061344

1345+
test_expect_success 'set up base for -p color tests' '
1346+
echo commit >file &&
1347+
git commit -am "commit state" &&
1348+
git tag patch-base
1349+
'
1350+
13071351
for cmd in add checkout commit reset restore "stash save" "stash push"
13081352
do
13091353
test_expect_success "$cmd rejects invalid context options" '
@@ -1320,6 +1364,15 @@ do
13201364
test_must_fail git $cmd --inter-hunk-context 2 2>actual &&
13211365
test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual
13221366
'
1367+
1368+
test_expect_success "$cmd falls back to color.ui" '
1369+
git reset --hard patch-base &&
1370+
echo working-tree >file &&
1371+
test_write_lines y |
1372+
force_color git -c color.ui=false $cmd -p >output.raw 2>&1 &&
1373+
test_decode_color <output.raw >output &&
1374+
test_cmp output.raw output
1375+
'
13231376
done
13241377

13251378
test_done

t/t3904-stash-patch.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,23 @@ test_expect_success 'stash -p with split hunk' '
107107
! grep "added line 2" test
108108
'
109109

110+
test_expect_success 'stash -p not confused by GIT_PAGER_IN_USE' '
111+
echo to-stash >test &&
112+
# Set both GIT_PAGER_IN_USE and TERM. Our goal is to entice any
113+
# diff subprocesses into thinking that they could output
114+
# color, even though their stdout is not going into a tty.
115+
echo y |
116+
GIT_PAGER_IN_USE=1 TERM=vt100 git stash -p &&
117+
git diff --exit-code
118+
'
119+
120+
test_expect_success 'index push not confused by GIT_PAGER_IN_USE' '
121+
echo index >test &&
122+
git add test &&
123+
echo working-tree >test &&
124+
# As above, we try to entice the child diff into using color.
125+
GIT_PAGER_IN_USE=1 TERM=vt100 git stash push test &&
126+
git diff --exit-code
127+
'
128+
110129
test_done

0 commit comments

Comments
 (0)