Skip to content

Commit 2739889

Browse files
committed
Merge branch 'jk/config-ignore-duplicates'
Drop duplicate detection from "git-config --get"; this lets it better match the internal config callbacks, which clears up some corner cases with includes. * jk/config-ignore-duplicates: builtin/config.c: Fix a sparse warning git-config: use git_config_with_options git-config: do not complain about duplicate entries git-config: collect values instead of immediately printing git-config: fix regexp memory leaks on error conditions git-config: remove memory leak of key regexp t1300: test "git config --get-all" more thoroughly t1300: remove redundant test t1300: style updates
2 parents fda800f + 5ba1a8a commit 2739889

File tree

4 files changed

+232
-196
lines changed

4 files changed

+232
-196
lines changed

builtin/config.c

Lines changed: 43 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ static int show_keys;
1515
static int use_key_regexp;
1616
static int do_all;
1717
static int do_not_match;
18-
static int seen;
1918
static char delim = '=';
2019
static char key_delim = ' ';
2120
static char term = '\n';
@@ -95,12 +94,19 @@ static int show_all_config(const char *key_, const char *value_, void *cb)
9594
return 0;
9695
}
9796

98-
static int show_config(const char *key_, const char *value_, void *cb)
97+
struct strbuf_list {
98+
struct strbuf *items;
99+
int nr;
100+
int alloc;
101+
};
102+
103+
static int collect_config(const char *key_, const char *value_, void *cb)
99104
{
105+
struct strbuf_list *values = cb;
106+
struct strbuf *buf;
100107
char value[256];
101108
const char *vptr = value;
102109
int must_free_vptr = 0;
103-
int dup_error = 0;
104110
int must_print_delim = 0;
105111

106112
if (!use_key_regexp && strcmp(key_, key))
@@ -111,12 +117,14 @@ static int show_config(const char *key_, const char *value_, void *cb)
111117
(do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
112118
return 0;
113119

120+
ALLOC_GROW(values->items, values->nr + 1, values->alloc);
121+
buf = &values->items[values->nr++];
122+
strbuf_init(buf, 0);
123+
114124
if (show_keys) {
115-
printf("%s", key_);
125+
strbuf_addstr(buf, key_);
116126
must_print_delim = 1;
117127
}
118-
if (seen && !do_all)
119-
dup_error = 1;
120128
if (types == TYPE_INT)
121129
sprintf(value, "%d", git_config_int(key_, value_?value_:""));
122130
else if (types == TYPE_BOOL)
@@ -139,16 +147,12 @@ static int show_config(const char *key_, const char *value_, void *cb)
139147
vptr = "";
140148
must_print_delim = 0;
141149
}
142-
seen++;
143-
if (dup_error) {
144-
error("More than one value for the key %s: %s",
145-
key_, vptr);
146-
}
147-
else {
148-
if (must_print_delim)
149-
printf("%c", key_delim);
150-
printf("%s%c", vptr, term);
151-
}
150+
151+
if (must_print_delim)
152+
strbuf_addch(buf, key_delim);
153+
strbuf_addstr(buf, vptr);
154+
strbuf_addch(buf, term);
155+
152156
if (must_free_vptr)
153157
/* If vptr must be freed, it's a pointer to a
154158
* dynamically allocated buffer, it's safe to cast to
@@ -162,19 +166,8 @@ static int show_config(const char *key_, const char *value_, void *cb)
162166
static int get_value(const char *key_, const char *regex_)
163167
{
164168
int ret = CONFIG_GENERIC_ERROR;
165-
char *global = NULL, *xdg = NULL, *repo_config = NULL;
166-
const char *system_wide = NULL, *local;
167-
struct config_include_data inc = CONFIG_INCLUDE_INIT;
168-
config_fn_t fn;
169-
void *data;
170-
171-
local = given_config_file;
172-
if (!local) {
173-
local = repo_config = git_pathdup("config");
174-
if (git_config_system())
175-
system_wide = git_etc_gitconfig();
176-
home_config_paths(&global, &xdg, "config");
177-
}
169+
struct strbuf_list values = {NULL};
170+
int i;
178171

179172
if (use_key_regexp) {
180173
char *tl;
@@ -196,7 +189,8 @@ static int get_value(const char *key_, const char *regex_)
196189
key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
197190
if (regcomp(key_regexp, key, REG_EXTENDED)) {
198191
fprintf(stderr, "Invalid key pattern: %s\n", key_);
199-
free(key);
192+
free(key_regexp);
193+
key_regexp = NULL;
200194
ret = CONFIG_INVALID_PATTERN;
201195
goto free_strings;
202196
}
@@ -216,53 +210,37 @@ static int get_value(const char *key_, const char *regex_)
216210
regexp = (regex_t*)xmalloc(sizeof(regex_t));
217211
if (regcomp(regexp, regex_, REG_EXTENDED)) {
218212
fprintf(stderr, "Invalid pattern: %s\n", regex_);
213+
free(regexp);
214+
regexp = NULL;
219215
ret = CONFIG_INVALID_PATTERN;
220216
goto free_strings;
221217
}
222218
}
223219

224-
fn = show_config;
225-
data = NULL;
226-
if (respect_includes) {
227-
inc.fn = fn;
228-
inc.data = data;
229-
fn = git_config_include;
230-
data = &inc;
231-
}
232-
233-
if (do_all && system_wide)
234-
git_config_from_file(fn, system_wide, data);
235-
if (do_all && xdg)
236-
git_config_from_file(fn, xdg, data);
237-
if (do_all && global)
238-
git_config_from_file(fn, global, data);
239-
if (do_all)
240-
git_config_from_file(fn, local, data);
241-
git_config_from_parameters(fn, data);
242-
if (!do_all && !seen)
243-
git_config_from_file(fn, local, data);
244-
if (!do_all && !seen && global)
245-
git_config_from_file(fn, global, data);
246-
if (!do_all && !seen && xdg)
247-
git_config_from_file(fn, xdg, data);
248-
if (!do_all && !seen && system_wide)
249-
git_config_from_file(fn, system_wide, data);
220+
git_config_with_options(collect_config, &values,
221+
given_config_file, respect_includes);
222+
223+
ret = !values.nr;
250224

225+
for (i = 0; i < values.nr; i++) {
226+
struct strbuf *buf = values.items + i;
227+
if (do_all || i == values.nr - 1)
228+
fwrite(buf->buf, 1, buf->len, stdout);
229+
strbuf_release(buf);
230+
}
231+
free(values.items);
232+
233+
free_strings:
251234
free(key);
235+
if (key_regexp) {
236+
regfree(key_regexp);
237+
free(key_regexp);
238+
}
252239
if (regexp) {
253240
regfree(regexp);
254241
free(regexp);
255242
}
256243

257-
if (do_all)
258-
ret = !seen;
259-
else
260-
ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
261-
262-
free_strings:
263-
free(repo_config);
264-
free(global);
265-
free(xdg);
266244
return ret;
267245
}
268246

config.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_)
12791279

12801280
out_free_ret_1:
12811281
free(*store_key);
1282+
*store_key = NULL;
12821283
return -CONFIG_INVALID_KEY;
12831284
}
12841285

0 commit comments

Comments
 (0)