1
1
#include "cache.h"
2
2
#include "string-list.h"
3
+ #include "run-command.h"
4
+ #include "string-list.h"
3
5
#include "trailer.h"
4
6
/*
5
7
* Copyright (c) 2013, 2014 Christian Couder <[email protected] >
@@ -33,6 +35,8 @@ static struct trailer_item *first_conf_item;
33
35
34
36
static char * separators = ":" ;
35
37
38
+ #define TRAILER_ARG_STRING "$ARG"
39
+
36
40
static int after_or_end (enum action_where where )
37
41
{
38
42
return (where == WHERE_AFTER ) || (where == WHERE_END );
@@ -78,6 +82,13 @@ static inline int contains_only_spaces(const char *str)
78
82
return !* s ;
79
83
}
80
84
85
+ static inline void strbuf_replace (struct strbuf * sb , const char * a , const char * b )
86
+ {
87
+ const char * ptr = strstr (sb -> buf , a );
88
+ if (ptr )
89
+ strbuf_splice (sb , ptr - sb -> buf , strlen (a ), b , strlen (b ));
90
+ }
91
+
81
92
static void free_trailer_item (struct trailer_item * item )
82
93
{
83
94
free (item -> conf .name );
@@ -203,6 +214,63 @@ static struct trailer_item *remove_first(struct trailer_item **first)
203
214
return item ;
204
215
}
205
216
217
+ static int read_from_command (struct child_process * cp , struct strbuf * buf )
218
+ {
219
+ if (run_command (cp ))
220
+ return error ("running trailer command '%s' failed" , cp -> argv [0 ]);
221
+ if (strbuf_read (buf , cp -> out , 1024 ) < 1 )
222
+ return error ("reading from trailer command '%s' failed" , cp -> argv [0 ]);
223
+ strbuf_trim (buf );
224
+ return 0 ;
225
+ }
226
+
227
+ static const char * apply_command (const char * command , const char * arg )
228
+ {
229
+ struct strbuf cmd = STRBUF_INIT ;
230
+ struct strbuf buf = STRBUF_INIT ;
231
+ struct child_process cp ;
232
+ const char * argv [] = {NULL , NULL };
233
+ const char * result ;
234
+
235
+ strbuf_addstr (& cmd , command );
236
+ if (arg )
237
+ strbuf_replace (& cmd , TRAILER_ARG_STRING , arg );
238
+
239
+ argv [0 ] = cmd .buf ;
240
+ memset (& cp , 0 , sizeof (cp ));
241
+ cp .argv = argv ;
242
+ cp .env = local_repo_env ;
243
+ cp .no_stdin = 1 ;
244
+ cp .out = -1 ;
245
+ cp .use_shell = 1 ;
246
+
247
+ if (read_from_command (& cp , & buf )) {
248
+ strbuf_release (& buf );
249
+ result = xstrdup ("" );
250
+ } else
251
+ result = strbuf_detach (& buf , NULL );
252
+
253
+ strbuf_release (& cmd );
254
+ return result ;
255
+ }
256
+
257
+ static void apply_item_command (struct trailer_item * in_tok , struct trailer_item * arg_tok )
258
+ {
259
+ if (arg_tok -> conf .command ) {
260
+ const char * arg ;
261
+ if (arg_tok -> value && arg_tok -> value [0 ]) {
262
+ arg = arg_tok -> value ;
263
+ } else {
264
+ if (in_tok && in_tok -> value )
265
+ arg = xstrdup (in_tok -> value );
266
+ else
267
+ arg = xstrdup ("" );
268
+ }
269
+ arg_tok -> value = apply_command (arg_tok -> conf .command , arg );
270
+ free ((char * )arg );
271
+ }
272
+ }
273
+
206
274
static void apply_arg_if_exists (struct trailer_item * in_tok ,
207
275
struct trailer_item * arg_tok ,
208
276
struct trailer_item * on_tok ,
@@ -214,23 +282,27 @@ static void apply_arg_if_exists(struct trailer_item *in_tok,
214
282
free_trailer_item (arg_tok );
215
283
break ;
216
284
case EXISTS_REPLACE :
285
+ apply_item_command (in_tok , arg_tok );
217
286
add_arg_to_input_list (on_tok , arg_tok ,
218
287
in_tok_first , in_tok_last );
219
288
remove_from_list (in_tok , in_tok_first , in_tok_last );
220
289
free_trailer_item (in_tok );
221
290
break ;
222
291
case EXISTS_ADD :
292
+ apply_item_command (in_tok , arg_tok );
223
293
add_arg_to_input_list (on_tok , arg_tok ,
224
294
in_tok_first , in_tok_last );
225
295
break ;
226
296
case EXISTS_ADD_IF_DIFFERENT :
297
+ apply_item_command (in_tok , arg_tok );
227
298
if (check_if_different (in_tok , arg_tok , 1 ))
228
299
add_arg_to_input_list (on_tok , arg_tok ,
229
300
in_tok_first , in_tok_last );
230
301
else
231
302
free_trailer_item (arg_tok );
232
303
break ;
233
304
case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR :
305
+ apply_item_command (in_tok , arg_tok );
234
306
if (check_if_different (on_tok , arg_tok , 0 ))
235
307
add_arg_to_input_list (on_tok , arg_tok ,
236
308
in_tok_first , in_tok_last );
@@ -254,6 +326,7 @@ static void apply_arg_if_missing(struct trailer_item **in_tok_first,
254
326
case MISSING_ADD :
255
327
where = arg_tok -> conf .where ;
256
328
in_tok = after_or_end (where ) ? in_tok_last : in_tok_first ;
329
+ apply_item_command (NULL , arg_tok );
257
330
if (* in_tok ) {
258
331
add_arg_to_input_list (* in_tok , arg_tok ,
259
332
in_tok_first , in_tok_last );
@@ -537,7 +610,7 @@ static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
537
610
char * tok , char * val )
538
611
{
539
612
struct trailer_item * new = xcalloc (sizeof (* new ), 1 );
540
- new -> value = val ;
613
+ new -> value = val ? val : xstrdup ( "" ) ;
541
614
542
615
if (conf_item ) {
543
616
duplicate_conf (& new -> conf , & conf_item -> conf );
@@ -604,7 +677,17 @@ static struct trailer_item *process_command_line_args(struct string_list *traile
604
677
struct trailer_item * arg_tok_first = NULL ;
605
678
struct trailer_item * arg_tok_last = NULL ;
606
679
struct string_list_item * tr ;
680
+ struct trailer_item * item ;
681
+
682
+ /* Add a trailer item for each configured trailer with a command */
683
+ for (item = first_conf_item ; item ; item = item -> next ) {
684
+ if (item -> conf .command ) {
685
+ struct trailer_item * new = new_trailer_item (item , NULL , NULL );
686
+ add_trailer_item (& arg_tok_first , & arg_tok_last , new );
687
+ }
688
+ }
607
689
690
+ /* Add a trailer item for each trailer on the command line */
608
691
for_each_string_list_item (tr , trailers ) {
609
692
struct trailer_item * new = create_trailer_item (tr -> string );
610
693
add_trailer_item (& arg_tok_first , & arg_tok_last , new );
0 commit comments