This patch implements reading the configuration to get trailer information, and then processing it and storing it in a doubly linked list. The config information is stored in the list whose first item is pointed to by: static struct trailer_item *first_conf_item; Signed-off-by: Christian Couder <chriscool@xxxxxxxxxxxxx> --- trailer.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/trailer.c b/trailer.c index d88de3f..e7d8244 100644 --- a/trailer.c +++ b/trailer.c @@ -25,6 +25,8 @@ struct trailer_item { struct conf_info *conf; }; +static struct trailer_item *first_conf_item; + static int same_token(struct trailer_item *a, struct trailer_item *b, int alnum_len) { return !strncasecmp(a->token, b->token, alnum_len); @@ -234,3 +236,130 @@ static void process_trailers_lists(struct trailer_item **infile_tok_first, apply_arg_if_missing(infile_tok_first, infile_tok_last, arg_tok); } } + +static int set_where(struct conf_info *item, const char *value) +{ + if (!strcasecmp("after", value)) { + item->where = WHERE_AFTER; + } else if (!strcasecmp("before", value)) { + item->where = WHERE_BEFORE; + } else + return 1; + return 0; +} + +static int set_if_exist(struct conf_info *item, const char *value) +{ + if (!strcasecmp("addIfDifferent", value)) { + item->if_exist = EXIST_ADD_IF_DIFFERENT; + } else if (!strcasecmp("addIfDifferentNeighbor", value)) { + item->if_exist = EXIST_ADD_IF_DIFFERENT_NEIGHBOR; + } else if (!strcasecmp("add", value)) { + item->if_exist = EXIST_ADD; + } else if (!strcasecmp("overwrite", value)) { + item->if_exist = EXIST_OVERWRITE; + } else if (!strcasecmp("doNothing", value)) { + item->if_exist = EXIST_DO_NOTHING; + } else + return 1; + return 0; +} + +static int set_if_missing(struct conf_info *item, const char *value) +{ + if (!strcasecmp("doNothing", value)) { + item->if_missing = MISSING_DO_NOTHING; + } else if (!strcasecmp("add", value)) { + item->if_missing = MISSING_ADD; + } else + return 1; + return 0; +} + +enum trailer_info_type { TRAILER_VALUE, TRAILER_COMMAND, TRAILER_WHERE, + TRAILER_IF_EXIST, TRAILER_IF_MISSING }; + +static int set_name_and_type(const char *conf_key, const char *suffix, + enum trailer_info_type type, + char **pname, enum trailer_info_type *ptype) +{ + int ret = ends_with(conf_key, suffix); + if (ret) { + *pname = xstrndup(conf_key, strlen(conf_key) - strlen(suffix)); + *ptype = type; + } + return ret; +} + +static struct trailer_item *get_conf_item(char *name) +{ + struct trailer_item *item; + struct trailer_item *previous; + + /* Look up item with same name */ + for (previous = NULL, item = first_conf_item; + item; + previous = item, item = item->next) + { + if (!strcasecmp(item->conf->name, name)) + return item; + } + + /* Item does not already exists, create it */ + item = xcalloc(sizeof(struct trailer_item), 1); + item->conf = xcalloc(sizeof(struct conf_info), 1); + item->conf->name = xstrdup(name); + + if (!previous) { + first_conf_item = item; + } else { + previous->next = item; + item->previous = previous; + } + + return item; +} + +static int git_trailer_config(const char *conf_key, const char *value, void *cb) +{ + if (starts_with(conf_key, "trailer.")) { + const char *orig_conf_key = conf_key; + struct trailer_item *item; + struct conf_info *conf; + char *name; + enum trailer_info_type type; + + conf_key += 8; + if (!set_name_and_type(conf_key, ".key", TRAILER_VALUE, &name, &type) && + !set_name_and_type(conf_key, ".command", TRAILER_COMMAND, &name, &type) && + !set_name_and_type(conf_key, ".where", TRAILER_WHERE, &name, &type) && + !set_name_and_type(conf_key, ".ifexist", TRAILER_IF_EXIST, &name, &type) && + !set_name_and_type(conf_key, ".ifmissing", TRAILER_IF_MISSING, &name, &type)) + return 0; + + item = get_conf_item(name); + conf = item->conf; + + if (type == TRAILER_VALUE) { + if (conf->key) + warning(_("more than one %s"), orig_conf_key); + conf->key = xstrdup(value); + } else if (type == TRAILER_COMMAND) { + if (conf->command) + warning(_("more than one %s"), orig_conf_key); + conf->command = xstrdup(value); + } else if (type == TRAILER_WHERE) { + if (set_where(conf, value)) + warning(_("unknown value '%s' for key '%s'"), value, orig_conf_key); + } else if (type == TRAILER_IF_EXIST) { + if (set_if_exist(conf, value)) + warning(_("unknown value '%s' for key '%s'"), value, orig_conf_key); + } else if (type == TRAILER_IF_MISSING) { + if (set_if_missing(conf, value)) + warning(_("unknown value '%s' for key '%s'"), value, orig_conf_key); + } else { + die("internal bug in trailer.c"); + } + } + return 0; +} -- 1.8.5.2.201.gacc5987 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html