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" |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 3 | #include <regex.h> |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 4 | |
| 5 | static const char git_config_set_usage[] = |
Sean | 34eb334 | 2006-11-02 10:44:20 -0500 | [diff] [blame] | 6 | "git-repo-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --unset | --unset-all] name [value [value_regex]] | --list"; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 7 | |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 8 | static char *key; |
| 9 | static regex_t *key_regexp; |
| 10 | static regex_t *regexp; |
| 11 | static int show_keys; |
| 12 | static int use_key_regexp; |
| 13 | static int do_all; |
| 14 | static int do_not_match; |
| 15 | static int seen; |
Petr Baudis | 7162dff | 2006-02-12 04:14:48 +0100 | [diff] [blame] | 16 | static enum { T_RAW, T_INT, T_BOOL } type = T_RAW; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 17 | |
Petr Baudis | de791f1 | 2006-04-25 00:59:25 +0200 | [diff] [blame] | 18 | static int show_all_config(const char *key_, const char *value_) |
| 19 | { |
| 20 | if (value_) |
| 21 | printf("%s=%s\n", key_, value_); |
| 22 | else |
| 23 | printf("%s\n", key_); |
| 24 | return 0; |
| 25 | } |
| 26 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 27 | static int show_config(const char* key_, const char* value_) |
| 28 | { |
Junio C Hamano | e098c6f | 2006-05-02 21:06:56 -0700 | [diff] [blame] | 29 | char value[256]; |
| 30 | const char *vptr = value; |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 31 | int dup_error = 0; |
Junio C Hamano | e098c6f | 2006-05-02 21:06:56 -0700 | [diff] [blame] | 32 | |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 33 | if (!use_key_regexp && strcmp(key_, key)) |
| 34 | return 0; |
| 35 | if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0)) |
| 36 | return 0; |
| 37 | if (regexp != NULL && |
Johannes Schindelin | f98d863 | 2005-11-20 13:24:18 +0100 | [diff] [blame] | 38 | (do_not_match ^ |
Junio C Hamano | acb7014 | 2006-06-24 05:19:30 -0700 | [diff] [blame] | 39 | regexec(regexp, (value_?value_:""), 0, NULL, 0))) |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 40 | return 0; |
| 41 | |
| 42 | if (show_keys) |
| 43 | printf("%s ", key_); |
| 44 | if (seen && !do_all) |
| 45 | dup_error = 1; |
| 46 | if (type == T_INT) |
Junio C Hamano | acb7014 | 2006-06-24 05:19:30 -0700 | [diff] [blame] | 47 | sprintf(value, "%d", git_config_int(key_, value_?value_:"")); |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 48 | else if (type == T_BOOL) |
| 49 | vptr = git_config_bool(key_, value_) ? "true" : "false"; |
| 50 | else |
Junio C Hamano | acb7014 | 2006-06-24 05:19:30 -0700 | [diff] [blame] | 51 | vptr = value_?value_:""; |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 52 | seen++; |
| 53 | if (dup_error) { |
| 54 | error("More than one value for the key %s: %s", |
| 55 | key_, vptr); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 56 | } |
Johannes Schindelin | 8f5ff31 | 2006-05-03 14:41:03 +0200 | [diff] [blame] | 57 | else |
| 58 | printf("%s\n", vptr); |
| 59 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 60 | return 0; |
| 61 | } |
| 62 | |
| 63 | static int get_value(const char* key_, const char* regex_) |
| 64 | { |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 65 | int ret = -1; |
Linus Torvalds | d14f776 | 2006-05-09 12:24:02 -0700 | [diff] [blame] | 66 | char *tl; |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 67 | char *global = NULL, *repo_config = NULL; |
| 68 | const char *local; |
| 69 | |
| 70 | local = getenv("GIT_CONFIG"); |
| 71 | if (!local) { |
| 72 | const char *home = getenv("HOME"); |
| 73 | local = getenv("GIT_CONFIG_LOCAL"); |
| 74 | if (!local) |
Shawn Pearce | 9befac4 | 2006-09-02 00:16:31 -0400 | [diff] [blame] | 75 | local = repo_config = xstrdup(git_path("config")); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 76 | if (home) |
Shawn Pearce | 9befac4 | 2006-09-02 00:16:31 -0400 | [diff] [blame] | 77 | global = xstrdup(mkpath("%s/.gitconfig", home)); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 78 | } |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 79 | |
Shawn Pearce | 9befac4 | 2006-09-02 00:16:31 -0400 | [diff] [blame] | 80 | key = xstrdup(key_); |
Linus Torvalds | d14f776 | 2006-05-09 12:24:02 -0700 | [diff] [blame] | 81 | for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) |
| 82 | *tl = tolower(*tl); |
| 83 | for (tl=key; *tl && *tl != '.'; ++tl) |
| 84 | *tl = tolower(*tl); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 85 | |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 86 | if (use_key_regexp) { |
Jonas Fonseca | 2d7320d | 2006-09-01 00:32:39 +0200 | [diff] [blame] | 87 | key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 88 | if (regcomp(key_regexp, key, REG_EXTENDED)) { |
Junio C Hamano | e098c6f | 2006-05-02 21:06:56 -0700 | [diff] [blame] | 89 | fprintf(stderr, "Invalid key pattern: %s\n", key_); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 90 | goto free_strings; |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 91 | } |
| 92 | } |
| 93 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 94 | if (regex_) { |
Johannes Schindelin | f98d863 | 2005-11-20 13:24:18 +0100 | [diff] [blame] | 95 | if (regex_[0] == '!') { |
| 96 | do_not_match = 1; |
| 97 | regex_++; |
| 98 | } |
| 99 | |
Jonas Fonseca | 2d7320d | 2006-09-01 00:32:39 +0200 | [diff] [blame] | 100 | regexp = (regex_t*)xmalloc(sizeof(regex_t)); |
Amos Waterland | 0a15217 | 2006-01-04 19:31:02 -0500 | [diff] [blame] | 101 | if (regcomp(regexp, regex_, REG_EXTENDED)) { |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 102 | fprintf(stderr, "Invalid pattern: %s\n", regex_); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 103 | goto free_strings; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 104 | } |
| 105 | } |
| 106 | |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 107 | if (do_all && global) |
| 108 | git_config_from_file(show_config, global); |
| 109 | git_config_from_file(show_config, local); |
| 110 | if (!do_all && !seen && global) |
| 111 | git_config_from_file(show_config, global); |
| 112 | |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 113 | free(key); |
Amos Waterland | 0a15217 | 2006-01-04 19:31:02 -0500 | [diff] [blame] | 114 | if (regexp) { |
| 115 | regfree(regexp); |
| 116 | free(regexp); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 117 | } |
| 118 | |
| 119 | if (do_all) |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 120 | ret = !seen; |
| 121 | else |
Petr Baudis | dc2613d | 2006-07-03 22:47:55 +0200 | [diff] [blame] | 122 | ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 123 | |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 124 | free_strings: |
Junio C Hamano | 4cac42b | 2006-08-27 21:19:39 -0700 | [diff] [blame] | 125 | free(repo_config); |
| 126 | free(global); |
Johannes Schindelin | 5f1a63e | 2006-06-20 01:48:03 +0200 | [diff] [blame] | 127 | return ret; |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 128 | } |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 129 | |
Matthias Kestenholz | e12c095 | 2006-08-02 23:51:59 +0200 | [diff] [blame] | 130 | int cmd_repo_config(int argc, const char **argv, const char *prefix) |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 131 | { |
Linus Torvalds | 4d599e6 | 2006-05-25 08:22:42 -0700 | [diff] [blame] | 132 | int nongit = 0; |
| 133 | setup_git_directory_gently(&nongit); |
Petr Baudis | 7162dff | 2006-02-12 04:14:48 +0100 | [diff] [blame] | 134 | |
| 135 | while (1 < argc) { |
| 136 | if (!strcmp(argv[1], "--int")) |
| 137 | type = T_INT; |
| 138 | else if (!strcmp(argv[1], "--bool")) |
| 139 | type = T_BOOL; |
Johannes Schindelin | cfa24e1 | 2006-05-02 12:54:12 -0700 | [diff] [blame] | 140 | else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) |
| 141 | return git_config(show_all_config); |
Sean | 34eb334 | 2006-11-02 10:44:20 -0500 | [diff] [blame] | 142 | else if (!strcmp(argv[1], "--global")) { |
| 143 | char *home = getenv("HOME"); |
| 144 | if (home) { |
| 145 | char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); |
| 146 | setenv("GIT_CONFIG", user_config, 1); |
| 147 | free(user_config); |
| 148 | } else { |
| 149 | die("$HOME not set"); |
| 150 | } |
| 151 | } else |
Petr Baudis | 7162dff | 2006-02-12 04:14:48 +0100 | [diff] [blame] | 152 | break; |
| 153 | argc--; |
| 154 | argv++; |
| 155 | } |
| 156 | |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 157 | switch (argc) { |
| 158 | case 2: |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 159 | return get_value(argv[1], NULL); |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 160 | case 3: |
| 161 | if (!strcmp(argv[1], "--unset")) |
| 162 | return git_config_set(argv[2], NULL); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 163 | else if (!strcmp(argv[1], "--unset-all")) |
| 164 | return git_config_set_multivar(argv[2], NULL, NULL, 1); |
| 165 | else if (!strcmp(argv[1], "--get")) |
| 166 | return get_value(argv[2], NULL); |
| 167 | else if (!strcmp(argv[1], "--get-all")) { |
| 168 | do_all = 1; |
| 169 | return get_value(argv[2], NULL); |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 170 | } else if (!strcmp(argv[1], "--get-regexp")) { |
| 171 | show_keys = 1; |
| 172 | use_key_regexp = 1; |
| 173 | do_all = 1; |
| 174 | return get_value(argv[2], NULL); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 175 | } else |
| 176 | |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 177 | return git_config_set(argv[1], argv[2]); |
| 178 | case 4: |
| 179 | if (!strcmp(argv[1], "--unset")) |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 180 | return git_config_set_multivar(argv[2], NULL, argv[3], 0); |
| 181 | else if (!strcmp(argv[1], "--unset-all")) |
| 182 | return git_config_set_multivar(argv[2], NULL, argv[3], 1); |
| 183 | else if (!strcmp(argv[1], "--get")) |
| 184 | return get_value(argv[2], argv[3]); |
| 185 | else if (!strcmp(argv[1], "--get-all")) { |
| 186 | do_all = 1; |
| 187 | return get_value(argv[2], argv[3]); |
Johannes Schindelin | 2fa9a0f | 2006-05-02 14:22:48 +0200 | [diff] [blame] | 188 | } else if (!strcmp(argv[1], "--get-regexp")) { |
| 189 | show_keys = 1; |
| 190 | use_key_regexp = 1; |
| 191 | do_all = 1; |
| 192 | return get_value(argv[2], argv[3]); |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 193 | } else if (!strcmp(argv[1], "--replace-all")) |
| 194 | |
| 195 | return git_config_set_multivar(argv[2], argv[3], NULL, 1); |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 196 | else |
Johannes Schindelin | 4ddba79 | 2005-11-20 06:52:22 +0100 | [diff] [blame] | 197 | |
| 198 | return git_config_set_multivar(argv[1], argv[2], argv[3], 0); |
| 199 | case 5: |
| 200 | if (!strcmp(argv[1], "--replace-all")) |
| 201 | return git_config_set_multivar(argv[2], argv[3], argv[4], 1); |
| 202 | case 1: |
Johannes Schindelin | 1b1e59c | 2005-11-17 22:44:55 +0100 | [diff] [blame] | 203 | default: |
| 204 | usage(git_config_set_usage); |
| 205 | } |
| 206 | return 0; |
| 207 | } |