2 #include "string-list.h"
3 #include "run-command.h"
8 * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
11 enum action_where
{ WHERE_END
, WHERE_AFTER
, WHERE_BEFORE
, WHERE_START
};
12 enum action_if_exists
{ EXISTS_ADD_IF_DIFFERENT_NEIGHBOR
, EXISTS_ADD_IF_DIFFERENT
,
13 EXISTS_ADD
, EXISTS_REPLACE
, EXISTS_DO_NOTHING
};
14 enum action_if_missing
{ MISSING_ADD
, MISSING_DO_NOTHING
};
20 enum action_where where
;
21 enum action_if_exists if_exists
;
22 enum action_if_missing if_missing
;
25 static struct conf_info default_conf_info
;
28 struct trailer_item
*previous
;
29 struct trailer_item
*next
;
32 struct conf_info conf
;
35 static struct trailer_item
*first_conf_item
;
37 static char *separators
= ":";
39 #define TRAILER_ARG_STRING "$ARG"
41 static int after_or_end(enum action_where where
)
43 return (where
== WHERE_AFTER
) || (where
== WHERE_END
);
47 * Return the length of the string not including any final
48 * punctuation. E.g., the input "Signed-off-by:" would return
49 * 13, stripping the trailing punctuation but retaining
50 * internal punctuation.
52 static size_t token_len_without_separator(const char *token
, size_t len
)
54 while (len
> 0 && !isalnum(token
[len
- 1]))
59 static int same_token(struct trailer_item
*a
, struct trailer_item
*b
)
61 size_t a_len
= token_len_without_separator(a
->token
, strlen(a
->token
));
62 size_t b_len
= token_len_without_separator(b
->token
, strlen(b
->token
));
63 size_t min_len
= (a_len
> b_len
) ? b_len
: a_len
;
65 return !strncasecmp(a
->token
, b
->token
, min_len
);
68 static int same_value(struct trailer_item
*a
, struct trailer_item
*b
)
70 return !strcasecmp(a
->value
, b
->value
);
73 static int same_trailer(struct trailer_item
*a
, struct trailer_item
*b
)
75 return same_token(a
, b
) && same_value(a
, b
);
78 static inline int contains_only_spaces(const char *str
)
81 while (*s
&& isspace(*s
))
86 static inline void strbuf_replace(struct strbuf
*sb
, const char *a
, const char *b
)
88 const char *ptr
= strstr(sb
->buf
, a
);
90 strbuf_splice(sb
, ptr
- sb
->buf
, strlen(a
), b
, strlen(b
));
93 static void free_trailer_item(struct trailer_item
*item
)
95 free(item
->conf
.name
);
97 free(item
->conf
.command
);
98 free((char *)item
->token
);
99 free((char *)item
->value
);
103 static char last_non_space_char(const char *s
)
106 for (i
= strlen(s
) - 1; i
>= 0; i
--)
112 static void print_tok_val(FILE *outfile
, const char *tok
, const char *val
)
114 char c
= last_non_space_char(tok
);
117 if (strchr(separators
, c
))
118 fprintf(outfile
, "%s%s\n", tok
, val
);
120 fprintf(outfile
, "%s%c %s\n", tok
, separators
[0], val
);
123 static void print_all(FILE *outfile
, struct trailer_item
*first
, int trim_empty
)
125 struct trailer_item
*item
;
126 for (item
= first
; item
; item
= item
->next
) {
127 if (!trim_empty
|| strlen(item
->value
) > 0)
128 print_tok_val(outfile
, item
->token
, item
->value
);
132 static void update_last(struct trailer_item
**last
)
135 while ((*last
)->next
!= NULL
)
136 *last
= (*last
)->next
;
139 static void update_first(struct trailer_item
**first
)
142 while ((*first
)->previous
!= NULL
)
143 *first
= (*first
)->previous
;
146 static void add_arg_to_input_list(struct trailer_item
*on_tok
,
147 struct trailer_item
*arg_tok
,
148 struct trailer_item
**first
,
149 struct trailer_item
**last
)
151 if (after_or_end(arg_tok
->conf
.where
)) {
152 arg_tok
->next
= on_tok
->next
;
153 on_tok
->next
= arg_tok
;
154 arg_tok
->previous
= on_tok
;
156 arg_tok
->next
->previous
= arg_tok
;
159 arg_tok
->previous
= on_tok
->previous
;
160 on_tok
->previous
= arg_tok
;
161 arg_tok
->next
= on_tok
;
162 if (arg_tok
->previous
)
163 arg_tok
->previous
->next
= arg_tok
;
168 static int check_if_different(struct trailer_item
*in_tok
,
169 struct trailer_item
*arg_tok
,
172 enum action_where where
= arg_tok
->conf
.where
;
176 if (same_trailer(in_tok
, arg_tok
))
179 * if we want to add a trailer after another one,
180 * we have to check those before this one
182 in_tok
= after_or_end(where
) ? in_tok
->previous
: in_tok
->next
;
187 static void remove_from_list(struct trailer_item
*item
,
188 struct trailer_item
**first
,
189 struct trailer_item
**last
)
191 struct trailer_item
*next
= item
->next
;
192 struct trailer_item
*previous
= item
->previous
;
195 item
->next
->previous
= previous
;
201 item
->previous
->next
= next
;
202 item
->previous
= NULL
;
207 static struct trailer_item
*remove_first(struct trailer_item
**first
)
209 struct trailer_item
*item
= *first
;
212 item
->next
->previous
= NULL
;
218 static const char *apply_command(const char *command
, const char *arg
)
220 struct strbuf cmd
= STRBUF_INIT
;
221 struct strbuf buf
= STRBUF_INIT
;
222 struct child_process cp
= CHILD_PROCESS_INIT
;
223 const char *argv
[] = {NULL
, NULL
};
226 strbuf_addstr(&cmd
, command
);
228 strbuf_replace(&cmd
, TRAILER_ARG_STRING
, arg
);
232 cp
.env
= local_repo_env
;
236 if (capture_command(&cp
, &buf
, 1024)) {
237 error(_("running trailer command '%s' failed"), cmd
.buf
);
238 strbuf_release(&buf
);
239 result
= xstrdup("");
242 result
= strbuf_detach(&buf
, NULL
);
245 strbuf_release(&cmd
);
249 static void apply_item_command(struct trailer_item
*in_tok
, struct trailer_item
*arg_tok
)
251 if (arg_tok
->conf
.command
) {
253 if (arg_tok
->value
&& arg_tok
->value
[0]) {
254 arg
= arg_tok
->value
;
256 if (in_tok
&& in_tok
->value
)
257 arg
= xstrdup(in_tok
->value
);
261 arg_tok
->value
= apply_command(arg_tok
->conf
.command
, arg
);
266 static void apply_arg_if_exists(struct trailer_item
*in_tok
,
267 struct trailer_item
*arg_tok
,
268 struct trailer_item
*on_tok
,
269 struct trailer_item
**in_tok_first
,
270 struct trailer_item
**in_tok_last
)
272 switch (arg_tok
->conf
.if_exists
) {
273 case EXISTS_DO_NOTHING
:
274 free_trailer_item(arg_tok
);
277 apply_item_command(in_tok
, arg_tok
);
278 add_arg_to_input_list(on_tok
, arg_tok
,
279 in_tok_first
, in_tok_last
);
280 remove_from_list(in_tok
, in_tok_first
, in_tok_last
);
281 free_trailer_item(in_tok
);
284 apply_item_command(in_tok
, arg_tok
);
285 add_arg_to_input_list(on_tok
, arg_tok
,
286 in_tok_first
, in_tok_last
);
288 case EXISTS_ADD_IF_DIFFERENT
:
289 apply_item_command(in_tok
, arg_tok
);
290 if (check_if_different(in_tok
, arg_tok
, 1))
291 add_arg_to_input_list(on_tok
, arg_tok
,
292 in_tok_first
, in_tok_last
);
294 free_trailer_item(arg_tok
);
296 case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR
:
297 apply_item_command(in_tok
, arg_tok
);
298 if (check_if_different(on_tok
, arg_tok
, 0))
299 add_arg_to_input_list(on_tok
, arg_tok
,
300 in_tok_first
, in_tok_last
);
302 free_trailer_item(arg_tok
);
307 static void apply_arg_if_missing(struct trailer_item
**in_tok_first
,
308 struct trailer_item
**in_tok_last
,
309 struct trailer_item
*arg_tok
)
311 struct trailer_item
**in_tok
;
312 enum action_where where
;
314 switch (arg_tok
->conf
.if_missing
) {
315 case MISSING_DO_NOTHING
:
316 free_trailer_item(arg_tok
);
319 where
= arg_tok
->conf
.where
;
320 in_tok
= after_or_end(where
) ? in_tok_last
: in_tok_first
;
321 apply_item_command(NULL
, arg_tok
);
323 add_arg_to_input_list(*in_tok
, arg_tok
,
324 in_tok_first
, in_tok_last
);
326 *in_tok_first
= arg_tok
;
327 *in_tok_last
= arg_tok
;
333 static int find_same_and_apply_arg(struct trailer_item
**in_tok_first
,
334 struct trailer_item
**in_tok_last
,
335 struct trailer_item
*arg_tok
)
337 struct trailer_item
*in_tok
;
338 struct trailer_item
*on_tok
;
339 struct trailer_item
*following_tok
;
341 enum action_where where
= arg_tok
->conf
.where
;
342 int middle
= (where
== WHERE_AFTER
) || (where
== WHERE_BEFORE
);
343 int backwards
= after_or_end(where
);
344 struct trailer_item
*start_tok
= backwards
? *in_tok_last
: *in_tok_first
;
346 for (in_tok
= start_tok
; in_tok
; in_tok
= following_tok
) {
347 following_tok
= backwards
? in_tok
->previous
: in_tok
->next
;
348 if (!same_token(in_tok
, arg_tok
))
350 on_tok
= middle
? in_tok
: start_tok
;
351 apply_arg_if_exists(in_tok
, arg_tok
, on_tok
,
352 in_tok_first
, in_tok_last
);
358 static void process_trailers_lists(struct trailer_item
**in_tok_first
,
359 struct trailer_item
**in_tok_last
,
360 struct trailer_item
**arg_tok_first
)
362 struct trailer_item
*arg_tok
;
363 struct trailer_item
*next_arg
;
368 for (arg_tok
= *arg_tok_first
; arg_tok
; arg_tok
= next_arg
) {
371 next_arg
= arg_tok
->next
;
372 remove_from_list(arg_tok
, arg_tok_first
, NULL
);
374 applied
= find_same_and_apply_arg(in_tok_first
,
379 apply_arg_if_missing(in_tok_first
,
385 static int set_where(struct conf_info
*item
, const char *value
)
387 if (!strcasecmp("after", value
))
388 item
->where
= WHERE_AFTER
;
389 else if (!strcasecmp("before", value
))
390 item
->where
= WHERE_BEFORE
;
391 else if (!strcasecmp("end", value
))
392 item
->where
= WHERE_END
;
393 else if (!strcasecmp("start", value
))
394 item
->where
= WHERE_START
;
400 static int set_if_exists(struct conf_info
*item
, const char *value
)
402 if (!strcasecmp("addIfDifferent", value
))
403 item
->if_exists
= EXISTS_ADD_IF_DIFFERENT
;
404 else if (!strcasecmp("addIfDifferentNeighbor", value
))
405 item
->if_exists
= EXISTS_ADD_IF_DIFFERENT_NEIGHBOR
;
406 else if (!strcasecmp("add", value
))
407 item
->if_exists
= EXISTS_ADD
;
408 else if (!strcasecmp("replace", value
))
409 item
->if_exists
= EXISTS_REPLACE
;
410 else if (!strcasecmp("doNothing", value
))
411 item
->if_exists
= EXISTS_DO_NOTHING
;
417 static int set_if_missing(struct conf_info
*item
, const char *value
)
419 if (!strcasecmp("doNothing", value
))
420 item
->if_missing
= MISSING_DO_NOTHING
;
421 else if (!strcasecmp("add", value
))
422 item
->if_missing
= MISSING_ADD
;
428 static void duplicate_conf(struct conf_info
*dst
, struct conf_info
*src
)
431 dst
->name
= xstrdup_or_null(src
->name
);
432 dst
->key
= xstrdup_or_null(src
->key
);
433 dst
->command
= xstrdup_or_null(src
->command
);
436 static struct trailer_item
*get_conf_item(const char *name
)
438 struct trailer_item
*item
;
439 struct trailer_item
*previous
;
441 /* Look up item with same name */
442 for (previous
= NULL
, item
= first_conf_item
;
444 previous
= item
, item
= item
->next
) {
445 if (!strcasecmp(item
->conf
.name
, name
))
449 /* Item does not already exists, create it */
450 item
= xcalloc(sizeof(struct trailer_item
), 1);
451 duplicate_conf(&item
->conf
, &default_conf_info
);
452 item
->conf
.name
= xstrdup(name
);
455 first_conf_item
= item
;
457 previous
->next
= item
;
458 item
->previous
= previous
;
464 enum trailer_info_type
{ TRAILER_KEY
, TRAILER_COMMAND
, TRAILER_WHERE
,
465 TRAILER_IF_EXISTS
, TRAILER_IF_MISSING
};
469 enum trailer_info_type type
;
470 } trailer_config_items
[] = {
471 { "key", TRAILER_KEY
},
472 { "command", TRAILER_COMMAND
},
473 { "where", TRAILER_WHERE
},
474 { "ifexists", TRAILER_IF_EXISTS
},
475 { "ifmissing", TRAILER_IF_MISSING
}
478 static int git_trailer_default_config(const char *conf_key
, const char *value
, void *cb
)
480 const char *trailer_item
, *variable_name
;
482 if (!skip_prefix(conf_key
, "trailer.", &trailer_item
))
485 variable_name
= strrchr(trailer_item
, '.');
486 if (!variable_name
) {
487 if (!strcmp(trailer_item
, "where")) {
488 if (set_where(&default_conf_info
, value
) < 0)
489 warning(_("unknown value '%s' for key '%s'"),
491 } else if (!strcmp(trailer_item
, "ifexists")) {
492 if (set_if_exists(&default_conf_info
, value
) < 0)
493 warning(_("unknown value '%s' for key '%s'"),
495 } else if (!strcmp(trailer_item
, "ifmissing")) {
496 if (set_if_missing(&default_conf_info
, value
) < 0)
497 warning(_("unknown value '%s' for key '%s'"),
499 } else if (!strcmp(trailer_item
, "separators")) {
500 separators
= xstrdup(value
);
506 static int git_trailer_config(const char *conf_key
, const char *value
, void *cb
)
508 const char *trailer_item
, *variable_name
;
509 struct trailer_item
*item
;
510 struct conf_info
*conf
;
512 enum trailer_info_type type
;
515 if (!skip_prefix(conf_key
, "trailer.", &trailer_item
))
518 variable_name
= strrchr(trailer_item
, '.');
523 for (i
= 0; i
< ARRAY_SIZE(trailer_config_items
); i
++) {
524 if (strcmp(trailer_config_items
[i
].name
, variable_name
))
526 name
= xstrndup(trailer_item
, variable_name
- trailer_item
- 1);
527 type
= trailer_config_items
[i
].type
;
534 item
= get_conf_item(name
);
541 warning(_("more than one %s"), conf_key
);
542 conf
->key
= xstrdup(value
);
544 case TRAILER_COMMAND
:
546 warning(_("more than one %s"), conf_key
);
547 conf
->command
= xstrdup(value
);
550 if (set_where(conf
, value
))
551 warning(_("unknown value '%s' for key '%s'"), value
, conf_key
);
553 case TRAILER_IF_EXISTS
:
554 if (set_if_exists(conf
, value
))
555 warning(_("unknown value '%s' for key '%s'"), value
, conf_key
);
557 case TRAILER_IF_MISSING
:
558 if (set_if_missing(conf
, value
))
559 warning(_("unknown value '%s' for key '%s'"), value
, conf_key
);
562 die("BUG: trailer.c: unhandled type %d", type
);
567 static int parse_trailer(struct strbuf
*tok
, struct strbuf
*val
, const char *trailer
)
570 struct strbuf seps
= STRBUF_INIT
;
571 strbuf_addstr(&seps
, separators
);
572 strbuf_addch(&seps
, '=');
573 len
= strcspn(trailer
, seps
.buf
);
574 strbuf_release(&seps
);
576 int l
= strlen(trailer
);
577 while (l
> 0 && isspace(trailer
[l
- 1]))
579 return error(_("empty trailer token in trailer '%.*s'"), l
, trailer
);
581 if (len
< strlen(trailer
)) {
582 strbuf_add(tok
, trailer
, len
);
584 strbuf_addstr(val
, trailer
+ len
+ 1);
587 strbuf_addstr(tok
, trailer
);
593 static const char *token_from_item(struct trailer_item
*item
, char *tok
)
596 return item
->conf
.key
;
599 return item
->conf
.name
;
602 static struct trailer_item
*new_trailer_item(struct trailer_item
*conf_item
,
603 char *tok
, char *val
)
605 struct trailer_item
*new = xcalloc(sizeof(*new), 1);
606 new->value
= val
? val
: xstrdup("");
609 duplicate_conf(&new->conf
, &conf_item
->conf
);
610 new->token
= xstrdup(token_from_item(conf_item
, tok
));
613 duplicate_conf(&new->conf
, &default_conf_info
);
620 static int token_matches_item(const char *tok
, struct trailer_item
*item
, int tok_len
)
622 if (!strncasecmp(tok
, item
->conf
.name
, tok_len
))
624 return item
->conf
.key
? !strncasecmp(tok
, item
->conf
.key
, tok_len
) : 0;
627 static struct trailer_item
*create_trailer_item(const char *string
)
629 struct strbuf tok
= STRBUF_INIT
;
630 struct strbuf val
= STRBUF_INIT
;
631 struct trailer_item
*item
;
634 if (parse_trailer(&tok
, &val
, string
))
637 tok_len
= token_len_without_separator(tok
.buf
, tok
.len
);
639 /* Lookup if the token matches something in the config */
640 for (item
= first_conf_item
; item
; item
= item
->next
) {
641 if (token_matches_item(tok
.buf
, item
, tok_len
))
642 return new_trailer_item(item
,
643 strbuf_detach(&tok
, NULL
),
644 strbuf_detach(&val
, NULL
));
647 return new_trailer_item(NULL
,
648 strbuf_detach(&tok
, NULL
),
649 strbuf_detach(&val
, NULL
));
652 static void add_trailer_item(struct trailer_item
**first
,
653 struct trailer_item
**last
,
654 struct trailer_item
*new)
663 new->previous
= *last
;
668 static struct trailer_item
*process_command_line_args(struct string_list
*trailers
)
670 struct trailer_item
*arg_tok_first
= NULL
;
671 struct trailer_item
*arg_tok_last
= NULL
;
672 struct string_list_item
*tr
;
673 struct trailer_item
*item
;
675 /* Add a trailer item for each configured trailer with a command */
676 for (item
= first_conf_item
; item
; item
= item
->next
) {
677 if (item
->conf
.command
) {
678 struct trailer_item
*new = new_trailer_item(item
, NULL
, NULL
);
679 add_trailer_item(&arg_tok_first
, &arg_tok_last
, new);
683 /* Add a trailer item for each trailer on the command line */
684 for_each_string_list_item(tr
, trailers
) {
685 struct trailer_item
*new = create_trailer_item(tr
->string
);
686 add_trailer_item(&arg_tok_first
, &arg_tok_last
, new);
689 return arg_tok_first
;
692 static struct strbuf
**read_input_file(const char *file
)
694 struct strbuf
**lines
;
695 struct strbuf sb
= STRBUF_INIT
;
698 if (strbuf_read_file(&sb
, file
, 0) < 0)
699 die_errno(_("could not read input file '%s'"), file
);
701 if (strbuf_read(&sb
, fileno(stdin
), 0) < 0)
702 die_errno(_("could not read from stdin"));
705 lines
= strbuf_split(&sb
, '\n');
713 * Return the (0 based) index of the start of the patch or the line
714 * count if there is no patch in the message.
716 static int find_patch_start(struct strbuf
**lines
, int count
)
720 /* Get the start of the patch part if any */
721 for (i
= 0; i
< count
; i
++) {
722 if (starts_with(lines
[i
]->buf
, "---"))
730 * Return the (0 based) index of the first trailer line or count if
731 * there are no trailers. Trailers are searched only in the lines from
732 * index (count - 1) down to index 0.
734 static int find_trailer_start(struct strbuf
**lines
, int count
)
736 int start
, end_of_title
, only_spaces
= 1;
738 /* The first paragraph is the title and cannot be trailers */
739 for (start
= 0; start
< count
; start
++) {
740 if (lines
[start
]->buf
[0] == comment_line_char
)
742 if (contains_only_spaces(lines
[start
]->buf
))
745 end_of_title
= start
;
748 * Get the start of the trailers by looking starting from the end
749 * for a line with only spaces before lines with one separator.
751 for (start
= count
- 1; start
>= end_of_title
; start
--) {
752 if (lines
[start
]->buf
[0] == comment_line_char
)
754 if (contains_only_spaces(lines
[start
]->buf
)) {
759 if (strcspn(lines
[start
]->buf
, separators
) < lines
[start
]->len
) {
767 return only_spaces
? count
: 0;
770 /* Get the index of the end of the trailers */
771 static int find_trailer_end(struct strbuf
**lines
, int patch_start
)
773 struct strbuf sb
= STRBUF_INIT
;
776 for (i
= 0; i
< patch_start
; i
++)
777 strbuf_addbuf(&sb
, lines
[i
]);
778 ignore_bytes
= ignore_non_trailer(&sb
);
780 for (i
= patch_start
- 1; i
>= 0 && ignore_bytes
> 0; i
--)
781 ignore_bytes
-= lines
[i
]->len
;
786 static int has_blank_line_before(struct strbuf
**lines
, int start
)
788 for (;start
>= 0; start
--) {
789 if (lines
[start
]->buf
[0] == comment_line_char
)
791 return contains_only_spaces(lines
[start
]->buf
);
796 static void print_lines(FILE *outfile
, struct strbuf
**lines
, int start
, int end
)
799 for (i
= start
; lines
[i
] && i
< end
; i
++)
800 fprintf(outfile
, "%s", lines
[i
]->buf
);
803 static int process_input_file(FILE *outfile
,
804 struct strbuf
**lines
,
805 struct trailer_item
**in_tok_first
,
806 struct trailer_item
**in_tok_last
)
809 int patch_start
, trailer_start
, trailer_end
, i
;
811 /* Get the line count */
815 patch_start
= find_patch_start(lines
, count
);
816 trailer_end
= find_trailer_end(lines
, patch_start
);
817 trailer_start
= find_trailer_start(lines
, trailer_end
);
819 /* Print lines before the trailers as is */
820 print_lines(outfile
, lines
, 0, trailer_start
);
822 if (!has_blank_line_before(lines
, trailer_start
- 1))
823 fprintf(outfile
, "\n");
825 /* Parse trailer lines */
826 for (i
= trailer_start
; i
< trailer_end
; i
++) {
827 if (lines
[i
]->buf
[0] != comment_line_char
) {
828 struct trailer_item
*new = create_trailer_item(lines
[i
]->buf
);
829 add_trailer_item(in_tok_first
, in_tok_last
, new);
836 static void free_all(struct trailer_item
**first
)
839 struct trailer_item
*item
= remove_first(first
);
840 free_trailer_item(item
);
844 static struct tempfile trailers_tempfile
;
846 static FILE *create_in_place_tempfile(const char *file
)
849 struct strbuf
template = STRBUF_INIT
;
854 die_errno(_("could not stat %s"), file
);
855 if (!S_ISREG(st
.st_mode
))
856 die(_("file %s is not a regular file"), file
);
857 if (!(st
.st_mode
& S_IWUSR
))
858 die(_("file %s is not writable by user"), file
);
860 /* Create temporary file in the same directory as the original */
861 tail
= strrchr(file
, '/');
863 strbuf_add(&template, file
, tail
- file
+ 1);
864 strbuf_addstr(&template, "git-interpret-trailers-XXXXXX");
866 xmks_tempfile_m(&trailers_tempfile
, template.buf
, st
.st_mode
);
867 strbuf_release(&template);
868 outfile
= fdopen_tempfile(&trailers_tempfile
, "w");
870 die_errno(_("could not open temporary file"));
875 void process_trailers(const char *file
, int in_place
, int trim_empty
, struct string_list
*trailers
)
877 struct trailer_item
*in_tok_first
= NULL
;
878 struct trailer_item
*in_tok_last
= NULL
;
879 struct trailer_item
*arg_tok_first
;
880 struct strbuf
**lines
;
882 FILE *outfile
= stdout
;
884 /* Default config must be setup first */
885 git_config(git_trailer_default_config
, NULL
);
886 git_config(git_trailer_config
, NULL
);
888 lines
= read_input_file(file
);
891 outfile
= create_in_place_tempfile(file
);
893 /* Print the lines before the trailers */
894 trailer_end
= process_input_file(outfile
, lines
, &in_tok_first
, &in_tok_last
);
896 arg_tok_first
= process_command_line_args(trailers
);
898 process_trailers_lists(&in_tok_first
, &in_tok_last
, &arg_tok_first
);
900 print_all(outfile
, in_tok_first
, trim_empty
);
902 free_all(&in_tok_first
);
904 /* Print the lines after the trailers as is */
905 print_lines(outfile
, lines
, trailer_end
, INT_MAX
);
908 if (rename_tempfile(&trailers_tempfile
, file
))
909 die_errno(_("could not rename temporary file to %s"), file
);
911 strbuf_list_free(lines
);