a1756c85803f9444fd6154511640d9b3b0da07e7
   1#include "builtin.h"
   2#include "cache.h"
   3#include <regex.h>
   4
   5static const char git_config_set_usage[] =
   6"git-repo-config [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --unset | --unset-all] name [value [value_regex]] | --list";
   7
   8static char *key;
   9static regex_t *key_regexp;
  10static regex_t *regexp;
  11static int show_keys;
  12static int use_key_regexp;
  13static int do_all;
  14static int do_not_match;
  15static int seen;
  16static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;
  17
  18static 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
  27static int show_config(const char* key_, const char* value_)
  28{
  29        char value[256];
  30        const char *vptr = value;
  31        int dup_error = 0;
  32
  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 &&
  38                         (do_not_match ^
  39                          regexec(regexp, (value_?value_:""), 0, NULL, 0)))
  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)
  47                sprintf(value, "%d", git_config_int(key_, value_?value_:""));
  48        else if (type == T_BOOL)
  49                vptr = git_config_bool(key_, value_) ? "true" : "false";
  50        else
  51                vptr = value_?value_:"";
  52        seen++;
  53        if (dup_error) {
  54                error("More than one value for the key %s: %s",
  55                                key_, vptr);
  56        }
  57        else
  58                printf("%s\n", vptr);
  59
  60        return 0;
  61}
  62
  63static int get_value(const char* key_, const char* regex_)
  64{
  65        int ret = -1;
  66        char *tl;
  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)
  75                        local = repo_config = strdup(git_path("config"));
  76                if (home)
  77                        global = strdup(mkpath("%s/.gitconfig", home));
  78        }
  79
  80        key = strdup(key_);
  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);
  85
  86        if (use_key_regexp) {
  87                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
  88                if (regcomp(key_regexp, key, REG_EXTENDED)) {
  89                        fprintf(stderr, "Invalid key pattern: %s\n", key_);
  90                        goto free_strings;
  91                }
  92        }
  93
  94        if (regex_) {
  95                if (regex_[0] == '!') {
  96                        do_not_match = 1;
  97                        regex_++;
  98                }
  99
 100                regexp = (regex_t*)xmalloc(sizeof(regex_t));
 101                if (regcomp(regexp, regex_, REG_EXTENDED)) {
 102                        fprintf(stderr, "Invalid pattern: %s\n", regex_);
 103                        goto free_strings;
 104                }
 105        }
 106
 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
 113        free(key);
 114        if (regexp) {
 115                regfree(regexp);
 116                free(regexp);
 117        }
 118
 119        if (do_all)
 120                ret = !seen;
 121        else
 122                ret =  (seen == 1) ? 0 : 1;
 123
 124free_strings:
 125        free(repo_config);
 126        free(global);
 127        return ret;
 128}
 129
 130int cmd_repo_config(int argc, const char **argv, const char *prefix)
 131{
 132        int nongit = 0;
 133        setup_git_directory_gently(&nongit);
 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;
 140                else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l"))
 141                        return git_config(show_all_config);
 142                else
 143                        break;
 144                argc--;
 145                argv++;
 146        }
 147
 148        switch (argc) {
 149        case 2:
 150                return get_value(argv[1], NULL);
 151        case 3:
 152                if (!strcmp(argv[1], "--unset"))
 153                        return git_config_set(argv[2], NULL);
 154                else if (!strcmp(argv[1], "--unset-all"))
 155                        return git_config_set_multivar(argv[2], NULL, NULL, 1);
 156                else if (!strcmp(argv[1], "--get"))
 157                        return get_value(argv[2], NULL);
 158                else if (!strcmp(argv[1], "--get-all")) {
 159                        do_all = 1;
 160                        return get_value(argv[2], NULL);
 161                } else if (!strcmp(argv[1], "--get-regexp")) {
 162                        show_keys = 1;
 163                        use_key_regexp = 1;
 164                        do_all = 1;
 165                        return get_value(argv[2], NULL);
 166                } else
 167
 168                        return git_config_set(argv[1], argv[2]);
 169        case 4:
 170                if (!strcmp(argv[1], "--unset"))
 171                        return git_config_set_multivar(argv[2], NULL, argv[3], 0);
 172                else if (!strcmp(argv[1], "--unset-all"))
 173                        return git_config_set_multivar(argv[2], NULL, argv[3], 1);
 174                else if (!strcmp(argv[1], "--get"))
 175                        return get_value(argv[2], argv[3]);
 176                else if (!strcmp(argv[1], "--get-all")) {
 177                        do_all = 1;
 178                        return get_value(argv[2], argv[3]);
 179                } else if (!strcmp(argv[1], "--get-regexp")) {
 180                        show_keys = 1;
 181                        use_key_regexp = 1;
 182                        do_all = 1;
 183                        return get_value(argv[2], argv[3]);
 184                } else if (!strcmp(argv[1], "--replace-all"))
 185
 186                        return git_config_set_multivar(argv[2], argv[3], NULL, 1);
 187                else
 188
 189                        return git_config_set_multivar(argv[1], argv[2], argv[3], 0);
 190        case 5:
 191                if (!strcmp(argv[1], "--replace-all"))
 192                        return git_config_set_multivar(argv[2], argv[3], argv[4], 1);
 193        case 1:
 194        default:
 195                usage(git_config_set_usage);
 196        }
 197        return 0;
 198}