@ -134,6 +134,41 @@ static int get_value(config_fn_t fn, char *name, unsigned int len)
@@ -134,6 +134,41 @@ static int get_value(config_fn_t fn, char *name, unsigned int len)
return fn(name, value);
}
static int get_extended_base_var(char *name, int baselen, int c)
{
do {
if (c == '\n')
return -1;
c = get_next_char();
} while (isspace(c));
/* We require the format to be '[base "extension"]' */
if (c != '"')
return -1;
name[baselen++] = '.';
for (;;) {
int c = get_next_char();
if (c == '\n')
return -1;
if (c == '"')
break;
if (c == '\\') {
c = get_next_char();
if (c == '\n')
return -1;
}
name[baselen++] = c;
if (baselen > MAXNAME / 2)
return -1;
}
/* Final ']' */
if (get_next_char() != ']')
return -1;
return baselen;
}
static int get_base_var(char *name)
{
int baselen = 0;
@ -144,6 +179,8 @@ static int get_base_var(char *name)
@@ -144,6 +179,8 @@ static int get_base_var(char *name)
return -1;
if (c == ']')
return baselen;
if (isspace(c))
return get_extended_base_var(name, baselen, c);
if (!isalnum(c) && c != '.')
return -1;
if (baselen > MAXNAME / 2)
@ -335,10 +372,12 @@ static int store_aux(const char* key, const char* value)
@@ -335,10 +372,12 @@ static int store_aux(const char* key, const char* value)
store.offset[store.seen] = ftell(config_file);
store.state = KEY_SEEN;
store.seen++;
} else if (strrchr(key, '.') - key == store.baselen &&
} else {
if (strrchr(key, '.') - key == store.baselen &&
!strncmp(key, store.key, store.baselen)) {
store.state = SECTION_SEEN;
store.offset[store.seen] = ftell(config_file);
}
}
}
return 0;
@ -346,8 +385,30 @@ static int store_aux(const char* key, const char* value)
@@ -346,8 +385,30 @@ static int store_aux(const char* key, const char* value)
static void store_write_section(int fd, const char* key)
{
const char *dot = strchr(key, '.');
int len1 = store.baselen, len2 = -1;
dot = strchr(key, '.');
if (dot) {
int dotlen = dot - key;
if (dotlen < len1) {
len2 = len1 - dotlen - 1;
len1 = dotlen;
}
}
write(fd, "[", 1);
write(fd, key, store.baselen);
write(fd, key, len1);
if (len2 >= 0) {
write(fd, " \"", 2);
while (--len2 >= 0) {
unsigned char c = *++dot;
if (c == '"')
write(fd, "\\", 1);
write(fd, &c, 1);
}
write(fd, "\"", 1);
}
write(fd, "]\n", 2);
}
@ -421,7 +482,7 @@ int git_config_set(const char* key, const char* value)
@@ -421,7 +482,7 @@ int git_config_set(const char* key, const char* value)
int git_config_set_multivar(const char* key, const char* value,
const char* value_regex, int multi_replace)
{
int i;
int i, dot;
int fd = -1, in_fd;
int ret;
char* config_filename = strdup(git_path("config"));
@ -446,16 +507,23 @@ int git_config_set_multivar(const char* key, const char* value,
@@ -446,16 +507,23 @@ int git_config_set_multivar(const char* key, const char* value,
* Validate the key and while at it, lower case it for matching.
*/
store.key = (char*)malloc(strlen(key)+1);
for (i = 0; key[i]; i++)
if (i != store.baselen &&
((!isalnum(key[i]) && key[i] != '.') ||
(i == store.baselen+1 && !isalpha(key[i])))) {
fprintf(stderr, "invalid key: %s\n", key);
free(store.key);
ret = 1;
goto out_free;
} else
store.key[i] = tolower(key[i]);
dot = 0;
for (i = 0; key[i]; i++) {
unsigned char c = key[i];
if (c == '.')
dot = 1;
/* Leave the extended basename untouched.. */
if (!dot || i > store.baselen) {
if (!isalnum(c) || (i == store.baselen+1 && !isalpha(c))) {
fprintf(stderr, "invalid key: %s\n", key);
free(store.key);
ret = 1;
goto out_free;
}
c = tolower(c);
}
store.key[i] = c;
}
store.key[i] = 0;
/*