builtin-config.con commit Merge branch 'maint' of git://repo.or.cz/git-gui into maint (b833651)
   1#include "builtin.h"
   2#include "cache.h"
   3
   4static const char git_config_set_usage[] =
   5"git-config [ --global | --system ] [ --bool | --int ] [--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";
   6
   7static char *key;
   8static regex_t *key_regexp;
   9static regex_t *regexp;
  10static int show_keys;
  11static int use_key_regexp;
  12static int do_all;
  13static int do_not_match;
  14static int seen;
  15static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;
  16
  17static int show_all_config(const char *key_, const char *value_)
  18{
  19        if (value_)
  20                printf("%s=%s\n", key_, value_);
  21        else
  22                printf("%s\n", key_);
  23        return 0;
  24}
  25
  26static int show_config(const char* key_, const char* value_)
  27{
  28        char value[256];
  29        const char *vptr = value;
  30        int dup_error = 0;
  31
  32        if (!use_key_regexp && strcmp(key_, key))
  33                return 0;
  34        if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
  35                return 0;
  36        if (regexp != NULL &&
  37                         (do_not_match ^
  38                          regexec(regexp, (value_?value_:""), 0, NULL, 0)))
  39                return 0;
  40
  41        if (show_keys) {
  42                if (value_)
  43                        printf("%s ", key_);
  44                else
  45                        printf("%s", key_);
  46        }
  47        if (seen && !do_all)
  48                dup_error = 1;
  49        if (type == T_INT)
  50                sprintf(value, "%d", git_config_int(key_, value_?value_:""));
  51        else if (type == T_BOOL)
  52                vptr = git_config_bool(key_, value_) ? "true" : "false";
  53        else
  54                vptr = value_?value_:"";
  55        seen++;
  56        if (dup_error) {
  57                error("More than one value for the key %s: %s",
  58                                key_, vptr);
  59        }
  60        else
  61                printf("%s\n", vptr);
  62
  63        return 0;
  64}
  65
  66static int get_value(const char* key_, const char* regex_)
  67{
  68        int ret = -1;
  69        char *tl;
  70        char *global = NULL, *repo_config = NULL;
  71        const char *system_wide = NULL, *local;
  72
  73        local = getenv(CONFIG_ENVIRONMENT);
  74        if (!local) {
  75                const char *home = getenv("HOME");
  76                local = getenv(CONFIG_LOCAL_ENVIRONMENT);
  77                if (!local)
  78                        local = repo_config = xstrdup(git_path("config"));
  79                if (home)
  80                        global = xstrdup(mkpath("%s/.gitconfig", home));
  81                system_wide = ETC_GITCONFIG;
  82        }
  83
  84        key = xstrdup(key_);
  85        for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
  86                *tl = tolower(*tl);
  87        for (tl=key; *tl && *tl != '.'; ++tl)
  88                *tl = tolower(*tl);
  89
  90        if (use_key_regexp) {
  91                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
  92                if (regcomp(key_regexp, key, REG_EXTENDED)) {
  93                        fprintf(stderr, "Invalid key pattern: %s\n", key_);
  94                        goto free_strings;
  95                }
  96        }
  97
  98        if (regex_) {
  99                if (regex_[0] == '!') {
 100                        do_not_match = 1;
 101                        regex_++;
 102                }
 103
 104                regexp = (regex_t*)xmalloc(sizeof(regex_t));
 105                if (regcomp(regexp, regex_, REG_EXTENDED)) {
 106                        fprintf(stderr, "Invalid pattern: %s\n", regex_);
 107                        goto free_strings;
 108                }
 109        }
 110
 111        if (do_all && system_wide)
 112                git_config_from_file(show_config, system_wide);
 113        if (do_all && global)
 114                git_config_from_file(show_config, global);
 115        git_config_from_file(show_config, local);
 116        if (!do_all && !seen && global)
 117                git_config_from_file(show_config, global);
 118        if (!do_all && !seen && system_wide)
 119                git_config_from_file(show_config, system_wide);
 120
 121        free(key);
 122        if (regexp) {
 123                regfree(regexp);
 124                free(regexp);
 125        }
 126
 127        if (do_all)
 128                ret = !seen;
 129        else
 130                ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
 131
 132free_strings:
 133        free(repo_config);
 134        free(global);
 135        return ret;
 136}
 137
 138int cmd_config(int argc, const char **argv, const char *prefix)
 139{
 140        int nongit = 0;
 141        setup_git_directory_gently(&nongit);
 142
 143        while (1 < argc) {
 144                if (!strcmp(argv[1], "--int"))
 145                        type = T_INT;
 146                else if (!strcmp(argv[1], "--bool"))
 147                        type = T_BOOL;
 148                else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l"))
 149                        return git_config(show_all_config);
 150                else if (!strcmp(argv[1], "--global")) {
 151                        char *home = getenv("HOME");
 152                        if (home) {
 153                                char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
 154                                setenv("GIT_CONFIG", user_config, 1);
 155                                free(user_config);
 156                        } else {
 157                                die("$HOME not set");
 158                        }
 159                }
 160                else if (!strcmp(argv[1], "--system"))
 161                        setenv("GIT_CONFIG", ETC_GITCONFIG, 1);
 162                else if (!strcmp(argv[1], "--rename-section")) {
 163                        int ret;
 164                        if (argc != 4)
 165                                usage(git_config_set_usage);
 166                        ret = git_config_rename_section(argv[2], argv[3]);
 167                        if (ret < 0)
 168                                return ret;
 169                        if (ret == 0) {
 170                                fprintf(stderr, "No such section!\n");
 171                                return 1;
 172                        }
 173                        return 0;
 174                }
 175                else if (!strcmp(argv[1], "--remove-section")) {
 176                        int ret;
 177                        if (argc != 3)
 178                                usage(git_config_set_usage);
 179                        ret = git_config_rename_section(argv[2], NULL);
 180                        if (ret < 0)
 181                                return ret;
 182                        if (ret == 0) {
 183                                fprintf(stderr, "No such section!\n");
 184                                return 1;
 185                        }
 186                        return 0;
 187                }
 188                else
 189                        break;
 190                argc--;
 191                argv++;
 192        }
 193
 194        switch (argc) {
 195        case 2:
 196                return get_value(argv[1], NULL);
 197        case 3:
 198                if (!strcmp(argv[1], "--unset"))
 199                        return git_config_set(argv[2], NULL);
 200                else if (!strcmp(argv[1], "--unset-all"))
 201                        return git_config_set_multivar(argv[2], NULL, NULL, 1);
 202                else if (!strcmp(argv[1], "--get"))
 203                        return get_value(argv[2], NULL);
 204                else if (!strcmp(argv[1], "--get-all")) {
 205                        do_all = 1;
 206                        return get_value(argv[2], NULL);
 207                } else if (!strcmp(argv[1], "--get-regexp")) {
 208                        show_keys = 1;
 209                        use_key_regexp = 1;
 210                        do_all = 1;
 211                        return get_value(argv[2], NULL);
 212                } else
 213
 214                        return git_config_set(argv[1], argv[2]);
 215        case 4:
 216                if (!strcmp(argv[1], "--unset"))
 217                        return git_config_set_multivar(argv[2], NULL, argv[3], 0);
 218                else if (!strcmp(argv[1], "--unset-all"))
 219                        return git_config_set_multivar(argv[2], NULL, argv[3], 1);
 220                else if (!strcmp(argv[1], "--get"))
 221                        return get_value(argv[2], argv[3]);
 222                else if (!strcmp(argv[1], "--get-all")) {
 223                        do_all = 1;
 224                        return get_value(argv[2], argv[3]);
 225                } else if (!strcmp(argv[1], "--get-regexp")) {
 226                        show_keys = 1;
 227                        use_key_regexp = 1;
 228                        do_all = 1;
 229                        return get_value(argv[2], argv[3]);
 230                } else if (!strcmp(argv[1], "--add"))
 231                        return git_config_set_multivar(argv[2], argv[3], "^$", 0);
 232                else if (!strcmp(argv[1], "--replace-all"))
 233
 234                        return git_config_set_multivar(argv[2], argv[3], NULL, 1);
 235                else
 236
 237                        return git_config_set_multivar(argv[1], argv[2], argv[3], 0);
 238        case 5:
 239                if (!strcmp(argv[1], "--replace-all"))
 240                        return git_config_set_multivar(argv[2], argv[3], argv[4], 1);
 241        case 1:
 242        default:
 243                usage(git_config_set_usage);
 244        }
 245        return 0;
 246}