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 ,
@@ -360,6 +361,7 @@ static int is_octal(const char *p, size_t len)
360
361
static int parse_diff (struct add_p_state * s , const struct pathspec * ps )
361
362
{
362
363
struct argv_array args = ARGV_ARRAY_INIT ;
364
+ const char * diff_algorithm = s -> s .interactive_diff_algorithm ;
363
365
struct strbuf * plain = & s -> plain , * colored = NULL ;
364
366
struct child_process cp = CHILD_PROCESS_INIT ;
365
367
char * p , * pend , * colored_p = NULL , * colored_pend = NULL , marker = '\0' ;
@@ -369,6 +371,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
369
371
int res ;
370
372
371
373
argv_array_pushv (& args , s -> mode -> diff_cmd );
374
+ if (diff_algorithm )
375
+ argv_array_pushf (& args , "--diff-algorithm=%s" , diff_algorithm );
372
376
if (s -> revision ) {
373
377
struct object_id oid ;
374
378
argv_array_push (& args ,
@@ -398,6 +402,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
398
402
399
403
if (want_color_fd (1 , -1 )) {
400
404
struct child_process colored_cp = CHILD_PROCESS_INIT ;
405
+ const char * diff_filter = s -> s .interactive_diff_filter ;
401
406
402
407
setup_child_process (s , & colored_cp , NULL );
403
408
xsnprintf ((char * )args .argv [color_arg_index ], 8 , "--color" );
@@ -407,6 +412,24 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
407
412
argv_array_clear (& args );
408
413
if (res )
409
414
return error (_ ("could not parse colored diff" ));
415
+
416
+ if (diff_filter ) {
417
+ struct child_process filter_cp = CHILD_PROCESS_INIT ;
418
+
419
+ setup_child_process (s , & filter_cp ,
420
+ diff_filter , NULL );
421
+ filter_cp .git_cmd = 0 ;
422
+ filter_cp .use_shell = 1 ;
423
+ strbuf_reset (& s -> buf );
424
+ if (pipe_command (& filter_cp ,
425
+ colored -> buf , colored -> len ,
426
+ & s -> buf , colored -> len ,
427
+ NULL , 0 ) < 0 )
428
+ return error (_ ("failed to run '%s'" ),
429
+ diff_filter );
430
+ strbuf_swap (colored , & s -> buf );
431
+ }
432
+
410
433
strbuf_complete_line (colored );
411
434
colored_p = colored -> buf ;
412
435
colored_pend = colored_p + colored -> len ;
@@ -531,6 +554,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
531
554
colored_pend - colored_p );
532
555
if (colored_eol )
533
556
colored_p = colored_eol + 1 ;
557
+ else if (p != pend )
558
+ /* colored shorter than non-colored? */
559
+ goto mismatched_output ;
534
560
else
535
561
colored_p = colored_pend ;
536
562
@@ -555,6 +581,15 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
555
581
*/
556
582
hunk -> splittable_into ++ ;
557
583
584
+ /* non-colored shorter than colored? */
585
+ if (colored_p != colored_pend ) {
586
+ mismatched_output :
587
+ error (_ ("mismatched output from interactive.diffFilter" ));
588
+ advise (_ ("Your filter must maintain a one-to-one correspondence\n"
589
+ "between its input and output lines." ));
590
+ return -1 ;
591
+ }
592
+
558
593
return 0 ;
559
594
}
560
595
@@ -1115,14 +1150,27 @@ static int run_apply_check(struct add_p_state *s,
1115
1150
return 0 ;
1116
1151
}
1117
1152
1153
+ static int read_single_character (struct add_p_state * s )
1154
+ {
1155
+ if (s -> s .use_single_key ) {
1156
+ int res = read_key_without_echo (& s -> answer );
1157
+ printf ("%s\n" , res == EOF ? "" : s -> answer .buf );
1158
+ return res ;
1159
+ }
1160
+
1161
+ if (strbuf_getline (& s -> answer , stdin ) == EOF )
1162
+ return EOF ;
1163
+ strbuf_trim_trailing_newline (& s -> answer );
1164
+ return 0 ;
1165
+ }
1166
+
1118
1167
static int prompt_yesno (struct add_p_state * s , const char * prompt )
1119
1168
{
1120
1169
for (;;) {
1121
1170
color_fprintf (stdout , s -> s .prompt_color , "%s" , _ (prompt ));
1122
1171
fflush (stdout );
1123
- if (strbuf_getline ( & s -> answer , stdin ) == EOF )
1172
+ if (read_single_character ( s ) == EOF )
1124
1173
return -1 ;
1125
- strbuf_trim_trailing_newline (& s -> answer );
1126
1174
switch (tolower (s -> answer .buf [0 ])) {
1127
1175
case 'n' : return 0 ;
1128
1176
case 'y' : return 1 ;
@@ -1362,9 +1410,8 @@ static int patch_update_file(struct add_p_state *s,
1362
1410
_ (s -> mode -> prompt_mode [prompt_mode_type ]),
1363
1411
s -> buf .buf );
1364
1412
fflush (stdout );
1365
- if (strbuf_getline ( & s -> answer , stdin ) == EOF )
1413
+ if (read_single_character ( s ) == EOF )
1366
1414
break ;
1367
- strbuf_trim_trailing_newline (& s -> answer );
1368
1415
1369
1416
if (!s -> answer .len )
1370
1417
continue ;
@@ -1612,6 +1659,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1612
1659
parse_diff (& s , ps ) < 0 ) {
1613
1660
strbuf_release (& s .plain );
1614
1661
strbuf_release (& s .colored );
1662
+ clear_add_i_state (& s .s );
1615
1663
return -1 ;
1616
1664
}
1617
1665
@@ -1630,5 +1678,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1630
1678
strbuf_release (& s .buf );
1631
1679
strbuf_release (& s .plain );
1632
1680
strbuf_release (& s .colored );
1681
+ clear_add_i_state (& s .s );
1633
1682
return 0 ;
1634
1683
}
0 commit comments