Matthias Kestenholz | e12c095 | 2006-08-02 23:51:59 +0200 | [diff] [blame] | 1 | #include "builtin.h" |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 2 | #include "cache.h" |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 3 | #include "color.h" |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 4 | #include "parse-options.h" |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 5 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 6 | static const char *const builtin_config_usage[] = { |
| 7 | "git config [options]", |
| 8 | NULL |
| 9 | }; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 10 | |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 11 | static char *key; |
| 12 | static regex_t *key_regexp; |
| 13 | static regex_t *regexp; |
| 14 | static int show_keys; |
| 15 | static int use_key_regexp; |
| 16 | static int do_all; |
| 17 | static int do_not_match; |
| 18 | static int seen; |
Frank Lichtenheld | 2275d50 | 2007-06-25 16:03:55 +0200 | [diff] [blame] | 19 | static char delim = '='; |
| 20 | static char key_delim = ' '; |
| 21 | static char term = '\n'; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 22 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 23 | static int use_global_config, use_system_config; |
| 24 | static const char *given_config_file; |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 25 | static int actions, types; |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 26 | static const char *get_color_slot, *get_colorbool_slot; |
| 27 | static int end_null; |
| 28 | |
| 29 | #define ACTION_GET (1<<0) |
| 30 | #define ACTION_GET_ALL (1<<1) |
| 31 | #define ACTION_GET_REGEXP (1<<2) |
| 32 | #define ACTION_REPLACE_ALL (1<<3) |
| 33 | #define ACTION_ADD (1<<4) |
| 34 | #define ACTION_UNSET (1<<5) |
| 35 | #define ACTION_UNSET_ALL (1<<6) |
| 36 | #define ACTION_RENAME_SECTION (1<<7) |
| 37 | #define ACTION_REMOVE_SECTION (1<<8) |
| 38 | #define ACTION_LIST (1<<9) |
| 39 | #define ACTION_EDIT (1<<10) |
| 40 | #define ACTION_SET (1<<11) |
| 41 | #define ACTION_SET_ALL (1<<12) |
| 42 | #define ACTION_GET_COLOR (1<<13) |
| 43 | #define ACTION_GET_COLORBOOL (1<<14) |
| 44 | |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 45 | #define TYPE_BOOL (1<<0) |
| 46 | #define TYPE_INT (1<<1) |
| 47 | #define TYPE_BOOL_OR_INT (1<<2) |
Matthieu Moy | 1349484 | 2009-12-30 17:51:53 +0100 | [diff] [blame] | 48 | #define TYPE_PATH (1<<3) |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 49 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 50 | static struct option builtin_config_options[] = { |
| 51 | OPT_GROUP("Config file location"), |
| 52 | OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"), |
| 53 | OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"), |
| 54 | OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"), |
| 55 | OPT_GROUP("Action"), |
| 56 | OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET), |
| 57 | OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL), |
| 58 | OPT_BIT(0, "get-regexp", &actions, "get values for regexp: name-regex [value-regex]", ACTION_GET_REGEXP), |
Carlos Rica | bf71b4b | 2009-03-17 10:46:37 +0100 | [diff] [blame] | 59 | OPT_BIT(0, "replace-all", &actions, "replace all matching variables: name value [value_regex]", ACTION_REPLACE_ALL), |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 60 | OPT_BIT(0, "add", &actions, "adds a new variable: name value", ACTION_ADD), |
| 61 | OPT_BIT(0, "unset", &actions, "removes a variable: name [value-regex]", ACTION_UNSET), |
| 62 | OPT_BIT(0, "unset-all", &actions, "removes all matches: name [value-regex]", ACTION_UNSET_ALL), |
| 63 | OPT_BIT(0, "rename-section", &actions, "rename section: old-name new-name", ACTION_RENAME_SECTION), |
| 64 | OPT_BIT(0, "remove-section", &actions, "remove a section: name", ACTION_REMOVE_SECTION), |
| 65 | OPT_BIT('l', "list", &actions, "list all", ACTION_LIST), |
| 66 | OPT_BIT('e', "edit", &actions, "opens an editor", ACTION_EDIT), |
| 67 | OPT_STRING(0, "get-color", &get_color_slot, "slot", "find the color configured: [default]"), |
| 68 | OPT_STRING(0, "get-colorbool", &get_colorbool_slot, "slot", "find the color setting: [stdout-is-tty]"), |
| 69 | OPT_GROUP("Type"), |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 70 | OPT_BIT(0, "bool", &types, "value is \"true\" or \"false\"", TYPE_BOOL), |
| 71 | OPT_BIT(0, "int", &types, "value is decimal number", TYPE_INT), |
Jeff King | ba04822 | 2009-03-07 12:14:05 -0500 | [diff] [blame] | 72 | OPT_BIT(0, "bool-or-int", &types, "value is --bool or --int", TYPE_BOOL_OR_INT), |
Matthieu Moy | 1349484 | 2009-12-30 17:51:53 +0100 | [diff] [blame] | 73 | OPT_BIT(0, "path", &types, "value is a path (file or directory name)", TYPE_PATH), |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 74 | OPT_GROUP("Other"), |
| 75 | OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"), |
| 76 | OPT_END(), |
| 77 | }; |
| 78 | |
| 79 | static void check_argc(int argc, int min, int max) { |
| 80 | if (argc >= min && argc <= max) |
| 81 | return; |
| 82 | error("wrong number of arguments"); |
| 83 | usage_with_options(builtin_config_usage, builtin_config_options); |
| 84 | } |
| 85 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 86 | static int show_all_config(const char *key_, const char *value_, void *cb) |
Petr Baudis | de791f1 | 2006-04-25 00:59:25 +0200 | [diff] [blame] | 87 | { |
| 88 | if (value_) |
Frank Lichtenheld | 2275d50 | 2007-06-25 16:03:55 +0200 | [diff] [blame] | 89 | printf("%s%c%s%c", key_, delim, value_, term); |
Petr Baudis | de791f1 | 2006-04-25 00:59:25 +0200 | [diff] [blame] | 90 | else |
Frank Lichtenheld | 2275d50 | 2007-06-25 16:03:55 +0200 | [diff] [blame] | 91 | printf("%s%c", key_, term); |
Petr Baudis | de791f1 | 2006-04-25 00:59:25 +0200 | [diff] [blame] | 92 | return 0; |
| 93 | } |
| 94 | |
Felipe Contreras | 4b951b7 | 2009-02-21 02:48:53 +0200 | [diff] [blame] | 95 | static int show_config(const char *key_, const char *value_, void *cb) |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 96 | { |
Junio C Hamano | e098c6f | 2006-05-02 21:06:56 -0700 | [diff] [blame] | 97 | char value[256]; |
| 98 | const char *vptr = value; |
Matthieu Moy | 1349484 | 2009-12-30 17:51:53 +0100 | [diff] [blame] | 99 | int must_free_vptr = 0; |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 100 | int dup_error = 0; |
Junio C Hamano | e098c6f | 2006-05-02 21:06:56 -0700 | [diff] [blame] | 101 | |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 102 | if (!use_key_regexp && strcmp(key_, key)) |
| 103 | return 0; |
| 104 | if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0)) |
| 105 | return 0; |
| 106 | if (regexp != NULL && |
Björn Steinbrink | 9e4bbeb | 2007-12-05 16:11:24 +0100 | [diff] [blame] | 107 | (do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0))) |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 108 | return 0; |
| 109 | |
Frank Lichtenheld | b69ba46 | 2007-06-25 16:03:54 +0200 | [diff] [blame] | 110 | if (show_keys) { |
| 111 | if (value_) |
Frank Lichtenheld | 2275d50 | 2007-06-25 16:03:55 +0200 | [diff] [blame] | 112 | printf("%s%c", key_, key_delim); |
Frank Lichtenheld | b69ba46 | 2007-06-25 16:03:54 +0200 | [diff] [blame] | 113 | else |
| 114 | printf("%s", key_); |
| 115 | } |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 116 | if (seen && !do_all) |
| 117 | dup_error = 1; |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 118 | if (types == TYPE_INT) |
Junio C Hamano | acb7014 | 2006-06-24 05:19:30 -0700 | [diff] [blame] | 119 | sprintf(value, "%d", git_config_int(key_, value_?value_:"")); |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 120 | else if (types == TYPE_BOOL) |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 121 | vptr = git_config_bool(key_, value_) ? "true" : "false"; |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 122 | else if (types == TYPE_BOOL_OR_INT) { |
Junio C Hamano | c35b0b5 | 2008-04-13 12:11:11 -0700 | [diff] [blame] | 123 | int is_bool, v; |
| 124 | v = git_config_bool_or_int(key_, value_, &is_bool); |
| 125 | if (is_bool) |
| 126 | vptr = v ? "true" : "false"; |
| 127 | else |
| 128 | sprintf(value, "%d", v); |
Matthieu Moy | 1349484 | 2009-12-30 17:51:53 +0100 | [diff] [blame] | 129 | } else if (types == TYPE_PATH) { |
| 130 | git_config_pathname(&vptr, key_, value_); |
| 131 | must_free_vptr = 1; |
Junio C Hamano | c35b0b5 | 2008-04-13 12:11:11 -0700 | [diff] [blame] | 132 | } |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 133 | else |
Junio C Hamano | acb7014 | 2006-06-24 05:19:30 -0700 | [diff] [blame] | 134 | vptr = value_?value_:""; |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 135 | seen++; |
| 136 | if (dup_error) { |
| 137 | error("More than one value for the key %s: %s", |
| 138 | key_, vptr); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 139 | } |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 140 | else |
Frank Lichtenheld | 2275d50 | 2007-06-25 16:03:55 +0200 | [diff] [blame] | 141 | printf("%s%c", vptr, term); |
Matthieu Moy | 1349484 | 2009-12-30 17:51:53 +0100 | [diff] [blame] | 142 | if (must_free_vptr) |
| 143 | /* If vptr must be freed, it's a pointer to a |
| 144 | * dynamically allocated buffer, it's safe to cast to |
| 145 | * const. |
| 146 | */ |
| 147 | free((char *)vptr); |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 148 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 149 | return 0; |
| 150 | } |
| 151 | |
Felipe Contreras | 4b951b7 | 2009-02-21 02:48:53 +0200 | [diff] [blame] | 152 | static int get_value(const char *key_, const char *regex_) |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 153 | { |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 154 | int ret = -1; |
Linus Torvalds | d14f776 | 2006-05-09 12:24:02 -0700 | [diff] [blame] | 155 | char *tl; |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 156 | char *global = NULL, *repo_config = NULL; |
Johannes Schindelin | 32043c9 | 2007-02-14 12:48:14 +0100 | [diff] [blame] | 157 | const char *system_wide = NULL, *local; |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 158 | |
Daniel Barkalow | dc87183 | 2008-06-30 03:37:47 -0400 | [diff] [blame] | 159 | local = config_exclusive_filename; |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 160 | if (!local) { |
| 161 | const char *home = getenv("HOME"); |
Alex Riesen | a4f34cb | 2008-10-27 11:22:09 +0100 | [diff] [blame] | 162 | local = repo_config = git_pathdup("config"); |
Jeff King | ab88c36 | 2008-02-06 05:11:18 -0500 | [diff] [blame] | 163 | if (git_config_global() && home) |
Shawn Pearce | 9befac4 | 2006-09-02 00:16:31 -0400 | [diff] [blame] | 164 | global = xstrdup(mkpath("%s/.gitconfig", home)); |
Jeff King | ab88c36 | 2008-02-06 05:11:18 -0500 | [diff] [blame] | 165 | if (git_config_system()) |
| 166 | system_wide = git_etc_gitconfig(); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 167 | } |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 168 | |
Shawn Pearce | 9befac4 | 2006-09-02 00:16:31 -0400 | [diff] [blame] | 169 | key = xstrdup(key_); |
Linus Torvalds | d14f776 | 2006-05-09 12:24:02 -0700 | [diff] [blame] | 170 | for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) |
| 171 | *tl = tolower(*tl); |
| 172 | for (tl=key; *tl && *tl != '.'; ++tl) |
| 173 | *tl = tolower(*tl); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 174 | |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 175 | if (use_key_regexp) { |
Jonas Fonseca | 2d7320d | 2006-09-01 00:32:39 +0200 | [diff] [blame] | 176 | key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 177 | if (regcomp(key_regexp, key, REG_EXTENDED)) { |
Junio C Hamano | e098c6f | 2006-05-02 21:06:56 -0700 | [diff] [blame] | 178 | fprintf(stderr, "Invalid key pattern: %s\n", key_); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 179 | goto free_strings; |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 180 | } |
| 181 | } |
| 182 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 183 | if (regex_) { |
Johannes Schindelin | f98d863 | 2005-11-20 13:24:18 +0100 | [diff] [blame] | 184 | if (regex_[0] == '!') { |
| 185 | do_not_match = 1; |
| 186 | regex_++; |
| 187 | } |
| 188 | |
Jonas Fonseca | 2d7320d | 2006-09-01 00:32:39 +0200 | [diff] [blame] | 189 | regexp = (regex_t*)xmalloc(sizeof(regex_t)); |
Amos Waterland | 0a15217 | 2006-01-04 19:31:02 -0500 | [diff] [blame] | 190 | if (regcomp(regexp, regex_, REG_EXTENDED)) { |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 191 | fprintf(stderr, "Invalid pattern: %s\n", regex_); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 192 | goto free_strings; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 193 | } |
| 194 | } |
| 195 | |
Johannes Schindelin | 32043c9 | 2007-02-14 12:48:14 +0100 | [diff] [blame] | 196 | if (do_all && system_wide) |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 197 | git_config_from_file(show_config, system_wide, NULL); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 198 | if (do_all && global) |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 199 | git_config_from_file(show_config, global, NULL); |
Alex Riesen | 8b1fa77 | 2010-03-26 23:53:57 +0100 | [diff] [blame] | 200 | if (do_all) |
| 201 | git_config_from_file(show_config, local, NULL); |
| 202 | git_config_from_parameters(show_config, NULL); |
| 203 | if (!do_all && !seen) |
| 204 | git_config_from_file(show_config, local, NULL); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 205 | if (!do_all && !seen && global) |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 206 | git_config_from_file(show_config, global, NULL); |
Johannes Schindelin | 32043c9 | 2007-02-14 12:48:14 +0100 | [diff] [blame] | 207 | if (!do_all && !seen && system_wide) |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 208 | git_config_from_file(show_config, system_wide, NULL); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 209 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 210 | free(key); |
Amos Waterland | 0a15217 | 2006-01-04 19:31:02 -0500 | [diff] [blame] | 211 | if (regexp) { |
| 212 | regfree(regexp); |
| 213 | free(regexp); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 214 | } |
| 215 | |
| 216 | if (do_all) |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 217 | ret = !seen; |
| 218 | else |
Petr Baudis | dc2613d | 2006-07-03 22:47:55 +0200 | [diff] [blame] | 219 | ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 220 | |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 221 | free_strings: |
Junio C Hamano | 4cac42b | 2006-08-27 21:19:39 -0700 | [diff] [blame] | 222 | free(repo_config); |
| 223 | free(global); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 224 | return ret; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 225 | } |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 226 | |
Stephan Beyer | 186458b | 2008-07-24 01:09:35 +0200 | [diff] [blame] | 227 | static char *normalize_value(const char *key, const char *value) |
Frank Lichtenheld | db1696b | 2007-06-25 16:00:24 +0200 | [diff] [blame] | 228 | { |
| 229 | char *normalized; |
| 230 | |
| 231 | if (!value) |
| 232 | return NULL; |
| 233 | |
Matthieu Moy | 1349484 | 2009-12-30 17:51:53 +0100 | [diff] [blame] | 234 | if (types == 0 || types == TYPE_PATH) |
| 235 | /* |
| 236 | * We don't do normalization for TYPE_PATH here: If |
| 237 | * the path is like ~/foobar/, we prefer to store |
| 238 | * "~/foobar/" in the config file, and to expand the ~ |
| 239 | * when retrieving the value. |
| 240 | */ |
Frank Lichtenheld | db1696b | 2007-06-25 16:00:24 +0200 | [diff] [blame] | 241 | normalized = xstrdup(value); |
| 242 | else { |
| 243 | normalized = xmalloc(64); |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 244 | if (types == TYPE_INT) { |
Frank Lichtenheld | db1696b | 2007-06-25 16:00:24 +0200 | [diff] [blame] | 245 | int v = git_config_int(key, value); |
| 246 | sprintf(normalized, "%d", v); |
| 247 | } |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 248 | else if (types == TYPE_BOOL) |
Frank Lichtenheld | db1696b | 2007-06-25 16:00:24 +0200 | [diff] [blame] | 249 | sprintf(normalized, "%s", |
| 250 | git_config_bool(key, value) ? "true" : "false"); |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 251 | else if (types == TYPE_BOOL_OR_INT) { |
Junio C Hamano | c35b0b5 | 2008-04-13 12:11:11 -0700 | [diff] [blame] | 252 | int is_bool, v; |
| 253 | v = git_config_bool_or_int(key, value, &is_bool); |
| 254 | if (!is_bool) |
| 255 | sprintf(normalized, "%d", v); |
| 256 | else |
| 257 | sprintf(normalized, "%s", v ? "true" : "false"); |
| 258 | } |
Frank Lichtenheld | db1696b | 2007-06-25 16:00:24 +0200 | [diff] [blame] | 259 | } |
| 260 | |
| 261 | return normalized; |
| 262 | } |
| 263 | |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 264 | static int get_color_found; |
| 265 | static const char *get_color_slot; |
Felipe Contreras | b408457 | 2009-02-21 02:48:56 +0200 | [diff] [blame] | 266 | static const char *get_colorbool_slot; |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 267 | static char parsed_color[COLOR_MAXLEN]; |
| 268 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 269 | static int git_get_color_config(const char *var, const char *value, void *cb) |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 270 | { |
| 271 | if (!strcmp(var, get_color_slot)) { |
Junio C Hamano | f769982 | 2008-02-11 10:48:12 -0800 | [diff] [blame] | 272 | if (!value) |
| 273 | config_error_nonbool(var); |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 274 | color_parse(value, var, parsed_color); |
| 275 | get_color_found = 1; |
| 276 | } |
| 277 | return 0; |
| 278 | } |
| 279 | |
Felipe Contreras | 0e854a2 | 2009-02-21 02:48:57 +0200 | [diff] [blame] | 280 | static void get_color(const char *def_color) |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 281 | { |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 282 | get_color_found = 0; |
| 283 | parsed_color[0] = '\0'; |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 284 | git_config(git_get_color_config, NULL); |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 285 | |
| 286 | if (!get_color_found && def_color) |
| 287 | color_parse(def_color, "command line", parsed_color); |
| 288 | |
| 289 | fputs(parsed_color, stdout); |
Junio C Hamano | 9ce0352 | 2007-11-27 22:41:05 -0800 | [diff] [blame] | 290 | } |
| 291 | |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 292 | static int stdout_is_tty; |
| 293 | static int get_colorbool_found; |
Junio C Hamano | 69243c2 | 2007-12-05 22:12:07 -0800 | [diff] [blame] | 294 | static int get_diff_color_found; |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 295 | static int git_get_colorbool_config(const char *var, const char *value, |
| 296 | void *cb) |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 297 | { |
Felipe Contreras | b408457 | 2009-02-21 02:48:56 +0200 | [diff] [blame] | 298 | if (!strcmp(var, get_colorbool_slot)) { |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 299 | get_colorbool_found = |
| 300 | git_config_colorbool(var, value, stdout_is_tty); |
Junio C Hamano | 69243c2 | 2007-12-05 22:12:07 -0800 | [diff] [blame] | 301 | } |
| 302 | if (!strcmp(var, "diff.color")) { |
| 303 | get_diff_color_found = |
| 304 | git_config_colorbool(var, value, stdout_is_tty); |
| 305 | } |
Matthias Kestenholz | 4d4f5ba | 2008-04-09 21:32:06 +0200 | [diff] [blame] | 306 | if (!strcmp(var, "color.ui")) { |
| 307 | git_use_color_default = git_config_colorbool(var, value, stdout_is_tty); |
| 308 | return 0; |
| 309 | } |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 310 | return 0; |
| 311 | } |
| 312 | |
Felipe Contreras | 0e854a2 | 2009-02-21 02:48:57 +0200 | [diff] [blame] | 313 | static int get_colorbool(int print) |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 314 | { |
Junio C Hamano | 69243c2 | 2007-12-05 22:12:07 -0800 | [diff] [blame] | 315 | get_colorbool_found = -1; |
| 316 | get_diff_color_found = -1; |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 317 | git_config(git_get_colorbool_config, NULL); |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 318 | |
Junio C Hamano | 69243c2 | 2007-12-05 22:12:07 -0800 | [diff] [blame] | 319 | if (get_colorbool_found < 0) { |
Felipe Contreras | b408457 | 2009-02-21 02:48:56 +0200 | [diff] [blame] | 320 | if (!strcmp(get_colorbool_slot, "color.diff")) |
Junio C Hamano | 69243c2 | 2007-12-05 22:12:07 -0800 | [diff] [blame] | 321 | get_colorbool_found = get_diff_color_found; |
| 322 | if (get_colorbool_found < 0) |
Matthias Kestenholz | 4d4f5ba | 2008-04-09 21:32:06 +0200 | [diff] [blame] | 323 | get_colorbool_found = git_use_color_default; |
Junio C Hamano | 69243c2 | 2007-12-05 22:12:07 -0800 | [diff] [blame] | 324 | } |
| 325 | |
Felipe Contreras | 0e854a2 | 2009-02-21 02:48:57 +0200 | [diff] [blame] | 326 | if (print) { |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 327 | printf("%s\n", get_colorbool_found ? "true" : "false"); |
| 328 | return 0; |
Felipe Contreras | 0e854a2 | 2009-02-21 02:48:57 +0200 | [diff] [blame] | 329 | } else |
| 330 | return get_colorbool_found ? 0 : 1; |
Junio C Hamano | 0f6f5a4 | 2007-12-05 17:26:11 -0800 | [diff] [blame] | 331 | } |
| 332 | |
Felipe Contreras | b408457 | 2009-02-21 02:48:56 +0200 | [diff] [blame] | 333 | int cmd_config(int argc, const char **argv, const char *unused_prefix) |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 334 | { |
SZEDER Gábor | af05d67 | 2008-03-25 22:06:26 +0100 | [diff] [blame] | 335 | int nongit; |
Felipe Contreras | 4b951b7 | 2009-02-21 02:48:53 +0200 | [diff] [blame] | 336 | char *value; |
Felipe Contreras | b408457 | 2009-02-21 02:48:56 +0200 | [diff] [blame] | 337 | const char *prefix = setup_git_directory_gently(&nongit); |
Petr Baudis | 7162dff | 2006-02-12 04:14:48 +0100 | [diff] [blame] | 338 | |
Daniel Barkalow | dc87183 | 2008-06-30 03:37:47 -0400 | [diff] [blame] | 339 | config_exclusive_filename = getenv(CONFIG_ENVIRONMENT); |
| 340 | |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 341 | argc = parse_options(argc, argv, prefix, builtin_config_options, |
| 342 | builtin_config_usage, |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 343 | PARSE_OPT_STOP_AT_NON_OPTION); |
| 344 | |
Felipe Contreras | 67052c9 | 2009-02-21 02:49:26 +0200 | [diff] [blame] | 345 | if (use_global_config + use_system_config + !!given_config_file > 1) { |
| 346 | error("only one config file at a time."); |
| 347 | usage_with_options(builtin_config_usage, builtin_config_options); |
| 348 | } |
| 349 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 350 | if (use_global_config) { |
| 351 | char *home = getenv("HOME"); |
| 352 | if (home) { |
| 353 | char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); |
| 354 | config_exclusive_filename = user_config; |
| 355 | } else { |
| 356 | die("$HOME not set"); |
Frank Lichtenheld | a72c874 | 2007-10-05 22:16:44 +0200 | [diff] [blame] | 357 | } |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 358 | } |
| 359 | else if (use_system_config) |
| 360 | config_exclusive_filename = git_etc_gitconfig(); |
| 361 | else if (given_config_file) { |
| 362 | if (!is_absolute_path(given_config_file) && prefix) |
| 363 | config_exclusive_filename = prefix_filename(prefix, |
| 364 | strlen(prefix), |
Johan Herland | 65807ee | 2010-01-26 16:02:16 +0100 | [diff] [blame] | 365 | given_config_file); |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 366 | else |
| 367 | config_exclusive_filename = given_config_file; |
Petr Baudis | 7162dff | 2006-02-12 04:14:48 +0100 | [diff] [blame] | 368 | } |
| 369 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 370 | if (end_null) { |
| 371 | term = '\0'; |
| 372 | delim = '\n'; |
| 373 | key_delim = '\n'; |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 374 | } |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 375 | |
Felipe Contreras | 16c1e93 | 2009-02-21 02:49:27 +0200 | [diff] [blame] | 376 | if (HAS_MULTI_BITS(types)) { |
| 377 | error("only one type at a time."); |
| 378 | usage_with_options(builtin_config_usage, builtin_config_options); |
| 379 | } |
| 380 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 381 | if (get_color_slot) |
| 382 | actions |= ACTION_GET_COLOR; |
| 383 | if (get_colorbool_slot) |
| 384 | actions |= ACTION_GET_COLORBOOL; |
| 385 | |
Felipe Contreras | c238735 | 2009-02-21 02:49:29 +0200 | [diff] [blame] | 386 | if ((get_color_slot || get_colorbool_slot) && types) { |
| 387 | error("--get-color and variable type are incoherent"); |
| 388 | usage_with_options(builtin_config_usage, builtin_config_options); |
| 389 | } |
| 390 | |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 391 | if (HAS_MULTI_BITS(actions)) { |
| 392 | error("only one action at a time."); |
| 393 | usage_with_options(builtin_config_usage, builtin_config_options); |
| 394 | } |
| 395 | if (actions == 0) |
| 396 | switch (argc) { |
| 397 | case 1: actions = ACTION_GET; break; |
| 398 | case 2: actions = ACTION_SET; break; |
| 399 | case 3: actions = ACTION_SET_ALL; break; |
| 400 | default: |
| 401 | usage_with_options(builtin_config_usage, builtin_config_options); |
| 402 | } |
| 403 | |
| 404 | if (actions == ACTION_LIST) { |
Felipe Contreras | 225a9ca | 2009-02-21 02:49:28 +0200 | [diff] [blame] | 405 | check_argc(argc, 0, 0); |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 406 | if (git_config(show_all_config, NULL) < 0) { |
| 407 | if (config_exclusive_filename) |
Thomas Rast | d824cbb | 2009-06-27 17:58:46 +0200 | [diff] [blame] | 408 | die_errno("unable to read config file '%s'", |
| 409 | config_exclusive_filename); |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 410 | else |
| 411 | die("error processing config file(s)"); |
| 412 | } |
| 413 | } |
| 414 | else if (actions == ACTION_EDIT) { |
Felipe Contreras | 225a9ca | 2009-02-21 02:49:28 +0200 | [diff] [blame] | 415 | check_argc(argc, 0, 0); |
Felipe Contreras | d212ca1 | 2009-04-30 01:49:47 +0300 | [diff] [blame] | 416 | if (!config_exclusive_filename && nongit) |
| 417 | die("not in a git directory"); |
Felipe Contreras | d64ec16 | 2009-02-21 02:49:25 +0200 | [diff] [blame] | 418 | git_config(git_default_config, NULL); |
| 419 | launch_editor(config_exclusive_filename ? |
| 420 | config_exclusive_filename : git_path("config"), |
| 421 | NULL, NULL); |
| 422 | } |
| 423 | else if (actions == ACTION_SET) { |
| 424 | check_argc(argc, 2, 2); |
| 425 | value = normalize_value(argv[0], argv[1]); |
| 426 | return git_config_set(argv[0], value); |
| 427 | } |
| 428 | else if (actions == ACTION_SET_ALL) { |
| 429 | check_argc(argc, 2, 3); |
| 430 | value = normalize_value(argv[0], argv[1]); |
| 431 | return git_config_set_multivar(argv[0], value, argv[2], 0); |
| 432 | } |
| 433 | else if (actions == ACTION_ADD) { |
| 434 | check_argc(argc, 2, 2); |
| 435 | value = normalize_value(argv[0], argv[1]); |
| 436 | return git_config_set_multivar(argv[0], value, "^$", 0); |
| 437 | } |
| 438 | else if (actions == ACTION_REPLACE_ALL) { |
| 439 | check_argc(argc, 2, 3); |
| 440 | value = normalize_value(argv[0], argv[1]); |
| 441 | return git_config_set_multivar(argv[0], value, argv[2], 1); |
| 442 | } |
| 443 | else if (actions == ACTION_GET) { |
| 444 | check_argc(argc, 1, 2); |
| 445 | return get_value(argv[0], argv[1]); |
| 446 | } |
| 447 | else if (actions == ACTION_GET_ALL) { |
| 448 | do_all = 1; |
| 449 | check_argc(argc, 1, 2); |
| 450 | return get_value(argv[0], argv[1]); |
| 451 | } |
| 452 | else if (actions == ACTION_GET_REGEXP) { |
| 453 | show_keys = 1; |
| 454 | use_key_regexp = 1; |
| 455 | do_all = 1; |
| 456 | check_argc(argc, 1, 2); |
| 457 | return get_value(argv[0], argv[1]); |
| 458 | } |
| 459 | else if (actions == ACTION_UNSET) { |
| 460 | check_argc(argc, 1, 2); |
| 461 | if (argc == 2) |
| 462 | return git_config_set_multivar(argv[0], NULL, argv[1], 0); |
| 463 | else |
| 464 | return git_config_set(argv[0], NULL); |
| 465 | } |
| 466 | else if (actions == ACTION_UNSET_ALL) { |
| 467 | check_argc(argc, 1, 2); |
| 468 | return git_config_set_multivar(argv[0], NULL, argv[1], 1); |
| 469 | } |
| 470 | else if (actions == ACTION_RENAME_SECTION) { |
| 471 | int ret; |
| 472 | check_argc(argc, 2, 2); |
| 473 | ret = git_config_rename_section(argv[0], argv[1]); |
| 474 | if (ret < 0) |
| 475 | return ret; |
| 476 | if (ret == 0) |
| 477 | die("No such section!"); |
| 478 | } |
| 479 | else if (actions == ACTION_REMOVE_SECTION) { |
| 480 | int ret; |
| 481 | check_argc(argc, 1, 1); |
| 482 | ret = git_config_rename_section(argv[0], NULL); |
| 483 | if (ret < 0) |
| 484 | return ret; |
| 485 | if (ret == 0) |
| 486 | die("No such section!"); |
| 487 | } |
| 488 | else if (actions == ACTION_GET_COLOR) { |
| 489 | get_color(argv[0]); |
| 490 | } |
| 491 | else if (actions == ACTION_GET_COLORBOOL) { |
| 492 | if (argc == 1) |
| 493 | stdout_is_tty = git_config_bool("command line", argv[0]); |
| 494 | else if (argc == 0) |
| 495 | stdout_is_tty = isatty(1); |
| 496 | return get_colorbool(argc != 0); |
| 497 | } |
| 498 | |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 499 | return 0; |
| 500 | } |