@matheusbsbs / matheus-bagliano / commits / d64ec16c2a
Fork 0

git config: reorganize to use parseopt

This patch has benefited from comments by Johannes Schindelin and Junio C Hamano. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Felipe Contreras committed Feb 21, 2009 at 02:49 UTC d64ec16c2af4ddcf3985d11d5dc28a15db181de5
1 file changed +195 -154
builtin-config.c
+195 -154
@@ -1,9 +1,12 @@
1 #include "builtin.h"
2 #include "cache.h"
3 #include "color.h"
4 +#include "parse-options.h"
5
5 -static const char git_config_set_usage[] =
6 -"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty] | --edit | -e ]";
6 +static const char *const builtin_config_usage[] = {
7 + "git config [options]",
8 + NULL
9 +};
10
11 static char *key;
12 static regex_t *key_regexp;
@@ -18,6 +21,63 @@ static char key_delim = ' ';
21 static char term = '\n';
22 static enum { T_RAW, T_INT, T_BOOL, T_BOOL_OR_INT } type = T_RAW;
23
24 +static int use_global_config, use_system_config;
25 +static const char *given_config_file;
26 +static int actions;
27 +static const char *get_color_slot, *get_colorbool_slot;
28 +static int end_null;
29 +
30 +#define ACTION_GET (1<<0)
31 +#define ACTION_GET_ALL (1<<1)
32 +#define ACTION_GET_REGEXP (1<<2)
33 +#define ACTION_REPLACE_ALL (1<<3)
34 +#define ACTION_ADD (1<<4)
35 +#define ACTION_UNSET (1<<5)
36 +#define ACTION_UNSET_ALL (1<<6)
37 +#define ACTION_RENAME_SECTION (1<<7)
38 +#define ACTION_REMOVE_SECTION (1<<8)
39 +#define ACTION_LIST (1<<9)
40 +#define ACTION_EDIT (1<<10)
41 +#define ACTION_SET (1<<11)
42 +#define ACTION_SET_ALL (1<<12)
43 +#define ACTION_GET_COLOR (1<<13)
44 +#define ACTION_GET_COLORBOOL (1<<14)
45 +
46 +static struct option builtin_config_options[] = {
47 + OPT_GROUP("Config file location"),
48 + OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
49 + OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
50 + OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"),
51 + OPT_GROUP("Action"),
52 + OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
53 + OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
54 + OPT_BIT(0, "get-regexp", &actions, "get values for regexp: name-regex [value-regex]", ACTION_GET_REGEXP),
55 + OPT_BIT(0, "replace-all", &actions, "replace all matching variables: name [value [value_regex]", ACTION_REPLACE_ALL),
56 + OPT_BIT(0, "add", &actions, "adds a new variable: name value", ACTION_ADD),
57 + OPT_BIT(0, "unset", &actions, "removes a variable: name [value-regex]", ACTION_UNSET),
58 + OPT_BIT(0, "unset-all", &actions, "removes all matches: name [value-regex]", ACTION_UNSET_ALL),
59 + OPT_BIT(0, "rename-section", &actions, "rename section: old-name new-name", ACTION_RENAME_SECTION),
60 + OPT_BIT(0, "remove-section", &actions, "remove a section: name", ACTION_REMOVE_SECTION),
61 + OPT_BIT('l', "list", &actions, "list all", ACTION_LIST),
62 + OPT_BIT('e', "edit", &actions, "opens an editor", ACTION_EDIT),
63 + OPT_STRING(0, "get-color", &get_color_slot, "slot", "find the color configured: [default]"),
64 + OPT_STRING(0, "get-colorbool", &get_colorbool_slot, "slot", "find the color setting: [stdout-is-tty]"),
65 + OPT_GROUP("Type"),
66 + OPT_SET_INT(0, "bool", &type, "value is \"true\" or \"false\"", T_BOOL),
67 + OPT_SET_INT(0, "int", &type, "value is decimal number", T_INT),
68 + OPT_SET_INT(0, "bool-or-int", &type, NULL, T_BOOL_OR_INT),
69 + OPT_GROUP("Other"),
70 + OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"),
71 + OPT_END(),
72 +};
73 +
74 +static void check_argc(int argc, int min, int max) {
75 + if (argc >= min && argc <= max)
76 + return;
77 + error("wrong number of arguments");
78 + usage_with_options(builtin_config_usage, builtin_config_options);
79 +}
80 +
81 static int show_all_config(const char *key_, const char *value_, void *cb)
82 {
83 if (value_)
@@ -253,162 +313,143 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
313
314 config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
315
256 - while (1 < argc) {
257 - if (!strcmp(argv[1], "--int"))
258 - type = T_INT;
259 - else if (!strcmp(argv[1], "--bool"))
260 - type = T_BOOL;
261 - else if (!strcmp(argv[1], "--bool-or-int"))
262 - type = T_BOOL_OR_INT;
263 - else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) {
264 - if (argc != 2)
265 - usage(git_config_set_usage);
266 - if (git_config(show_all_config, NULL) < 0) {
267 - if (config_exclusive_filename)
268 - die("unable to read config file %s: %s",
269 - config_exclusive_filename, strerror(errno));
270 - else
271 - die("error processing config file(s)");
272 - }
273 - return 0;
274 - }
275 - else if (!strcmp(argv[1], "--global")) {
276 - char *home = getenv("HOME");
277 - if (home) {
278 - char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
279 - config_exclusive_filename = user_config;
280 - } else {
281 - die("$HOME not set");
282 - }
283 - }
284 - else if (!strcmp(argv[1], "--system"))
285 - config_exclusive_filename = git_etc_gitconfig();
286 - else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
287 - if (argc < 3)
288 - usage(git_config_set_usage);
289 - if (!is_absolute_path(argv[2]) && prefix)
290 - config_exclusive_filename = prefix_filename(prefix,
291 - strlen(prefix),
292 - argv[2]);
293 - else
294 - config_exclusive_filename = argv[2];
295 - argc--;
296 - argv++;
297 - }
298 - else if (!strcmp(argv[1], "--null") || !strcmp(argv[1], "-z")) {
299 - term = '\0';
300 - delim = '\n';
301 - key_delim = '\n';
302 - }
303 - else if (!strcmp(argv[1], "--rename-section")) {
304 - int ret;
305 - if (argc != 4)
306 - usage(git_config_set_usage);
307 - ret = git_config_rename_section(argv[2], argv[3]);
308 - if (ret < 0)
309 - return ret;
310 - if (ret == 0) {
311 - fprintf(stderr, "No such section!\n");
312 - return 1;
313 - }
314 - return 0;
315 - }
316 - else if (!strcmp(argv[1], "--remove-section")) {
317 - int ret;
318 - if (argc != 3)
319 - usage(git_config_set_usage);
320 - ret = git_config_rename_section(argv[2], NULL);
321 - if (ret < 0)
322 - return ret;
323 - if (ret == 0) {
324 - fprintf(stderr, "No such section!\n");
325 - return 1;
326 - }
327 - return 0;
328 - } else if (!strcmp(argv[1], "--get-color")) {
329 - if (argc > 4 || argc < 3)
330 - usage(git_config_set_usage);
331 - get_color_slot = argv[2];
332 - get_color(argv[3]);
333 - return 0;
334 - } else if (!strcmp(argv[1], "--get-colorbool")) {
335 - if (argc == 4)
336 - stdout_is_tty = git_config_bool("command line", argv[3]);
337 - else if (argc == 3)
338 - stdout_is_tty = isatty(1);
339 - else
340 - usage(git_config_set_usage);
341 - get_colorbool_slot = argv[2];
342 - return get_colorbool(argc != 3);
343 - } else if (!strcmp(argv[1], "--edit") || !strcmp(argv[1], "-e")) {
344 - if (argc != 2)
345 - usage(git_config_set_usage);
346 - git_config(git_default_config, NULL);
347 - launch_editor(config_exclusive_filename ?
348 - config_exclusive_filename : git_path("config"),
349 - NULL, NULL);
350 - return 0;
351 - } else
352 - break;
353 - argc--;
354 - argv++;
355 - }
356 -
357 - switch (argc) {
358 - case 2:
359 - return get_value(argv[1], NULL);
360 - case 3:
361 - if (!strcmp(argv[1], "--unset"))
362 - return git_config_set(argv[2], NULL);
363 - else if (!strcmp(argv[1], "--unset-all"))
364 - return git_config_set_multivar(argv[2], NULL, NULL, 1);
365 - else if (!strcmp(argv[1], "--get"))
366 - return get_value(argv[2], NULL);
367 - else if (!strcmp(argv[1], "--get-all")) {
368 - do_all = 1;
369 - return get_value(argv[2], NULL);
370 - } else if (!strcmp(argv[1], "--get-regexp")) {
371 - show_keys = 1;
372 - use_key_regexp = 1;
373 - do_all = 1;
374 - return get_value(argv[2], NULL);
316 + argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
317 + PARSE_OPT_STOP_AT_NON_OPTION);
318 +
319 + if (use_global_config) {
320 + char *home = getenv("HOME");
321 + if (home) {
322 + char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
323 + config_exclusive_filename = user_config;
324 } else {
376 - value = normalize_value(argv[1], argv[2]);
377 - return git_config_set(argv[1], value);
325 + die("$HOME not set");
326 }
379 - case 4:
380 - if (!strcmp(argv[1], "--unset"))
381 - return git_config_set_multivar(argv[2], NULL, argv[3], 0);
382 - else if (!strcmp(argv[1], "--unset-all"))
383 - return git_config_set_multivar(argv[2], NULL, argv[3], 1);
384 - else if (!strcmp(argv[1], "--get"))
385 - return get_value(argv[2], argv[3]);
386 - else if (!strcmp(argv[1], "--get-all")) {
387 - do_all = 1;
388 - return get_value(argv[2], argv[3]);
389 - } else if (!strcmp(argv[1], "--get-regexp")) {
390 - show_keys = 1;
391 - use_key_regexp = 1;
392 - do_all = 1;
393 - return get_value(argv[2], argv[3]);
394 - } else if (!strcmp(argv[1], "--add")) {
395 - value = normalize_value(argv[2], argv[3]);
396 - return git_config_set_multivar(argv[2], value, "^$", 0);
397 - } else if (!strcmp(argv[1], "--replace-all")) {
398 - value = normalize_value(argv[2], argv[3]);
399 - return git_config_set_multivar(argv[2], value, NULL, 1);
400 - } else {
401 - value = normalize_value(argv[1], argv[2]);
402 - return git_config_set_multivar(argv[1], value, argv[3], 0);
327 + }
328 + else if (use_system_config)
329 + config_exclusive_filename = git_etc_gitconfig();
330 + else if (given_config_file) {
331 + if (!is_absolute_path(given_config_file) && prefix)
332 + config_exclusive_filename = prefix_filename(prefix,
333 + strlen(prefix),
334 + argv[2]);
335 + else
336 + config_exclusive_filename = given_config_file;
337 + }
338 +
339 + if (end_null) {
340 + term = '\0';
341 + delim = '\n';
342 + key_delim = '\n';
343 + }
344 +
345 + if (get_color_slot)
346 + actions |= ACTION_GET_COLOR;
347 + if (get_colorbool_slot)
348 + actions |= ACTION_GET_COLORBOOL;
349 +
350 + if (HAS_MULTI_BITS(actions)) {
351 + error("only one action at a time.");
352 + usage_with_options(builtin_config_usage, builtin_config_options);
353 + }
354 + if (actions == 0)
355 + switch (argc) {
356 + case 1: actions = ACTION_GET; break;
357 + case 2: actions = ACTION_SET; break;
358 + case 3: actions = ACTION_SET_ALL; break;
359 + default:
360 + usage_with_options(builtin_config_usage, builtin_config_options);
361 }
404 - case 5:
405 - if (!strcmp(argv[1], "--replace-all")) {
406 - value = normalize_value(argv[2], argv[3]);
407 - return git_config_set_multivar(argv[2], value, argv[4], 1);
362 +
363 + if (actions == ACTION_LIST) {
364 + if (git_config(show_all_config, NULL) < 0) {
365 + if (config_exclusive_filename)
366 + die("unable to read config file %s: %s",
367 + config_exclusive_filename, strerror(errno));
368 + else
369 + die("error processing config file(s)");
370 }
409 - case 1:
410 - default:
411 - usage(git_config_set_usage);
371 }
372 + else if (actions == ACTION_EDIT) {
373 + git_config(git_default_config, NULL);
374 + launch_editor(config_exclusive_filename ?
375 + config_exclusive_filename : git_path("config"),
376 + NULL, NULL);
377 + }
378 + else if (actions == ACTION_SET) {
379 + check_argc(argc, 2, 2);
380 + value = normalize_value(argv[0], argv[1]);
381 + return git_config_set(argv[0], value);
382 + }
383 + else if (actions == ACTION_SET_ALL) {
384 + check_argc(argc, 2, 3);
385 + value = normalize_value(argv[0], argv[1]);
386 + return git_config_set_multivar(argv[0], value, argv[2], 0);
387 + }
388 + else if (actions == ACTION_ADD) {
389 + check_argc(argc, 2, 2);
390 + value = normalize_value(argv[0], argv[1]);
391 + return git_config_set_multivar(argv[0], value, "^$", 0);
392 + }
393 + else if (actions == ACTION_REPLACE_ALL) {
394 + check_argc(argc, 2, 3);
395 + value = normalize_value(argv[0], argv[1]);
396 + return git_config_set_multivar(argv[0], value, argv[2], 1);
397 + }
398 + else if (actions == ACTION_GET) {
399 + check_argc(argc, 1, 2);
400 + return get_value(argv[0], argv[1]);
401 + }
402 + else if (actions == ACTION_GET_ALL) {
403 + do_all = 1;
404 + check_argc(argc, 1, 2);
405 + return get_value(argv[0], argv[1]);
406 + }
407 + else if (actions == ACTION_GET_REGEXP) {
408 + show_keys = 1;
409 + use_key_regexp = 1;
410 + do_all = 1;
411 + check_argc(argc, 1, 2);
412 + return get_value(argv[0], argv[1]);
413 + }
414 + else if (actions == ACTION_UNSET) {
415 + check_argc(argc, 1, 2);
416 + if (argc == 2)
417 + return git_config_set_multivar(argv[0], NULL, argv[1], 0);
418 + else
419 + return git_config_set(argv[0], NULL);
420 + }
421 + else if (actions == ACTION_UNSET_ALL) {
422 + check_argc(argc, 1, 2);
423 + return git_config_set_multivar(argv[0], NULL, argv[1], 1);
424 + }
425 + else if (actions == ACTION_RENAME_SECTION) {
426 + int ret;
427 + check_argc(argc, 2, 2);
428 + ret = git_config_rename_section(argv[0], argv[1]);
429 + if (ret < 0)
430 + return ret;
431 + if (ret == 0)
432 + die("No such section!");
433 + }
434 + else if (actions == ACTION_REMOVE_SECTION) {
435 + int ret;
436 + check_argc(argc, 1, 1);
437 + ret = git_config_rename_section(argv[0], NULL);
438 + if (ret < 0)
439 + return ret;
440 + if (ret == 0)
441 + die("No such section!");
442 + }
443 + else if (actions == ACTION_GET_COLOR) {
444 + get_color(argv[0]);
445 + }
446 + else if (actions == ACTION_GET_COLORBOOL) {
447 + if (argc == 1)
448 + stdout_is_tty = git_config_bool("command line", argv[0]);
449 + else if (argc == 0)
450 + stdout_is_tty = isatty(1);
451 + return get_colorbool(argc != 0);
452 + }
453 +
454 return 0;
455 }