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
}