Skip to content

Commit 0368265

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 8302074 + 20b81be commit 0368265

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
@@ -310,6 +311,7 @@ static int is_octal(const char *p, size_t len)
310311
static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
311312
{
312313
struct argv_array args = ARGV_ARRAY_INIT;
314+
const char *diff_algorithm = s->s.interactive_diff_algorithm;
313315
struct strbuf *plain = &s->plain, *colored = NULL;
314316
struct child_process cp = CHILD_PROCESS_INIT;
315317
char *p, *pend, *colored_p = NULL, *colored_pend = NULL, marker = '\0';
@@ -319,6 +321,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
319321
int res;
320322

321323
argv_array_pushv(&args, s->mode->diff);
324+
if (diff_algorithm)
325+
argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
322326
if (s->revision) {
323327
struct object_id oid;
324328
argv_array_push(&args,
@@ -348,6 +352,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
348352

349353
if (want_color_fd(1, -1)) {
350354
struct child_process colored_cp = CHILD_PROCESS_INIT;
355+
const char *diff_filter = s->s.interactive_diff_filter;
351356

352357
setup_child_process(&colored_cp, s, NULL);
353358
xsnprintf((char *)args.argv[color_arg_index], 8, "--color");
@@ -357,6 +362,24 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
357362
argv_array_clear(&args);
358363
if (res)
359364
return error(_("could not parse colored diff"));
365+
366+
if (diff_filter) {
367+
struct child_process filter_cp = CHILD_PROCESS_INIT;
368+
369+
setup_child_process(&filter_cp, s,
370+
diff_filter, NULL);
371+
filter_cp.git_cmd = 0;
372+
filter_cp.use_shell = 1;
373+
strbuf_reset(&s->buf);
374+
if (pipe_command(&filter_cp,
375+
colored->buf, colored->len,
376+
&s->buf, colored->len,
377+
NULL, 0) < 0)
378+
return error(_("failed to run '%s'"),
379+
diff_filter);
380+
strbuf_swap(colored, &s->buf);
381+
}
382+
360383
strbuf_complete_line(colored);
361384
colored_p = colored->buf;
362385
colored_pend = colored_p + colored->len;
@@ -458,6 +481,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
458481
colored_pend - colored_p);
459482
if (colored_eol)
460483
colored_p = colored_eol + 1;
484+
else if (p != pend)
485+
/* colored shorter than non-colored? */
486+
goto mismatched_output;
461487
else
462488
colored_p = colored_pend;
463489

@@ -479,6 +505,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
479505
*/
480506
hunk->splittable_into++;
481507

508+
/* non-colored shorter than colored? */
509+
if (colored_p != colored_pend) {
510+
mismatched_output:
511+
error(_("mismatched output from interactive.diffFilter"));
512+
advise(_("Your filter must maintain a one-to-one correspondence\n"
513+
"between its input and output lines."));
514+
return -1;
515+
}
516+
482517
return 0;
483518
}
484519

@@ -1013,14 +1048,27 @@ static int run_apply_check(struct add_p_state *s,
10131048
return 0;
10141049
}
10151050

1051+
static int read_single_character(struct add_p_state *s)
1052+
{
1053+
if (s->s.use_single_key) {
1054+
int res = read_key_without_echo(&s->answer);
1055+
printf("%s\n", res == EOF ? "" : s->answer.buf);
1056+
return res;
1057+
}
1058+
1059+
if (strbuf_getline(&s->answer, stdin) == EOF)
1060+
return EOF;
1061+
strbuf_trim_trailing_newline(&s->answer);
1062+
return 0;
1063+
}
1064+
10161065
static int prompt_yesno(struct add_p_state *s, const char *prompt)
10171066
{
10181067
for (;;) {
10191068
color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt));
10201069
fflush(stdout);
1021-
if (strbuf_getline(&s->answer, stdin) == EOF)
1070+
if (read_single_character(s) == EOF)
10221071
return -1;
1023-
strbuf_trim_trailing_newline(&s->answer);
10241072
switch (tolower(s->answer.buf[0])) {
10251073
case 'n': return 0;
10261074
case 'y': return 1;
@@ -1256,9 +1304,8 @@ static int patch_update_file(struct add_p_state *s,
12561304
_(s->mode->prompt_mode[prompt_mode_type]),
12571305
s->buf.buf);
12581306
fflush(stdout);
1259-
if (strbuf_getline(&s->answer, stdin) == EOF)
1307+
if (read_single_character(s) == EOF)
12601308
break;
1261-
strbuf_trim_trailing_newline(&s->answer);
12621309

12631310
if (!s->answer.len)
12641311
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 @@ then
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
fi
2526

0 commit comments

Comments
 (0)