d14f776402
This updates the hierarchical section name syntax to [section<space>+"<randomstring>"] where the only rule for "randomstring" is that it can't contain a newline, and if you really want to insert a double-quote, you do it with \". It turns that into the section name "secion.randomstring". The "section" part is still case insensitive, but the "randomstring" part is case sensitive. So you could use this for things like [email "torvalds@osdl.org"] name = Linus Torvalds if you wanted to do the "email->name" conversion as part of the config file format (I'm not claiming that is sensible, I'm just giving it as an insane example). That would show up as the association email.torvalds@osdl.org.name -> Linus Torvalds which is easy to parse (the "." in the email _looks_ ambiguous, but it isn't: you know that there will always be a single key-name, so you find the key name with "strrchr(name, '.')" and things are entirely unambiguous). Repo-config is updated to be able to parse the new format, and also write things out in the new format. [jc: rolled two patches from Linus and one fix-up from Sean into one, with additional adjustments for t/t1300 test to check the case insensitiveness of section base and variable and case sensitiveness of the extended section part. Then stripped some part off to make the result applicable to the stale 1.3.X series that does not have recent enhancements. ] Signed-off-by: Linus Torvalds <torvalds@osdl.org> Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca> Signed-off-by: Junio C Hamano <junkio@cox.net>
145 lines
3.2 KiB
C
145 lines
3.2 KiB
C
#include "cache.h"
|
|
#include <regex.h>
|
|
|
|
static const char git_config_set_usage[] =
|
|
"git-repo-config [ --bool | --int ] [--get | --get-all | --replace-all | --unset | --unset-all] name [value [value_regex]]";
|
|
|
|
static char* key = NULL;
|
|
static char* value = NULL;
|
|
static regex_t* regexp = NULL;
|
|
static int do_all = 0;
|
|
static int do_not_match = 0;
|
|
static int seen = 0;
|
|
static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;
|
|
|
|
static int show_config(const char* key_, const char* value_)
|
|
{
|
|
if (value_ == NULL)
|
|
value_ = "";
|
|
|
|
if (!strcmp(key_, key) &&
|
|
(regexp == NULL ||
|
|
(do_not_match ^
|
|
!regexec(regexp, value_, 0, NULL, 0)))) {
|
|
if (do_all) {
|
|
printf("%s\n", value_);
|
|
return 0;
|
|
}
|
|
if (seen > 0) {
|
|
fprintf(stderr, "More than one value: %s\n", value);
|
|
free(value);
|
|
}
|
|
|
|
if (type == T_INT) {
|
|
value = malloc(256);
|
|
sprintf(value, "%d", git_config_int(key_, value_));
|
|
} else if (type == T_BOOL) {
|
|
value = malloc(256);
|
|
sprintf(value, "%s", git_config_bool(key_, value_)
|
|
? "true" : "false");
|
|
} else {
|
|
value = strdup(value_);
|
|
}
|
|
seen++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int get_value(const char* key_, const char* regex_)
|
|
{
|
|
int i;
|
|
char *tl;
|
|
|
|
key = strdup(key_);
|
|
for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
|
|
*tl = tolower(*tl);
|
|
for (tl=key; *tl && *tl != '.'; ++tl)
|
|
*tl = tolower(*tl);
|
|
|
|
if (regex_) {
|
|
if (regex_[0] == '!') {
|
|
do_not_match = 1;
|
|
regex_++;
|
|
}
|
|
|
|
regexp = (regex_t*)malloc(sizeof(regex_t));
|
|
if (regcomp(regexp, regex_, REG_EXTENDED)) {
|
|
fprintf(stderr, "Invalid pattern: %s\n", regex_);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
i = git_config(show_config);
|
|
if (value) {
|
|
printf("%s\n", value);
|
|
free(value);
|
|
}
|
|
free(key);
|
|
if (regexp) {
|
|
regfree(regexp);
|
|
free(regexp);
|
|
}
|
|
|
|
if (do_all)
|
|
return 0;
|
|
|
|
return seen == 1 ? 0 : 1;
|
|
}
|
|
|
|
int main(int argc, const char **argv)
|
|
{
|
|
setup_git_directory();
|
|
|
|
while (1 < argc) {
|
|
if (!strcmp(argv[1], "--int"))
|
|
type = T_INT;
|
|
else if (!strcmp(argv[1], "--bool"))
|
|
type = T_BOOL;
|
|
else
|
|
break;
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
switch (argc) {
|
|
case 2:
|
|
return get_value(argv[1], NULL);
|
|
case 3:
|
|
if (!strcmp(argv[1], "--unset"))
|
|
return git_config_set(argv[2], NULL);
|
|
else if (!strcmp(argv[1], "--unset-all"))
|
|
return git_config_set_multivar(argv[2], NULL, NULL, 1);
|
|
else if (!strcmp(argv[1], "--get"))
|
|
return get_value(argv[2], NULL);
|
|
else if (!strcmp(argv[1], "--get-all")) {
|
|
do_all = 1;
|
|
return get_value(argv[2], NULL);
|
|
} else
|
|
|
|
return git_config_set(argv[1], argv[2]);
|
|
case 4:
|
|
if (!strcmp(argv[1], "--unset"))
|
|
return git_config_set_multivar(argv[2], NULL, argv[3], 0);
|
|
else if (!strcmp(argv[1], "--unset-all"))
|
|
return git_config_set_multivar(argv[2], NULL, argv[3], 1);
|
|
else if (!strcmp(argv[1], "--get"))
|
|
return get_value(argv[2], argv[3]);
|
|
else if (!strcmp(argv[1], "--get-all")) {
|
|
do_all = 1;
|
|
return get_value(argv[2], argv[3]);
|
|
} else if (!strcmp(argv[1], "--replace-all"))
|
|
|
|
return git_config_set_multivar(argv[2], argv[3], NULL, 1);
|
|
else
|
|
|
|
return git_config_set_multivar(argv[1], argv[2], argv[3], 0);
|
|
case 5:
|
|
if (!strcmp(argv[1], "--replace-all"))
|
|
return git_config_set_multivar(argv[2], argv[3], argv[4], 1);
|
|
case 1:
|
|
default:
|
|
usage(git_config_set_usage);
|
|
}
|
|
return 0;
|
|
}
|