builtin-repo-config.con commit rerere: add clear, diff, and status commands (d9671b7)
   1#include "builtin.h"
   2#include "cache.h"
   3#include <regex.h>
   4
   5static const char git_config_set_usage[] =
   6"git-repo-config [ --global ] [ --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 = xstrdup(git_path("config"));
  76                if (home)
  77                        global = xstrdup(mkpath("%s/.gitconfig", home));
  78        }
  79
  80        key = xstrdup(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 : seen > 1 ? 2 : 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 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
 152                        break;
 153                argc--;
 154                argv++;
 155        }
 156
 157        switch (argc) {
 158        case 2:
 159                return get_value(argv[1], NULL);
 160        case 3:
 161                if (!strcmp(argv[1], "--unset"))
 162                        return git_config_set(argv[2], NULL);
 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);
 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);
 175                } else
 176
 177                        return git_config_set(argv[1], argv[2]);
 178        case 4:
 179                if (!strcmp(argv[1], "--unset"))
 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]);
 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]);
 193                } else if (!strcmp(argv[1], "--replace-all"))
 194
 195                        return git_config_set_multivar(argv[2], argv[3], NULL, 1);
 196                else
 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:
 203        default:
 204                usage(git_config_set_usage);
 205        }
 206        return 0;
 207}