trailer: read and process config information

Read the configuration to get trailer information, and then process it and store 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@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Christian Couder committed Oct 13, 2014 at 20:16 UTC 46a0613f00f2cf6a61d04fa49131fcbe3afaad07
1 file changed +185
trailer.c
+185
@@ -277,3 +277,188 @@ static void process_trailers_lists(struct trailer_item **in_tok_first,
277 arg_tok);
278 }
279 }
280 +
281 +static int set_where(struct conf_info *item, const char *value)
282 +{
283 + if (!strcasecmp("after", value))
284 + item->where = WHERE_AFTER;
285 + else if (!strcasecmp("before", value))
286 + item->where = WHERE_BEFORE;
287 + else if (!strcasecmp("end", value))
288 + item->where = WHERE_END;
289 + else if (!strcasecmp("start", value))
290 + item->where = WHERE_START;
291 + else
292 + return -1;
293 + return 0;
294 +}
295 +
296 +static int set_if_exists(struct conf_info *item, const char *value)
297 +{
298 + if (!strcasecmp("addIfDifferent", value))
299 + item->if_exists = EXISTS_ADD_IF_DIFFERENT;
300 + else if (!strcasecmp("addIfDifferentNeighbor", value))
301 + item->if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
302 + else if (!strcasecmp("add", value))
303 + item->if_exists = EXISTS_ADD;
304 + else if (!strcasecmp("replace", value))
305 + item->if_exists = EXISTS_REPLACE;
306 + else if (!strcasecmp("doNothing", value))
307 + item->if_exists = EXISTS_DO_NOTHING;
308 + else
309 + return -1;
310 + return 0;
311 +}
312 +
313 +static int set_if_missing(struct conf_info *item, const char *value)
314 +{
315 + if (!strcasecmp("doNothing", value))
316 + item->if_missing = MISSING_DO_NOTHING;
317 + else if (!strcasecmp("add", value))
318 + item->if_missing = MISSING_ADD;
319 + else
320 + return -1;
321 + return 0;
322 +}
323 +
324 +static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
325 +{
326 + *dst = *src;
327 + if (src->name)
328 + dst->name = xstrdup(src->name);
329 + if (src->key)
330 + dst->key = xstrdup(src->key);
331 + if (src->command)
332 + dst->command = xstrdup(src->command);
333 +}
334 +
335 +static struct trailer_item *get_conf_item(const char *name)
336 +{
337 + struct trailer_item *item;
338 + struct trailer_item *previous;
339 +
340 + /* Look up item with same name */
341 + for (previous = NULL, item = first_conf_item;
342 + item;
343 + previous = item, item = item->next) {
344 + if (!strcasecmp(item->conf.name, name))
345 + return item;
346 + }
347 +
348 + /* Item does not already exists, create it */
349 + item = xcalloc(sizeof(struct trailer_item), 1);
350 + duplicate_conf(&item->conf, &default_conf_info);
351 + item->conf.name = xstrdup(name);
352 +
353 + if (!previous)
354 + first_conf_item = item;
355 + else {
356 + previous->next = item;
357 + item->previous = previous;
358 + }
359 +
360 + return item;
361 +}
362 +
363 +enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE,
364 + TRAILER_IF_EXISTS, TRAILER_IF_MISSING };
365 +
366 +static struct {
367 + const char *name;
368 + enum trailer_info_type type;
369 +} trailer_config_items[] = {
370 + { "key", TRAILER_KEY },
371 + { "command", TRAILER_COMMAND },
372 + { "where", TRAILER_WHERE },
373 + { "ifexists", TRAILER_IF_EXISTS },
374 + { "ifmissing", TRAILER_IF_MISSING }
375 +};
376 +
377 +static int git_trailer_default_config(const char *conf_key, const char *value, void *cb)
378 +{
379 + const char *trailer_item, *variable_name;
380 +
381 + if (!skip_prefix(conf_key, "trailer.", &trailer_item))
382 + return 0;
383 +
384 + variable_name = strrchr(trailer_item, '.');
385 + if (!variable_name) {
386 + if (!strcmp(trailer_item, "where")) {
387 + if (set_where(&default_conf_info, value) < 0)
388 + warning(_("unknown value '%s' for key '%s'"),
389 + value, conf_key);
390 + } else if (!strcmp(trailer_item, "ifexists")) {
391 + if (set_if_exists(&default_conf_info, value) < 0)
392 + warning(_("unknown value '%s' for key '%s'"),
393 + value, conf_key);
394 + } else if (!strcmp(trailer_item, "ifmissing")) {
395 + if (set_if_missing(&default_conf_info, value) < 0)
396 + warning(_("unknown value '%s' for key '%s'"),
397 + value, conf_key);
398 + } else if (!strcmp(trailer_item, "separators")) {
399 + separators = xstrdup(value);
400 + }
401 + }
402 + return 0;
403 +}
404 +
405 +static int git_trailer_config(const char *conf_key, const char *value, void *cb)
406 +{
407 + const char *trailer_item, *variable_name;
408 + struct trailer_item *item;
409 + struct conf_info *conf;
410 + char *name = NULL;
411 + enum trailer_info_type type;
412 + int i;
413 +
414 + if (!skip_prefix(conf_key, "trailer.", &trailer_item))
415 + return 0;
416 +
417 + variable_name = strrchr(trailer_item, '.');
418 + if (!variable_name)
419 + return 0;
420 +
421 + variable_name++;
422 + for (i = 0; i < ARRAY_SIZE(trailer_config_items); i++) {
423 + if (strcmp(trailer_config_items[i].name, variable_name))
424 + continue;
425 + name = xstrndup(trailer_item, variable_name - trailer_item - 1);
426 + type = trailer_config_items[i].type;
427 + break;
428 + }
429 +
430 + if (!name)
431 + return 0;
432 +
433 + item = get_conf_item(name);
434 + conf = &item->conf;
435 + free(name);
436 +
437 + switch (type) {
438 + case TRAILER_KEY:
439 + if (conf->key)
440 + warning(_("more than one %s"), conf_key);
441 + conf->key = xstrdup(value);
442 + break;
443 + case TRAILER_COMMAND:
444 + if (conf->command)
445 + warning(_("more than one %s"), conf_key);
446 + conf->command = xstrdup(value);
447 + break;
448 + case TRAILER_WHERE:
449 + if (set_where(conf, value))
450 + warning(_("unknown value '%s' for key '%s'"), value, conf_key);
451 + break;
452 + case TRAILER_IF_EXISTS:
453 + if (set_if_exists(conf, value))
454 + warning(_("unknown value '%s' for key '%s'"), value, conf_key);
455 + break;
456 + case TRAILER_IF_MISSING:
457 + if (set_if_missing(conf, value))
458 + warning(_("unknown value '%s' for key '%s'"), value, conf_key);
459 + break;
460 + default:
461 + die("internal bug in trailer.c");
462 + }
463 + return 0;
464 +}