config: arbitrary number of matches for --unset and --replace-all
git-config used a static match array to hold the matches we want to unset/replace when using --unset or --replace-all. Use a variable-sized array instead. This in particular fixes the symptoms git-svn had when storing large numbers of svn-remote.*.added-placeholder entries in the config file. While the tests are rather more paranoid than just --unset and --replace-all, the other operations already worked. Indeed git-svn's usage only breaks the first time *after* creating so many entries, when it wants to unset and re-add them all. Reported-by: Jess Hottenstein <jess.hottenstein@gmail.com> Signed-off-by: Thomas Rast <tr@thomasrast.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
d7d2c87955
commit
83786fa412
19
config.c
19
config.c
@ -1160,15 +1160,14 @@ int git_config(config_fn_t fn, void *data)
|
||||
* Find all the stuff for git_config_set() below.
|
||||
*/
|
||||
|
||||
#define MAX_MATCHES 512
|
||||
|
||||
static struct {
|
||||
int baselen;
|
||||
char *key;
|
||||
int do_not_match;
|
||||
regex_t *value_regex;
|
||||
int multi_replace;
|
||||
size_t offset[MAX_MATCHES];
|
||||
size_t *offset;
|
||||
unsigned int offset_alloc;
|
||||
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
|
||||
int seen;
|
||||
} store;
|
||||
@ -1191,11 +1190,11 @@ static int store_aux(const char *key, const char *value, void *cb)
|
||||
if (matches(key, value)) {
|
||||
if (store.seen == 1 && store.multi_replace == 0) {
|
||||
warning("%s has multiple values", key);
|
||||
} else if (store.seen >= MAX_MATCHES) {
|
||||
error("too many matches for %s", key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ALLOC_GROW(store.offset, store.seen + 1,
|
||||
store.offset_alloc);
|
||||
|
||||
store.offset[store.seen] = cf->do_ftell(cf);
|
||||
store.seen++;
|
||||
}
|
||||
@ -1223,11 +1222,15 @@ static int store_aux(const char *key, const char *value, void *cb)
|
||||
* Do not increment matches: this is no match, but we
|
||||
* just made sure we are in the desired section.
|
||||
*/
|
||||
ALLOC_GROW(store.offset, store.seen + 1,
|
||||
store.offset_alloc);
|
||||
store.offset[store.seen] = cf->do_ftell(cf);
|
||||
/* fallthru */
|
||||
case SECTION_END_SEEN:
|
||||
case START:
|
||||
if (matches(key, value)) {
|
||||
ALLOC_GROW(store.offset, store.seen + 1,
|
||||
store.offset_alloc);
|
||||
store.offset[store.seen] = cf->do_ftell(cf);
|
||||
store.state = KEY_SEEN;
|
||||
store.seen++;
|
||||
@ -1235,6 +1238,9 @@ static int store_aux(const char *key, const char *value, void *cb)
|
||||
if (strrchr(key, '.') - key == store.baselen &&
|
||||
!strncmp(key, store.key, store.baselen)) {
|
||||
store.state = SECTION_SEEN;
|
||||
ALLOC_GROW(store.offset,
|
||||
store.seen + 1,
|
||||
store.offset_alloc);
|
||||
store.offset[store.seen] = cf->do_ftell(cf);
|
||||
}
|
||||
}
|
||||
@ -1533,6 +1539,7 @@ int git_config_set_multivar_in_file(const char *config_filename,
|
||||
}
|
||||
}
|
||||
|
||||
ALLOC_GROW(store.offset, 1, store.offset_alloc);
|
||||
store.offset[0] = 0;
|
||||
store.state = START;
|
||||
store.seen = 0;
|
||||
|
Reference in New Issue
Block a user