Skip to content

Commit 65e4869

Browse files
dschoGit for Windows Build Agent
authored andcommitted
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 05b8d16 + 87486ad commit 65e4869

File tree

6 files changed

+319
-8
lines changed

6 files changed

+319
-8
lines changed

add-interactive.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ int init_add_i_state(struct repository *r, struct add_i_state *s)
5656
strlcpy(s->file_new_color,
5757
diff_get_color(s->use_color, DIFF_FILE_NEW), COLOR_MAXLEN);
5858

59+
free(s->interactive_diff_filter);
60+
if (git_config_get_string("interactive.difffilter",
61+
&s->interactive_diff_filter))
62+
s->interactive_diff_filter = NULL;
63+
64+
free(s->interactive_diff_algorithm);
65+
if (git_config_get_string("diff.algorithm",
66+
&s->interactive_diff_algorithm))
67+
s->interactive_diff_algorithm = NULL;
68+
69+
if (git_config_get_bool("interactive.singlekey",
70+
&s->use_single_key))
71+
s->use_single_key = 0;
5972

6073
return 0;
6174
}

add-interactive.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ 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
int init_add_i_state(struct repository *r, struct add_i_state *s);
@@ -27,6 +30,9 @@ enum color_add_i {
2730
COLOR_RESET,
2831
};
2932
const char *get_add_i_color(enum color_add_i ix);
33+
const char *get_interactive_diff_filter(void);
34+
const char *get_interactive_diff_algorithm(void);
35+
int get_interactive_use_single_key(void);
3036

3137
struct repository;
3238
struct pathspec;

add-patch.c

Lines changed: 51 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;
@@ -502,6 +525,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
502525
colored_pend - colored_p);
503526
if (colored_eol)
504527
colored_p = colored_eol + 1;
528+
else if (p != pend)
529+
/* colored shorter than non-colored? */
530+
goto mismatched_output;
505531
else
506532
colored_p = colored_pend;
507533

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

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

@@ -1063,14 +1098,27 @@ static int run_apply_check(struct add_p_state *s,
10631098
return 0;
10641099
}
10651100

1101+
static int read_single_character(struct add_p_state *s)
1102+
{
1103+
if (s->s.use_single_key) {
1104+
int res = read_key_without_echo(&s->answer);
1105+
printf("%s\n", res == EOF ? "" : s->answer.buf);
1106+
return res;
1107+
}
1108+
1109+
if (strbuf_getline(&s->answer, stdin) == EOF)
1110+
return EOF;
1111+
strbuf_trim_trailing_newline(&s->answer);
1112+
return 0;
1113+
}
1114+
10661115
static int prompt_yesno(struct add_p_state *s, const char *prompt)
10671116
{
10681117
for (;;) {
10691118
color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt));
10701119
fflush(stdout);
1071-
if (strbuf_getline(&s->answer, stdin) == EOF)
1120+
if (read_single_character(s) == EOF)
10721121
return -1;
1073-
strbuf_trim_trailing_newline(&s->answer);
10741122
switch (tolower(s->answer.buf[0])) {
10751123
case 'n': return 0;
10761124
case 'y': return 1;
@@ -1306,9 +1354,8 @@ static int patch_update_file(struct add_p_state *s,
13061354
_(s->mode->prompt_mode[prompt_mode_type]),
13071355
s->buf.buf);
13081356
fflush(stdout);
1309-
if (strbuf_getline(&s->answer, stdin) == EOF)
1357+
if (read_single_character(s) == EOF)
13101358
break;
1311-
strbuf_trim_trailing_newline(&s->answer);
13121359

13131360
if (!s->answer.len)
13141361
continue;

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)