Skip to content

Commit 76c57fe

Browse files
committed
Merge branch 'js/add-p-leftover-bits'
The final leg of rewriting "add -i/-p" in C. * js/add-p-leftover-bits: ci: include the built-in `git add -i` in the `linux-gcc` job built-in add -p: handle Escape sequences more efficiently built-in add -p: handle Escape sequences in interactive.singlekey mode built-in add -p: respect the `interactive.singlekey` config setting terminal: add a new function to read a single keystroke terminal: accommodate Git for Windows' default terminal terminal: make the code of disable_echo() reusable built-in add -p: handle diff.algorithm built-in add -p: support interactive.diffFilter t3701: adjust difffilter test
2 parents 9a5315e + b2627cc commit 76c57fe

7 files changed

+326
-9
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
/*
@@ -1152,6 +1170,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
11521170
strbuf_release(&print_file_item_data.worktree);
11531171
strbuf_release(&header);
11541172
prefix_item_list_clear(&commands);
1173+
clear_add_i_state(&s);
11551174

11561175
return res;
11571176
}

add-interactive.h

Lines changed: 4 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
struct repository;
2327
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,
@@ -360,6 +361,7 @@ static int is_octal(const char *p, size_t len)
360361
static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
361362
{
362363
struct argv_array args = ARGV_ARRAY_INIT;
364+
const char *diff_algorithm = s->s.interactive_diff_algorithm;
363365
struct strbuf *plain = &s->plain, *colored = NULL;
364366
struct child_process cp = CHILD_PROCESS_INIT;
365367
char *p, *pend, *colored_p = NULL, *colored_pend = NULL, marker = '\0';
@@ -369,6 +371,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
369371
int res;
370372

371373
argv_array_pushv(&args, s->mode->diff_cmd);
374+
if (diff_algorithm)
375+
argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
372376
if (s->revision) {
373377
struct object_id oid;
374378
argv_array_push(&args,
@@ -398,6 +402,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
398402

399403
if (want_color_fd(1, -1)) {
400404
struct child_process colored_cp = CHILD_PROCESS_INIT;
405+
const char *diff_filter = s->s.interactive_diff_filter;
401406

402407
setup_child_process(s, &colored_cp, NULL);
403408
xsnprintf((char *)args.argv[color_arg_index], 8, "--color");
@@ -407,6 +412,24 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
407412
argv_array_clear(&args);
408413
if (res)
409414
return error(_("could not parse colored diff"));
415+
416+
if (diff_filter) {
417+
struct child_process filter_cp = CHILD_PROCESS_INIT;
418+
419+
setup_child_process(s, &filter_cp,
420+
diff_filter, NULL);
421+
filter_cp.git_cmd = 0;
422+
filter_cp.use_shell = 1;
423+
strbuf_reset(&s->buf);
424+
if (pipe_command(&filter_cp,
425+
colored->buf, colored->len,
426+
&s->buf, colored->len,
427+
NULL, 0) < 0)
428+
return error(_("failed to run '%s'"),
429+
diff_filter);
430+
strbuf_swap(colored, &s->buf);
431+
}
432+
410433
strbuf_complete_line(colored);
411434
colored_p = colored->buf;
412435
colored_pend = colored_p + colored->len;
@@ -531,6 +554,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
531554
colored_pend - colored_p);
532555
if (colored_eol)
533556
colored_p = colored_eol + 1;
557+
else if (p != pend)
558+
/* colored shorter than non-colored? */
559+
goto mismatched_output;
534560
else
535561
colored_p = colored_pend;
536562

@@ -555,6 +581,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
555581
*/
556582
hunk->splittable_into++;
557583

584+
/* non-colored shorter than colored? */
585+
if (colored_p != colored_pend) {
586+
mismatched_output:
587+
error(_("mismatched output from interactive.diffFilter"));
588+
advise(_("Your filter must maintain a one-to-one correspondence\n"
589+
"between its input and output lines."));
590+
return -1;
591+
}
592+
558593
return 0;
559594
}
560595

@@ -1115,14 +1150,27 @@ static int run_apply_check(struct add_p_state *s,
11151150
return 0;
11161151
}
11171152

1153+
static int read_single_character(struct add_p_state *s)
1154+
{
1155+
if (s->s.use_single_key) {
1156+
int res = read_key_without_echo(&s->answer);
1157+
printf("%s\n", res == EOF ? "" : s->answer.buf);
1158+
return res;
1159+
}
1160+
1161+
if (strbuf_getline(&s->answer, stdin) == EOF)
1162+
return EOF;
1163+
strbuf_trim_trailing_newline(&s->answer);
1164+
return 0;
1165+
}
1166+
11181167
static int prompt_yesno(struct add_p_state *s, const char *prompt)
11191168
{
11201169
for (;;) {
11211170
color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt));
11221171
fflush(stdout);
1123-
if (strbuf_getline(&s->answer, stdin) == EOF)
1172+
if (read_single_character(s) == EOF)
11241173
return -1;
1125-
strbuf_trim_trailing_newline(&s->answer);
11261174
switch (tolower(s->answer.buf[0])) {
11271175
case 'n': return 0;
11281176
case 'y': return 1;
@@ -1362,9 +1410,8 @@ static int patch_update_file(struct add_p_state *s,
13621410
_(s->mode->prompt_mode[prompt_mode_type]),
13631411
s->buf.buf);
13641412
fflush(stdout);
1365-
if (strbuf_getline(&s->answer, stdin) == EOF)
1413+
if (read_single_character(s) == EOF)
13661414
break;
1367-
strbuf_trim_trailing_newline(&s->answer);
13681415

13691416
if (!s->answer.len)
13701417
continue;
@@ -1612,6 +1659,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
16121659
parse_diff(&s, ps) < 0) {
16131660
strbuf_release(&s.plain);
16141661
strbuf_release(&s.colored);
1662+
clear_add_i_state(&s.s);
16151663
return -1;
16161664
}
16171665

@@ -1630,5 +1678,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
16301678
strbuf_release(&s.buf);
16311679
strbuf_release(&s.plain);
16321680
strbuf_release(&s.colored);
1681+
clear_add_i_state(&s.s);
16331682
return 0;
16341683
}

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)