Skip to content

Commit e1923b1

Browse files
committed
Merge branch 'add-p-in-c-config-settings'
This is the final leg of the journey to a fully built-in `git add`: the `git add -i` and `git add -p` modes were re-implemented in C, but they lacked support for a couple of config settings. The one that sticks out most is the `interactive.singleKey` setting: it was not only particularly hard to get to work, especially on Windows. It is also the setting that seems to be incomplete already in the Perl version: while the name suggests that it applies to the main loop of `git add --interactive`, or to the file selections in that command, it does not. Only the `git add --patch` mode respects that setting. As it is outside the purpose of the conversion of `git-add--interactive.perl` to C, we will leave that loose end for some future date. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 84c8289 + ae50474 commit e1923b1

File tree

6 files changed

+328
-8
lines changed

6 files changed

+328
-8
lines changed

add-interactive.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
5252
diff_get_color(s->use_color, DIFF_FILE_OLD));
5353
init_color(r, s, "new", s->file_new_color,
5454
diff_get_color(s->use_color, DIFF_FILE_NEW));
55+
56+
FREE_AND_NULL(s->interactive_diff_filter);
57+
git_config_get_string("interactive.difffilter",
58+
&s->interactive_diff_filter);
59+
60+
FREE_AND_NULL(s->interactive_diff_algorithm);
61+
git_config_get_string("diff.algorithm",
62+
&s->interactive_diff_algorithm);
63+
64+
git_config_get_bool("interactive.singlekey", &s->use_single_key);
65+
}
66+
67+
void clear_add_i_state(struct add_i_state *s)
68+
{
69+
FREE_AND_NULL(s->interactive_diff_filter);
70+
FREE_AND_NULL(s->interactive_diff_algorithm);
71+
memset(s, 0, sizeof(*s));
72+
s->use_color = -1;
5573
}
5674

5775
/*
@@ -1143,6 +1161,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
11431161
strbuf_release(&print_file_item_data.worktree);
11441162
strbuf_release(&header);
11451163
prefix_item_list_clear(&commands);
1164+
clear_add_i_state(&s);
11461165

11471166
return res;
11481167
}

add-interactive.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ struct add_i_state {
1515
char context_color[COLOR_MAXLEN];
1616
char file_old_color[COLOR_MAXLEN];
1717
char file_new_color[COLOR_MAXLEN];
18+
19+
int use_single_key;
20+
char *interactive_diff_filter, *interactive_diff_algorithm;
1821
};
1922

2023
void init_add_i_state(struct add_i_state *s, struct repository *r);
24+
void clear_add_i_state(struct add_i_state *s);
2125

2226
enum color_add_i {
2327
COLOR_HEADER = 0,
@@ -27,6 +31,9 @@ enum color_add_i {
2731
COLOR_RESET,
2832
};
2933
const char *get_add_i_color(enum color_add_i ix);
34+
const char *get_interactive_diff_filter(void);
35+
const char *get_interactive_diff_algorithm(void);
36+
int get_interactive_use_single_key(void);
3037

3138
struct repository;
3239
struct pathspec;

add-patch.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "pathspec.h"
77
#include "color.h"
88
#include "diff.h"
9+
#include "compat/terminal.h"
910

1011
enum prompt_mode_type {
1112
PROMPT_MODE_CHANGE = 0, PROMPT_DELETION, PROMPT_HUNK
@@ -354,6 +355,7 @@ static int is_octal(const char *p, size_t len)
354355
static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
355356
{
356357
struct argv_array args = ARGV_ARRAY_INIT;
358+
const char *diff_algorithm = s->s.interactive_diff_algorithm;
357359
struct strbuf *plain = &s->plain, *colored = NULL;
358360
struct child_process cp = CHILD_PROCESS_INIT;
359361
char *p, *pend, *colored_p = NULL, *colored_pend = NULL, marker = '\0';
@@ -363,6 +365,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
363365
int res;
364366

365367
argv_array_pushv(&args, s->mode->diff);
368+
if (diff_algorithm)
369+
argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
366370
if (s->revision) {
367371
struct object_id oid;
368372
argv_array_push(&args,
@@ -392,6 +396,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
392396

393397
if (want_color_fd(1, -1)) {
394398
struct child_process colored_cp = CHILD_PROCESS_INIT;
399+
const char *diff_filter = s->s.interactive_diff_filter;
395400

396401
setup_child_process(&colored_cp, s, NULL);
397402
xsnprintf((char *)args.argv[color_arg_index], 8, "--color");
@@ -401,6 +406,24 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
401406
argv_array_clear(&args);
402407
if (res)
403408
return error(_("could not parse colored diff"));
409+
410+
if (diff_filter) {
411+
struct child_process filter_cp = CHILD_PROCESS_INIT;
412+
413+
setup_child_process(&filter_cp, s,
414+
diff_filter, NULL);
415+
filter_cp.git_cmd = 0;
416+
filter_cp.use_shell = 1;
417+
strbuf_reset(&s->buf);
418+
if (pipe_command(&filter_cp,
419+
colored->buf, colored->len,
420+
&s->buf, colored->len,
421+
NULL, 0) < 0)
422+
return error(_("failed to run '%s'"),
423+
diff_filter);
424+
strbuf_swap(colored, &s->buf);
425+
}
426+
404427
strbuf_complete_line(colored);
405428
colored_p = colored->buf;
406429
colored_pend = colored_p + colored->len;
@@ -501,6 +524,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
501524
colored_pend - colored_p);
502525
if (colored_eol)
503526
colored_p = colored_eol + 1;
527+
else if (p != pend)
528+
/* colored shorter than non-colored? */
529+
goto mismatched_output;
504530
else
505531
colored_p = colored_pend;
506532

@@ -522,6 +548,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
522548
*/
523549
hunk->splittable_into++;
524550

551+
/* non-colored shorter than colored? */
552+
if (colored_p != colored_pend) {
553+
mismatched_output:
554+
error(_("mismatched output from interactive.diffFilter"));
555+
advise(_("Your filter must maintain a one-to-one correspondence\n"
556+
"between its input and output lines."));
557+
return -1;
558+
}
559+
525560
return 0;
526561
}
527562

@@ -1075,14 +1110,27 @@ static int run_apply_check(struct add_p_state *s,
10751110
return 0;
10761111
}
10771112

1113+
static int read_single_character(struct add_p_state *s)
1114+
{
1115+
if (s->s.use_single_key) {
1116+
int res = read_key_without_echo(&s->answer);
1117+
printf("%s\n", res == EOF ? "" : s->answer.buf);
1118+
return res;
1119+
}
1120+
1121+
if (strbuf_getline(&s->answer, stdin) == EOF)
1122+
return EOF;
1123+
strbuf_trim_trailing_newline(&s->answer);
1124+
return 0;
1125+
}
1126+
10781127
static int prompt_yesno(struct add_p_state *s, const char *prompt)
10791128
{
10801129
for (;;) {
10811130
color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt));
10821131
fflush(stdout);
1083-
if (strbuf_getline(&s->answer, stdin) == EOF)
1132+
if (read_single_character(s) == EOF)
10841133
return -1;
1085-
strbuf_trim_trailing_newline(&s->answer);
10861134
switch (tolower(s->answer.buf[0])) {
10871135
case 'n': return 0;
10881136
case 'y': return 1;
@@ -1322,9 +1370,8 @@ static int patch_update_file(struct add_p_state *s,
13221370
_(s->mode->prompt_mode[prompt_mode_type]),
13231371
s->buf.buf);
13241372
fflush(stdout);
1325-
if (strbuf_getline(&s->answer, stdin) == EOF)
1373+
if (read_single_character(s) == EOF)
13261374
break;
1327-
strbuf_trim_trailing_newline(&s->answer);
13281375

13291376
if (!s->answer.len)
13301377
continue;
@@ -1571,6 +1618,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
15711618
parse_diff(&s, ps) < 0) {
15721619
strbuf_release(&s.plain);
15731620
strbuf_release(&s.colored);
1621+
clear_add_i_state(&s.s);
15741622
return -1;
15751623
}
15761624

@@ -1589,5 +1637,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
15891637
strbuf_release(&s.buf);
15901638
strbuf_release(&s.plain);
15911639
strbuf_release(&s.colored);
1640+
clear_add_i_state(&s.s);
15921641
return 0;
15931642
}

ci/run-build-and-tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ linux-gcc)
2020
export GIT_TEST_OE_DELTA_SIZE=5
2121
export GIT_TEST_COMMIT_GRAPH=1
2222
export GIT_TEST_MULTI_PACK_INDEX=1
23+
export GIT_TEST_ADD_I_USE_BUILTIN=1
2324
make test
2425
;;
2526
linux-gcc-4.8)

0 commit comments

Comments
 (0)