6
6
#include "pathspec.h"
7
7
#include "color.h"
8
8
#include "diff.h"
9
+ #include "compat/terminal.h"
9
10
10
11
enum prompt_mode_type {
11
12
PROMPT_MODE_CHANGE = 0 , PROMPT_DELETION , PROMPT_HUNK
@@ -354,6 +355,7 @@ static int is_octal(const char *p, size_t len)
354
355
static int parse_diff (struct add_p_state * s , const struct pathspec * ps )
355
356
{
356
357
struct argv_array args = ARGV_ARRAY_INIT ;
358
+ const char * diff_algorithm = s -> s .interactive_diff_algorithm ;
357
359
struct strbuf * plain = & s -> plain , * colored = NULL ;
358
360
struct child_process cp = CHILD_PROCESS_INIT ;
359
361
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)
363
365
int res ;
364
366
365
367
argv_array_pushv (& args , s -> mode -> diff );
368
+ if (diff_algorithm )
369
+ argv_array_pushf (& args , "--diff-algorithm=%s" , diff_algorithm );
366
370
if (s -> revision ) {
367
371
struct object_id oid ;
368
372
argv_array_push (& args ,
@@ -392,6 +396,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
392
396
393
397
if (want_color_fd (1 , -1 )) {
394
398
struct child_process colored_cp = CHILD_PROCESS_INIT ;
399
+ const char * diff_filter = s -> s .interactive_diff_filter ;
395
400
396
401
setup_child_process (& colored_cp , s , NULL );
397
402
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)
401
406
argv_array_clear (& args );
402
407
if (res )
403
408
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
+
404
427
strbuf_complete_line (colored );
405
428
colored_p = colored -> buf ;
406
429
colored_pend = colored_p + colored -> len ;
@@ -501,6 +524,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
501
524
colored_pend - colored_p );
502
525
if (colored_eol )
503
526
colored_p = colored_eol + 1 ;
527
+ else if (p != pend )
528
+ /* colored shorter than non-colored? */
529
+ goto mismatched_output ;
504
530
else
505
531
colored_p = colored_pend ;
506
532
@@ -522,6 +548,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
522
548
*/
523
549
hunk -> splittable_into ++ ;
524
550
551
+ /* non-colored shorter than colored? */
552
+ if (colored_p != colored_pend ) {
553
+ mismatched_output :
554
+ error (_ ("mismatched output from interactive.diffFilter" ));
555
+ advise (_ ("Your filter must maintain a one-to-one correspondence\n"
556
+ "between its input and output lines." ));
557
+ return -1 ;
558
+ }
559
+
525
560
return 0 ;
526
561
}
527
562
@@ -1089,14 +1124,27 @@ static int run_apply_check(struct add_p_state *s,
1089
1124
return 0 ;
1090
1125
}
1091
1126
1127
+ static int read_single_character (struct add_p_state * s )
1128
+ {
1129
+ if (s -> s .use_single_key ) {
1130
+ int res = read_key_without_echo (& s -> answer );
1131
+ printf ("%s\n" , res == EOF ? "" : s -> answer .buf );
1132
+ return res ;
1133
+ }
1134
+
1135
+ if (strbuf_getline (& s -> answer , stdin ) == EOF )
1136
+ return EOF ;
1137
+ strbuf_trim_trailing_newline (& s -> answer );
1138
+ return 0 ;
1139
+ }
1140
+
1092
1141
static int prompt_yesno (struct add_p_state * s , const char * prompt )
1093
1142
{
1094
1143
for (;;) {
1095
1144
color_fprintf (stdout , s -> s .prompt_color , "%s" , _ (prompt ));
1096
1145
fflush (stdout );
1097
- if (strbuf_getline ( & s -> answer , stdin ) == EOF )
1146
+ if (read_single_character ( s ) == EOF )
1098
1147
return -1 ;
1099
- strbuf_trim_trailing_newline (& s -> answer );
1100
1148
switch (tolower (s -> answer .buf [0 ])) {
1101
1149
case 'n' : return 0 ;
1102
1150
case 'y' : return 1 ;
@@ -1336,9 +1384,8 @@ static int patch_update_file(struct add_p_state *s,
1336
1384
_ (s -> mode -> prompt_mode [prompt_mode_type ]),
1337
1385
s -> buf .buf );
1338
1386
fflush (stdout );
1339
- if (strbuf_getline ( & s -> answer , stdin ) == EOF )
1387
+ if (read_single_character ( s ) == EOF )
1340
1388
break ;
1341
- strbuf_trim_trailing_newline (& s -> answer );
1342
1389
1343
1390
if (!s -> answer .len )
1344
1391
continue ;
@@ -1585,6 +1632,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1585
1632
parse_diff (& s , ps ) < 0 ) {
1586
1633
strbuf_release (& s .plain );
1587
1634
strbuf_release (& s .colored );
1635
+ clear_add_i_state (& s .s );
1588
1636
return -1 ;
1589
1637
}
1590
1638
@@ -1603,5 +1651,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1603
1651
strbuf_release (& s .buf );
1604
1652
strbuf_release (& s .plain );
1605
1653
strbuf_release (& s .colored );
1654
+ clear_add_i_state (& s .s );
1606
1655
return 0 ;
1607
1656
}
0 commit comments