66#include "pathspec.h"
77#include "color.h"
88#include "diff.h"
9+ #include "compat/terminal.h"
910
1011enum prompt_mode_type {
1112 PROMPT_MODE_CHANGE = 0 , PROMPT_DELETION , PROMPT_HUNK
@@ -309,6 +310,7 @@ static int is_octal(const char *p, size_t len)
309310static int parse_diff (struct add_p_state * s , const struct pathspec * ps )
310311{
311312 struct argv_array args = ARGV_ARRAY_INIT ;
313+ const char * diff_algorithm = s -> s .interactive_diff_algorithm ;
312314 struct strbuf * plain = & s -> plain , * colored = NULL ;
313315 struct child_process cp = CHILD_PROCESS_INIT ;
314316 char * p , * pend , * colored_p = NULL , * colored_pend = NULL , marker = '\0' ;
@@ -318,6 +320,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
318320 int res ;
319321
320322 argv_array_pushv (& args , s -> mode -> diff );
323+ if (diff_algorithm )
324+ argv_array_pushf (& args , "--diff-algorithm=%s" , diff_algorithm );
321325 if (s -> revision ) {
322326 struct object_id oid ;
323327 argv_array_push (& args ,
@@ -347,6 +351,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
347351
348352 if (want_color_fd (1 , -1 )) {
349353 struct child_process colored_cp = CHILD_PROCESS_INIT ;
354+ const char * diff_filter = s -> s .interactive_diff_filter ;
350355
351356 setup_child_process (& colored_cp , s , NULL );
352357 xsnprintf ((char * )args .argv [color_arg_index ], 8 , "--color" );
@@ -356,6 +361,24 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
356361 argv_array_clear (& args );
357362 if (res )
358363 return error (_ ("could not parse colored diff" ));
364+
365+ if (diff_filter ) {
366+ struct child_process filter_cp = CHILD_PROCESS_INIT ;
367+
368+ setup_child_process (& filter_cp , s ,
369+ diff_filter , NULL );
370+ filter_cp .git_cmd = 0 ;
371+ filter_cp .use_shell = 1 ;
372+ strbuf_reset (& s -> buf );
373+ if (pipe_command (& filter_cp ,
374+ colored -> buf , colored -> len ,
375+ & s -> buf , colored -> len ,
376+ NULL , 0 ) < 0 )
377+ return error (_ ("failed to run '%s'" ),
378+ diff_filter );
379+ strbuf_swap (colored , & s -> buf );
380+ }
381+
359382 strbuf_complete_line (colored );
360383 colored_p = colored -> buf ;
361384 colored_pend = colored_p + colored -> len ;
@@ -457,6 +480,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
457480 colored_pend - colored_p );
458481 if (colored_eol )
459482 colored_p = colored_eol + 1 ;
483+ else if (p != pend )
484+ /* colored shorter than non-colored? */
485+ goto mismatched_output ;
460486 else
461487 colored_p = colored_pend ;
462488
@@ -478,6 +504,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
478504 */
479505 hunk -> splittable_into ++ ;
480506
507+ /* non-colored shorter than colored? */
508+ if (colored_p != colored_pend ) {
509+ mismatched_output :
510+ error (_ ("mismatched output from interactive.diffFilter" ));
511+ advise (_ ("Your filter must maintain a one-to-one correspondence\n"
512+ "between its input and output lines." ));
513+ return -1 ;
514+ }
515+
481516 return 0 ;
482517}
483518
@@ -1012,14 +1047,27 @@ static int run_apply_check(struct add_p_state *s,
10121047 return 0 ;
10131048}
10141049
1050+ static int read_single_character (struct add_p_state * s )
1051+ {
1052+ if (s -> s .use_single_key ) {
1053+ int res = read_key_without_echo (& s -> answer );
1054+ printf ("%s\n" , res == EOF ? "" : s -> answer .buf );
1055+ return res ;
1056+ }
1057+
1058+ if (strbuf_getline (& s -> answer , stdin ) == EOF )
1059+ return EOF ;
1060+ strbuf_trim_trailing_newline (& s -> answer );
1061+ return 0 ;
1062+ }
1063+
10151064static int prompt_yesno (struct add_p_state * s , const char * prompt )
10161065{
10171066 for (;;) {
10181067 color_fprintf (stdout , s -> s .prompt_color , "%s" , _ (prompt ));
10191068 fflush (stdout );
1020- if (strbuf_getline ( & s -> answer , stdin ) == EOF )
1069+ if (read_single_character ( s ) == EOF )
10211070 return -1 ;
1022- strbuf_trim_trailing_newline (& s -> answer );
10231071 switch (tolower (s -> answer .buf [0 ])) {
10241072 case 'n' : return 0 ;
10251073 case 'y' : return 1 ;
@@ -1255,9 +1303,8 @@ static int patch_update_file(struct add_p_state *s,
12551303 _ (s -> mode -> prompt_mode [prompt_mode_type ]),
12561304 s -> buf .buf );
12571305 fflush (stdout );
1258- if (strbuf_getline ( & s -> answer , stdin ) == EOF )
1306+ if (read_single_character ( s ) == EOF )
12591307 break ;
1260- strbuf_trim_trailing_newline (& s -> answer );
12611308
12621309 if (!s -> answer .len )
12631310 continue ;
0 commit comments