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
@@ -310,6 +311,7 @@ static int is_octal(const char *p, size_t len)
310311static 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+
10161065static 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 ;
0 commit comments