Merge branch 'jk/config-parsing-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Mon, 4 Feb 2013 18:24:50 +0000 (10:24 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 4 Feb 2013 18:24:50 +0000 (10:24 -0800)
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

1  2 
builtin/help.c
cache.h
config.c
diff --combined builtin/help.c
index 6067a6134b58f2464b243f47112226a0a013f5c4,04cb77d67cf64d4a37f2d8c14b11e94913f90de9..d1d71816a9df67721578bc29665c15887575caec
@@@ -6,6 -6,7 +6,6 @@@
  #include "cache.h"
  #include "builtin.h"
  #include "exec_cmd.h"
 -#include "common-cmds.h"
  #include "parse-options.h"
  #include "run-command.h"
  #include "column.h"
@@@ -236,21 -237,21 +236,21 @@@ static int add_man_viewer_cmd(const cha
  
  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;
@@@ -286,6 -287,23 +286,6 @@@ static int git_help_config(const char *
  
  static struct cmdnames main_cmds, other_cmds;
  
 -void list_common_cmds_help(void)
 -{
 -      int i, longest = 0;
 -
 -      for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
 -              if (longest < strlen(common_cmds[i].name))
 -                      longest = strlen(common_cmds[i].name);
 -      }
 -
 -      puts(_("The most commonly used git commands are:"));
 -      for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
 -              printf("   %s   ", common_cmds[i].name);
 -              mput_char(' ', longest - strlen(common_cmds[i].name));
 -              puts(_(common_cmds[i].help));
 -      }
 -}
 -
  static int is_git_command(const char *s)
  {
        return is_in_cmdlist(&main_cmds, s) ||
diff --combined cache.h
index 94ffcda8f6cbb603b79eda1ae441a21450a16cb5,b19305bca2412f5bb9c5d4e9c0cad6e6c3407d62..9038fb500e45e926a696598b91a3759c22e3b306
+++ b/cache.h
@@@ -536,7 -536,6 +536,7 @@@ extern int delete_ref(const char *, con
  /* Environment bits from configuration mechanism */
  extern int trust_executable_bit;
  extern int trust_ctime;
 +extern int check_stat;
  extern int quote_path_fully;
  extern int has_symlinks;
  extern int minimum_abbrev, default_abbrev;
@@@ -563,12 -562,6 +563,12 @@@ extern int core_preload_index
  extern int core_apply_sparse_checkout;
  extern int precomposed_unicode;
  
 +/*
 + * The character that begins a commented line in user-editable file
 + * that is subject to stripspace.
 + */
 +extern char comment_line_char;
 +
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
@@@ -1018,6 -1011,7 +1018,6 @@@ struct ref 
                requires_force:1,
                merge:1,
                nonfastforward:1,
 -              not_forwardable:1,
                update:1,
                deletion:1;
        enum {
@@@ -1154,7 -1148,7 +1154,7 @@@ extern int check_repository_format_vers
  extern int git_env_bool(const char *, int);
  extern int git_config_system(void);
  extern int config_error_nonbool(const char *);
 -#ifdef __GNUC__
 +#if defined(__GNUC__) && ! defined(__clang__)
  #define config_error_nonbool(s) (config_error_nonbool(s), -1)
  #endif
  extern const char *get_log_output_encoding(void);
@@@ -1170,6 -1164,21 +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);
  
diff --combined config.c
index 5a20de3fa62b46d73cc0b13bf5d50aefac78fac6,11bd4d8058532b91eea2dcd5264497d4949557bd..aefd80b12a079d4a3c91d43c8a2c33ed6fbd0a38
+++ b/config.c
@@@ -566,12 -566,6 +566,12 @@@ static int git_default_core_config(cons
                trust_ctime = git_config_bool(var, value);
                return 0;
        }
 +      if (!strcmp(var, "core.statinfo")) {
 +              if (!strcasecmp(value, "default"))
 +                      check_stat = 1;
 +              else if (!strcasecmp(value, "minimal"))
 +                      check_stat = 0;
 +      }
  
        if (!strcmp(var, "core.quotepath")) {
                quote_path_fully = git_config_bool(var, value);
        if (!strcmp(var, "core.editor"))
                return git_config_string(&editor_program, var, value);
  
 +      if (!strcmp(var, "core.commentchar")) {
 +              const char *comment;
 +              int ret = git_config_string(&comment, var, value);
 +              if (!ret)
 +                      comment_line_char = comment[0];
 +              return ret;
 +      }
 +
        if (!strcmp(var, "core.askpass"))
                return git_config_string(&askpass_program, var, value);
  
@@@ -1681,3 -1667,36 +1681,36 @@@ int config_error_nonbool(const char *va
  {
        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;
+ }