4
4
#include "run-command.h"
5
5
#include "argv-array.h"
6
6
#include "pathspec.h"
7
+ #include "color.h"
7
8
8
9
struct hunk {
9
- size_t start , end ;
10
+ size_t start , end , colored_start , colored_end ;
10
11
enum { UNDECIDED_HUNK = 0 , SKIP_HUNK , USE_HUNK } use ;
11
12
};
12
13
@@ -15,7 +16,7 @@ struct add_p_state {
15
16
struct strbuf answer , buf ;
16
17
17
18
/* parsed diff */
18
- struct strbuf plain ;
19
+ struct strbuf plain , colored ;
19
20
struct hunk head ;
20
21
struct hunk * hunk ;
21
22
size_t hunk_nr , hunk_alloc ;
@@ -39,26 +40,50 @@ static void setup_child_process(struct child_process *cp,
39
40
40
41
static int parse_diff (struct add_p_state * s , const struct pathspec * ps )
41
42
{
42
- struct strbuf * plain = & s -> plain ;
43
+ struct argv_array args = ARGV_ARRAY_INIT ;
44
+ struct strbuf * plain = & s -> plain , * colored = NULL ;
43
45
struct child_process cp = CHILD_PROCESS_INIT ;
44
- char * p , * pend ;
45
- size_t i ;
46
+ char * p , * pend , * colored_p = NULL , * colored_pend = NULL ;
47
+ size_t i , color_arg_index ;
46
48
struct hunk * hunk = NULL ;
47
49
int res ;
48
50
49
51
/* Use `--no-color` explicitly, just in case `diff.color = always`. */
50
- setup_child_process ( & cp , s ,
51
- "diff-files" , "-p" , "--no-color" , "--" , NULL ) ;
52
+ argv_array_pushl ( & args , "diff-files" , "-p" , "--no-color" , "--" , NULL );
53
+ color_arg_index = args . argc - 2 ;
52
54
for (i = 0 ; i < ps -> nr ; i ++ )
53
- argv_array_push (& cp . args , ps -> items [i ].original );
55
+ argv_array_push (& args , ps -> items [i ].original );
54
56
57
+ setup_child_process (& cp , s , NULL );
58
+ cp .argv = args .argv ;
55
59
res = capture_command (& cp , plain , 0 );
56
- if (res )
60
+ if (res ) {
61
+ argv_array_clear (& args );
57
62
return error (_ ("could not parse diff" ));
58
- if (!plain -> len )
63
+ }
64
+ if (!plain -> len ) {
65
+ argv_array_clear (& args );
59
66
return 0 ;
67
+ }
60
68
strbuf_complete_line (plain );
61
69
70
+ if (want_color_fd (1 , -1 )) {
71
+ struct child_process colored_cp = CHILD_PROCESS_INIT ;
72
+
73
+ setup_child_process (& colored_cp , s , NULL );
74
+ xsnprintf ((char * )args .argv [color_arg_index ], 8 , "--color" );
75
+ colored_cp .argv = args .argv ;
76
+ colored = & s -> colored ;
77
+ res = capture_command (& colored_cp , colored , 0 );
78
+ argv_array_clear (& args );
79
+ if (res )
80
+ return error (_ ("could not parse colored diff" ));
81
+ strbuf_complete_line (colored );
82
+ colored_p = colored -> buf ;
83
+ colored_pend = colored_p + colored -> len ;
84
+ }
85
+ argv_array_clear (& args );
86
+
62
87
/* parse hunks */
63
88
p = plain -> buf ;
64
89
pend = p + plain -> len ;
@@ -82,33 +107,50 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
82
107
memset (hunk , 0 , sizeof (* hunk ));
83
108
84
109
hunk -> start = p - plain -> buf ;
110
+ if (colored )
111
+ hunk -> colored_start = colored_p - colored -> buf ;
85
112
}
86
113
87
114
p = eol == pend ? pend : eol + 1 ;
88
115
hunk -> end = p - plain -> buf ;
116
+
117
+ if (colored ) {
118
+ char * colored_eol = memchr (colored_p , '\n' ,
119
+ colored_pend - colored_p );
120
+ if (colored_eol )
121
+ colored_p = colored_eol + 1 ;
122
+ else
123
+ colored_p = colored_pend ;
124
+
125
+ hunk -> colored_end = colored_p - colored -> buf ;
126
+ }
89
127
}
90
128
91
129
return 0 ;
92
130
}
93
131
94
132
static void render_hunk (struct add_p_state * s , struct hunk * hunk ,
95
- struct strbuf * out )
133
+ int colored , struct strbuf * out )
96
134
{
97
- strbuf_add (out , s -> plain .buf + hunk -> start ,
98
- hunk -> end - hunk -> start );
135
+ if (colored )
136
+ strbuf_add (out , s -> colored .buf + hunk -> colored_start ,
137
+ hunk -> colored_end - hunk -> colored_start );
138
+ else
139
+ strbuf_add (out , s -> plain .buf + hunk -> start ,
140
+ hunk -> end - hunk -> start );
99
141
}
100
142
101
143
static void reassemble_patch (struct add_p_state * s , struct strbuf * out )
102
144
{
103
145
struct hunk * hunk ;
104
146
size_t i ;
105
147
106
- render_hunk (s , & s -> head , out );
148
+ render_hunk (s , & s -> head , 0 , out );
107
149
108
150
for (i = 0 ; i < s -> hunk_nr ; i ++ ) {
109
151
hunk = s -> hunk + i ;
110
152
if (hunk -> use == USE_HUNK )
111
- render_hunk (s , hunk , out );
153
+ render_hunk (s , hunk , 0 , out );
112
154
}
113
155
}
114
156
@@ -130,12 +172,13 @@ static int patch_update_file(struct add_p_state *s)
130
172
struct hunk * hunk ;
131
173
char ch ;
132
174
struct child_process cp = CHILD_PROCESS_INIT ;
175
+ int colored = !!s -> colored .len ;
133
176
134
177
if (!s -> hunk_nr )
135
178
return 0 ;
136
179
137
180
strbuf_reset (& s -> buf );
138
- render_hunk (s , & s -> head , & s -> buf );
181
+ render_hunk (s , & s -> head , colored , & s -> buf );
139
182
fputs (s -> buf .buf , stdout );
140
183
for (;;) {
141
184
if (hunk_index >= s -> hunk_nr )
@@ -162,7 +205,7 @@ static int patch_update_file(struct add_p_state *s)
162
205
break ;
163
206
164
207
strbuf_reset (& s -> buf );
165
- render_hunk (s , hunk , & s -> buf );
208
+ render_hunk (s , hunk , colored , & s -> buf );
166
209
fputs (s -> buf .buf , stdout );
167
210
168
211
strbuf_reset (& s -> buf );
@@ -247,6 +290,7 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
247
290
if (repo_refresh_and_write_index (r , REFRESH_QUIET , 0 ) < 0 ||
248
291
parse_diff (& s , ps ) < 0 ) {
249
292
strbuf_release (& s .plain );
293
+ strbuf_release (& s .colored );
250
294
return -1 ;
251
295
}
252
296
@@ -256,5 +300,6 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
256
300
strbuf_release (& s .answer );
257
301
strbuf_release (& s .buf );
258
302
strbuf_release (& s .plain );
303
+ strbuf_release (& s .colored );
259
304
return 0 ;
260
305
}
0 commit comments