trailer: process command line trailer arguments
Parse the trailer command line arguments and put the result into an arg_tok doubly linked list. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Christian Couder committed
Oct 13, 2014 at 20:16 UTC
f0a90b4edff44af9a3cb3c30ff8e656a59581a2f
1 file changed
+112
trailer.c
+112
@@ -1,4 +1,5 @@
1
#include "cache.h"
2
+#include "string-list.h"
3
/*
4
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
5
*/
@@ -462,3 +463,114 @@ static int git_trailer_config(const char *conf_key, const char *value, void *cb)
463
}
464
return 0;
465
}
466
+
467
+static int parse_trailer(struct strbuf *tok, struct strbuf *val, const char *trailer)
468
+{
469
+ size_t len;
470
+ struct strbuf seps = STRBUF_INIT;
471
+ strbuf_addstr(&seps, separators);
472
+ strbuf_addch(&seps, '=');
473
+ len = strcspn(trailer, seps.buf);
474
+ strbuf_release(&seps);
475
+ if (len == 0)
476
+ return error(_("empty trailer token in trailer '%s'"), trailer);
477
+ if (len < strlen(trailer)) {
478
+ strbuf_add(tok, trailer, len);
479
+ strbuf_trim(tok);
480
+ strbuf_addstr(val, trailer + len + 1);
481
+ strbuf_trim(val);
482
+ } else {
483
+ strbuf_addstr(tok, trailer);
484
+ strbuf_trim(tok);
485
+ }
486
+ return 0;
487
+}
488
+
489
+static const char *token_from_item(struct trailer_item *item, char *tok)
490
+{
491
+ if (item->conf.key)
492
+ return item->conf.key;
493
+ if (tok)
494
+ return tok;
495
+ return item->conf.name;
496
+}
497
+
498
+static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
499
+ char *tok, char *val)
500
+{
501
+ struct trailer_item *new = xcalloc(sizeof(*new), 1);
502
+ new->value = val;
503
+
504
+ if (conf_item) {
505
+ duplicate_conf(&new->conf, &conf_item->conf);
506
+ new->token = xstrdup(token_from_item(conf_item, tok));
507
+ free(tok);
508
+ } else {
509
+ duplicate_conf(&new->conf, &default_conf_info);
510
+ new->token = tok;
511
+ }
512
+
513
+ return new;
514
+}
515
+
516
+static int token_matches_item(const char *tok, struct trailer_item *item, int tok_len)
517
+{
518
+ if (!strncasecmp(tok, item->conf.name, tok_len))
519
+ return 1;
520
+ return item->conf.key ? !strncasecmp(tok, item->conf.key, tok_len) : 0;
521
+}
522
+
523
+static struct trailer_item *create_trailer_item(const char *string)
524
+{
525
+ struct strbuf tok = STRBUF_INIT;
526
+ struct strbuf val = STRBUF_INIT;
527
+ struct trailer_item *item;
528
+ int tok_len;
529
+
530
+ if (parse_trailer(&tok, &val, string))
531
+ return NULL;
532
+
533
+ tok_len = token_len_without_separator(tok.buf, tok.len);
534
+
535
+ /* Lookup if the token matches something in the config */
536
+ for (item = first_conf_item; item; item = item->next) {
537
+ if (token_matches_item(tok.buf, item, tok_len))
538
+ return new_trailer_item(item,
539
+ strbuf_detach(&tok, NULL),
540
+ strbuf_detach(&val, NULL));
541
+ }
542
+
543
+ return new_trailer_item(NULL,
544
+ strbuf_detach(&tok, NULL),
545
+ strbuf_detach(&val, NULL));
546
+}
547
+
548
+static void add_trailer_item(struct trailer_item **first,
549
+ struct trailer_item **last,
550
+ struct trailer_item *new)
551
+{
552
+ if (!new)
553
+ return;
554
+ if (!*last) {
555
+ *first = new;
556
+ *last = new;
557
+ } else {
558
+ (*last)->next = new;
559
+ new->previous = *last;
560
+ *last = new;
561
+ }
562
+}
563
+
564
+static struct trailer_item *process_command_line_args(struct string_list *trailers)
565
+{
566
+ struct trailer_item *arg_tok_first = NULL;
567
+ struct trailer_item *arg_tok_last = NULL;
568
+ struct string_list_item *tr;
569
+
570
+ for_each_string_list_item(tr, trailers) {
571
+ struct trailer_item *new = create_trailer_item(tr->string);
572
+ add_trailer_item(&arg_tok_first, &arg_tok_last, new);
573
+ }
574
+
575
+ return arg_tok_first;
576
+}