Skip to content

Commit 2013d85

Browse files
chriscoolgitster
authored andcommitted
trailer: parse trailers from file or stdin
Read trailers from a file or from stdin, parse the trailers and then put the result into a doubly linked list. Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f0a90b4 commit 2013d85

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

trailer.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b)
6969
return same_token(a, b) && same_value(a, b);
7070
}
7171

72+
static inline int contains_only_spaces(const char *str)
73+
{
74+
const char *s = str;
75+
while (*s && isspace(*s))
76+
s++;
77+
return !*s;
78+
}
79+
7280
static void free_trailer_item(struct trailer_item *item)
7381
{
7482
free(item->conf.name);
@@ -574,3 +582,118 @@ static struct trailer_item *process_command_line_args(struct string_list *traile
574582

575583
return arg_tok_first;
576584
}
585+
586+
static struct strbuf **read_input_file(const char *file)
587+
{
588+
struct strbuf **lines;
589+
struct strbuf sb = STRBUF_INIT;
590+
591+
if (file) {
592+
if (strbuf_read_file(&sb, file, 0) < 0)
593+
die_errno(_("could not read input file '%s'"), file);
594+
} else {
595+
if (strbuf_read(&sb, fileno(stdin), 0) < 0)
596+
die_errno(_("could not read from stdin"));
597+
}
598+
599+
lines = strbuf_split(&sb, '\n');
600+
601+
strbuf_release(&sb);
602+
603+
return lines;
604+
}
605+
606+
/*
607+
* Return the (0 based) index of the start of the patch or the line
608+
* count if there is no patch in the message.
609+
*/
610+
static int find_patch_start(struct strbuf **lines, int count)
611+
{
612+
int i;
613+
614+
/* Get the start of the patch part if any */
615+
for (i = 0; i < count; i++) {
616+
if (starts_with(lines[i]->buf, "---"))
617+
return i;
618+
}
619+
620+
return count;
621+
}
622+
623+
/*
624+
* Return the (0 based) index of the first trailer line or count if
625+
* there are no trailers. Trailers are searched only in the lines from
626+
* index (count - 1) down to index 0.
627+
*/
628+
static int find_trailer_start(struct strbuf **lines, int count)
629+
{
630+
int start, only_spaces = 1;
631+
632+
/*
633+
* Get the start of the trailers by looking starting from the end
634+
* for a line with only spaces before lines with one separator.
635+
*/
636+
for (start = count - 1; start >= 0; start--) {
637+
if (lines[start]->buf[0] == comment_line_char)
638+
continue;
639+
if (contains_only_spaces(lines[start]->buf)) {
640+
if (only_spaces)
641+
continue;
642+
return start + 1;
643+
}
644+
if (strcspn(lines[start]->buf, separators) < lines[start]->len) {
645+
if (only_spaces)
646+
only_spaces = 0;
647+
continue;
648+
}
649+
return count;
650+
}
651+
652+
return only_spaces ? count : 0;
653+
}
654+
655+
static int has_blank_line_before(struct strbuf **lines, int start)
656+
{
657+
for (;start >= 0; start--) {
658+
if (lines[start]->buf[0] == comment_line_char)
659+
continue;
660+
return contains_only_spaces(lines[start]->buf);
661+
}
662+
return 0;
663+
}
664+
665+
static void print_lines(struct strbuf **lines, int start, int end)
666+
{
667+
int i;
668+
for (i = start; lines[i] && i < end; i++)
669+
printf("%s", lines[i]->buf);
670+
}
671+
672+
static int process_input_file(struct strbuf **lines,
673+
struct trailer_item **in_tok_first,
674+
struct trailer_item **in_tok_last)
675+
{
676+
int count = 0;
677+
int patch_start, trailer_start, i;
678+
679+
/* Get the line count */
680+
while (lines[count])
681+
count++;
682+
683+
patch_start = find_patch_start(lines, count);
684+
trailer_start = find_trailer_start(lines, patch_start);
685+
686+
/* Print lines before the trailers as is */
687+
print_lines(lines, 0, trailer_start);
688+
689+
if (!has_blank_line_before(lines, trailer_start - 1))
690+
printf("\n");
691+
692+
/* Parse trailer lines */
693+
for (i = trailer_start; i < patch_start; i++) {
694+
struct trailer_item *new = create_trailer_item(lines[i]->buf);
695+
add_trailer_item(in_tok_first, in_tok_last, new);
696+
}
697+
698+
return patch_start;
699+
}

0 commit comments

Comments
 (0)