Skip to content

Commit

Permalink
Merge branch 'jk/config-parsing-cleanup'
Browse files Browse the repository at this point in the history
Configuration parsing for tar.* configuration variables were
broken. Introduce a new config-keyname parser API to make the
callers much less error prone.

* jk/config-parsing-cleanup:
  reflog: use parse_config_key in config callback
  help: use parse_config_key for man config
  submodule: simplify memory handling in config parsing
  submodule: use parse_config_key when parsing config
  userdiff: drop parse_driver function
  convert some config callbacks to parse_config_key
  archive-tar: use parse_config_key when parsing config
  config: add helper function for parsing key names
  • Loading branch information
Junio C Hamano committed Feb 4, 2013
2 parents 149a421 + b3873c3 commit 099ba55
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 99 deletions.
10 changes: 1 addition & 9 deletions archive-tar.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,20 +327,12 @@ static struct archiver *find_tar_filter(const char *name, int len)
static int tar_filter_config(const char *var, const char *value, void *data)
{
struct archiver *ar;
const char *dot;
const char *name;
const char *type;
int namelen;

if (prefixcmp(var, "tar."))
if (parse_config_key(var, "tar", &name, &namelen, &type) < 0 || !name)
return 0;
dot = strrchr(var, '.');
if (dot == var + 9)
return 0;

name = var + 4;
namelen = dot - name;
type = dot + 1;

ar = find_tar_filter(name, namelen);
if (!ar) {
Expand Down
14 changes: 7 additions & 7 deletions builtin/help.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,21 +236,21 @@ static int add_man_viewer_cmd(const char *name,

static int add_man_viewer_info(const char *var, const char *value)
{
const char *name = var + 4;
const char *subkey = strrchr(name, '.');
const char *name, *subkey;
int namelen;

if (!subkey)
if (parse_config_key(var, "man", &name, &namelen, &subkey) < 0 || !name)
return 0;

if (!strcmp(subkey, ".path")) {
if (!strcmp(subkey, "path")) {
if (!value)
return config_error_nonbool(var);
return add_man_viewer_path(name, subkey - name, value);
return add_man_viewer_path(name, namelen, value);
}
if (!strcmp(subkey, ".cmd")) {
if (!strcmp(subkey, "cmd")) {
if (!value)
return config_error_nonbool(var);
return add_man_viewer_cmd(name, subkey - name, value);
return add_man_viewer_cmd(name, namelen, value);
}

return 0;
Expand Down
13 changes: 7 additions & 6 deletions builtin/reflog.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,26 +510,27 @@ static int parse_expire_cfg_value(const char *var, const char *value, unsigned l

static int reflog_expire_config(const char *var, const char *value, void *cb)
{
const char *lastdot = strrchr(var, '.');
const char *pattern, *key;
int pattern_len;
unsigned long expire;
int slot;
struct reflog_expire_cfg *ent;

if (!lastdot || prefixcmp(var, "gc."))
if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0)
return git_default_config(var, value, cb);

if (!strcmp(lastdot, ".reflogexpire")) {
if (!strcmp(key, "reflogexpire")) {
slot = EXPIRE_TOTAL;
if (parse_expire_cfg_value(var, value, &expire))
return -1;
} else if (!strcmp(lastdot, ".reflogexpireunreachable")) {
} else if (!strcmp(key, "reflogexpireunreachable")) {
slot = EXPIRE_UNREACH;
if (parse_expire_cfg_value(var, value, &expire))
return -1;
} else
return git_default_config(var, value, cb);

if (lastdot == var + 2) {
if (!pattern) {
switch (slot) {
case EXPIRE_TOTAL:
default_reflog_expire = expire;
Expand All @@ -541,7 +542,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
return 0;
}

ent = find_cfg_ent(var + 3, lastdot - (var+3));
ent = find_cfg_ent(pattern, pattern_len);
if (!ent)
return -1;
switch (slot) {
Expand Down
15 changes: 15 additions & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,21 @@ struct config_include_data {
#define CONFIG_INCLUDE_INIT { 0 }
extern int git_config_include(const char *name, const char *value, void *data);

/*
* Match and parse a config key of the form:
*
* section.(subsection.)?key
*
* (i.e., what gets handed to a config_fn_t). The caller provides the section;
* we return -1 if it does not match, 0 otherwise. The subsection and key
* out-parameters are filled by the function (and subsection is NULL if it is
* missing).
*/
extern int parse_config_key(const char *var,
const char *section,
const char **subsection, int *subsection_len,
const char **key);

extern int committer_ident_sufficiently_given(void);
extern int author_ident_sufficiently_given(void);

Expand Down
33 changes: 33 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1681,3 +1681,36 @@ int config_error_nonbool(const char *var)
{
return error("Missing value for '%s'", var);
}

int parse_config_key(const char *var,
const char *section,
const char **subsection, int *subsection_len,
const char **key)
{
int section_len = strlen(section);
const char *dot;

/* Does it start with "section." ? */
if (prefixcmp(var, section) || var[section_len] != '.')
return -1;

/*
* Find the key; we don't know yet if we have a subsection, but we must
* parse backwards from the end, since the subsection may have dots in
* it, too.
*/
dot = strrchr(var, '.');
*key = dot + 1;

/* Did we have a subsection at all? */
if (dot == var + section_len) {
*subsection = NULL;
*subsection_len = 0;
}
else {
*subsection = var + section_len + 1;
*subsection_len = dot - *subsection;
}

return 0;
}
14 changes: 5 additions & 9 deletions convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,18 +457,16 @@ static struct convert_driver {

static int read_convert_config(const char *var, const char *value, void *cb)
{
const char *ep, *name;
const char *key, *name;
int namelen;
struct convert_driver *drv;

/*
* External conversion drivers are configured using
* "filter.<name>.variable".
*/
if (prefixcmp(var, "filter.") || (ep = strrchr(var, '.')) == var + 6)
if (parse_config_key(var, "filter", &name, &namelen, &key) < 0 || !name)
return 0;
name = var + 7;
namelen = ep - name;
for (drv = user_convert; drv; drv = drv->next)
if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
break;
Expand All @@ -479,8 +477,6 @@ static int read_convert_config(const char *var, const char *value, void *cb)
user_convert_tail = &(drv->next);
}

ep++;

/*
* filter.<name>.smudge and filter.<name>.clean specifies
* the command line:
Expand All @@ -490,13 +486,13 @@ static int read_convert_config(const char *var, const char *value, void *cb)
* The command-line will not be interpolated in any way.
*/

if (!strcmp("smudge", ep))
if (!strcmp("smudge", key))
return git_config_string(&drv->smudge, var, value);

if (!strcmp("clean", ep))
if (!strcmp("clean", key))
return git_config_string(&drv->clean, var, value);

if (!strcmp("required", ep)) {
if (!strcmp("required", key)) {
drv->required = git_config_bool(var, value);
return 0;
}
Expand Down
14 changes: 5 additions & 9 deletions ll-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ static const char *default_ll_merge;
static int read_merge_config(const char *var, const char *value, void *cb)
{
struct ll_merge_driver *fn;
const char *ep, *name;
const char *key, *name;
int namelen;

if (!strcmp(var, "merge.default")) {
Expand All @@ -236,15 +236,13 @@ static int read_merge_config(const char *var, const char *value, void *cb)
* especially, we do not want to look at variables such as
* "merge.summary", "merge.tool", and "merge.verbosity".
*/
if (prefixcmp(var, "merge.") || (ep = strrchr(var, '.')) == var + 5)
if (parse_config_key(var, "merge", &name, &namelen, &key) < 0 || !name)
return 0;

/*
* Find existing one as we might be processing merge.<name>.var2
* after seeing merge.<name>.var1.
*/
name = var + 6;
namelen = ep - name;
for (fn = ll_user_merge; fn; fn = fn->next)
if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
break;
Expand All @@ -256,16 +254,14 @@ static int read_merge_config(const char *var, const char *value, void *cb)
ll_user_merge_tail = &(fn->next);
}

ep++;

if (!strcmp("name", ep)) {
if (!strcmp("name", key)) {
if (!value)
return error("%s: lacks value", var);
fn->description = xstrdup(value);
return 0;
}

if (!strcmp("driver", ep)) {
if (!strcmp("driver", key)) {
if (!value)
return error("%s: lacks value", var);
/*
Expand All @@ -289,7 +285,7 @@ static int read_merge_config(const char *var, const char *value, void *cb)
return 0;
}

if (!strcmp("recursive", ep)) {
if (!strcmp("recursive", key)) {
if (!value)
return error("%s: lacks value", var);
fn->recursive = xstrdup(value);
Expand Down
43 changes: 21 additions & 22 deletions submodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,45 +126,44 @@ void gitmodules_config(void)

int parse_submodule_config_option(const char *var, const char *value)
{
int len;
struct string_list_item *config;
struct strbuf submodname = STRBUF_INIT;
const char *name, *key;
int namelen;

var += 10; /* Skip "submodule." */
if (parse_config_key(var, "submodule", &name, &namelen, &key) < 0 || !name)
return 0;

len = strlen(var);
if ((len > 5) && !strcmp(var + len - 5, ".path")) {
strbuf_add(&submodname, var, len - 5);
if (!strcmp(key, "path")) {
config = unsorted_string_list_lookup(&config_name_for_path, value);
if (config)
free(config->util);
else
config = string_list_append(&config_name_for_path, xstrdup(value));
config->util = strbuf_detach(&submodname, NULL);
strbuf_release(&submodname);
} else if ((len > 23) && !strcmp(var + len - 23, ".fetchrecursesubmodules")) {
strbuf_add(&submodname, var, len - 23);
config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, submodname.buf);
config->util = xmemdupz(name, namelen);
} else if (!strcmp(key, "fetchrecursesubmodules")) {
char *name_cstr = xmemdupz(name, namelen);
config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name_cstr);
if (!config)
config = string_list_append(&config_fetch_recurse_submodules_for_name,
strbuf_detach(&submodname, NULL));
config = string_list_append(&config_fetch_recurse_submodules_for_name, name_cstr);
else
free(name_cstr);
config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value);
strbuf_release(&submodname);
} else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) {
} else if (!strcmp(key, "ignore")) {
char *name_cstr;

if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
strcmp(value, "all") && strcmp(value, "none")) {
warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var);
return 0;
}

strbuf_add(&submodname, var, len - 7);
config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf);
if (config)
name_cstr = xmemdupz(name, namelen);
config = unsorted_string_list_lookup(&config_ignore_for_name, name_cstr);
if (config) {
free(config->util);
else
config = string_list_append(&config_ignore_for_name,
strbuf_detach(&submodname, NULL));
strbuf_release(&submodname);
free(name_cstr);
} else
config = string_list_append(&config_ignore_for_name, name_cstr);
config->util = xstrdup(value);
return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion t/t5000-tar-tree.sh
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ test_expect_success 'git-archive --prefix=olde-' '
test_expect_success 'setup tar filters' '
git config tar.tar.foo.command "tr ab ba" &&
git config tar.bar.command "tr ab ba" &&
git config tar.bar.remote true
git config tar.bar.remote true &&
git config tar.invalid baz
'

test_expect_success 'archive --list mentions user filter' '
Expand Down
Loading

0 comments on commit 099ba55

Please sign in to comment.