Skip to content

Commit fdbf451

Browse files
jonathantanmygitster
authored andcommitted
trailer: clarify failure modes in parse_trailer
The parse_trailer function has a few modes of operation, all depending on whether the separator is present in its input, and if yes, the separator's position. Some of these modes are failure modes, and these failure modes are handled differently depending on whether the trailer line was sourced from a file or from a command-line argument. Extract a function to find the separator, allowing the invokers of parse_trailer to determine how to handle the failure modes instead of making parse_trailer do it. In this function, also take in the list of separators, so that we can distinguish between command line arguments (which allow '=' as separator) and file input (which does not allow '=' as separator). Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cc71b0d commit fdbf451

File tree

1 file changed

+53
-22
lines changed

1 file changed

+53
-22
lines changed

trailer.c

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -543,29 +543,37 @@ static int token_matches_item(const char *tok, struct arg_item *item, int tok_le
543543
return item->conf.key ? !strncasecmp(tok, item->conf.key, tok_len) : 0;
544544
}
545545

546-
static int parse_trailer(struct strbuf *tok, struct strbuf *val,
547-
const struct conf_info **conf, const char *trailer)
546+
/*
547+
* Return the location of the first separator in line, or -1 if there is no
548+
* separator.
549+
*/
550+
static int find_separator(const char *line, const char *separators)
551+
{
552+
int loc = strcspn(line, separators);
553+
if (!line[loc])
554+
return -1;
555+
return loc;
556+
}
557+
558+
/*
559+
* Obtain the token, value, and conf from the given trailer.
560+
*
561+
* separator_pos must not be 0, since the token cannot be an empty string.
562+
*
563+
* If separator_pos is -1, interpret the whole trailer as a token.
564+
*/
565+
static void parse_trailer(struct strbuf *tok, struct strbuf *val,
566+
const struct conf_info **conf, const char *trailer,
567+
int separator_pos)
548568
{
549-
size_t len;
550-
struct strbuf seps = STRBUF_INIT;
551569
struct arg_item *item;
552570
int tok_len;
553571
struct list_head *pos;
554572

555-
strbuf_addstr(&seps, separators);
556-
strbuf_addch(&seps, '=');
557-
len = strcspn(trailer, seps.buf);
558-
strbuf_release(&seps);
559-
if (len == 0) {
560-
int l = strlen(trailer);
561-
while (l > 0 && isspace(trailer[l - 1]))
562-
l--;
563-
return error(_("empty trailer token in trailer '%.*s'"), l, trailer);
564-
}
565-
if (len < strlen(trailer)) {
566-
strbuf_add(tok, trailer, len);
573+
if (separator_pos != -1) {
574+
strbuf_add(tok, trailer, separator_pos);
567575
strbuf_trim(tok);
568-
strbuf_addstr(val, trailer + len + 1);
576+
strbuf_addstr(val, trailer + separator_pos + 1);
569577
strbuf_trim(val);
570578
} else {
571579
strbuf_addstr(tok, trailer);
@@ -587,8 +595,6 @@ static int parse_trailer(struct strbuf *tok, struct strbuf *val,
587595
break;
588596
}
589597
}
590-
591-
return 0;
592598
}
593599

594600
static void add_trailer_item(struct list_head *head, char *tok, char *val)
@@ -619,6 +625,12 @@ static void process_command_line_args(struct list_head *arg_head,
619625
const struct conf_info *conf;
620626
struct list_head *pos;
621627

628+
/*
629+
* In command-line arguments, '=' is accepted (in addition to the
630+
* separators that are defined).
631+
*/
632+
char *cl_separators = xstrfmt("=%s", separators);
633+
622634
/* Add an arg item for each configured trailer with a command */
623635
list_for_each(pos, &conf_head) {
624636
item = list_entry(pos, struct arg_item, list);
@@ -631,12 +643,25 @@ static void process_command_line_args(struct list_head *arg_head,
631643

632644
/* Add an arg item for each trailer on the command line */
633645
for_each_string_list_item(tr, trailers) {
634-
if (!parse_trailer(&tok, &val, &conf, tr->string))
646+
int separator_pos = find_separator(tr->string, cl_separators);
647+
if (separator_pos == 0) {
648+
struct strbuf sb = STRBUF_INIT;
649+
strbuf_addstr(&sb, tr->string);
650+
strbuf_trim(&sb);
651+
error(_("empty trailer token in trailer '%.*s'"),
652+
(int) sb.len, sb.buf);
653+
strbuf_release(&sb);
654+
} else {
655+
parse_trailer(&tok, &val, &conf, tr->string,
656+
separator_pos);
635657
add_arg_item(arg_head,
636658
strbuf_detach(&tok, NULL),
637659
strbuf_detach(&val, NULL),
638660
conf);
661+
}
639662
}
663+
664+
free(cl_separators);
640665
}
641666

642667
static struct strbuf **read_input_file(const char *file)
@@ -775,11 +800,17 @@ static int process_input_file(FILE *outfile,
775800

776801
/* Parse trailer lines */
777802
for (i = trailer_start; i < trailer_end; i++) {
778-
if (lines[i]->buf[0] != comment_line_char &&
779-
!parse_trailer(&tok, &val, NULL, lines[i]->buf))
803+
int separator_pos;
804+
if (lines[i]->buf[0] == comment_line_char)
805+
continue;
806+
separator_pos = find_separator(lines[i]->buf, separators);
807+
if (separator_pos >= 1) {
808+
parse_trailer(&tok, &val, NULL, lines[i]->buf,
809+
separator_pos);
780810
add_trailer_item(head,
781811
strbuf_detach(&tok, NULL),
782812
strbuf_detach(&val, NULL));
813+
}
783814
}
784815

785816
return trailer_end;

0 commit comments

Comments
 (0)