config: plug user_config leak
[gitweb.git] / builtin / config.c
index 1d7c6ef558bf7adcfb94ea454966667f987f7701..52a4606243e3e39108436feff0319f4c9cc8d990 100644 (file)
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "config.h"
 #include "color.h"
 #include "parse-options.h"
 #include "urlmatch.h"
@@ -25,9 +26,9 @@ static char term = '\n';
 static int use_global_config, use_system_config, use_local_config;
 static struct git_config_source given_config_source;
 static int actions, types;
-static const char *get_color_slot, *get_colorbool_slot;
 static int end_null;
-static int respect_includes = -1;
+static int respect_includes_opt = -1;
+static struct config_options config_options;
 static int show_origin;
 
 #define ACTION_GET (1<<0)
@@ -82,7 +83,7 @@ static struct option builtin_config_options[] = {
        OPT_GROUP(N_("Other")),
        OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
        OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
-       OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")),
+       OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
        OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
        OPT_END(),
 };
@@ -214,8 +215,7 @@ static int get_value(const char *key_, const char *regex_)
                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(key_regexp, key, REG_EXTENDED)) {
                        error("invalid key pattern: %s", key_);
-                       free(key_regexp);
-                       key_regexp = NULL;
+                       FREE_AND_NULL(key_regexp);
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
@@ -235,15 +235,14 @@ static int get_value(const char *key_, const char *regex_)
                regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(regexp, regex_, REG_EXTENDED)) {
                        error("invalid pattern: %s", regex_);
-                       free(regexp);
-                       regexp = NULL;
+                       FREE_AND_NULL(regexp);
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
        }
 
-       git_config_with_options(collect_config, &values,
-                               &given_config_source, respect_includes);
+       config_with_options(collect_config, &values,
+                           &given_config_source, &config_options);
 
        ret = !values.nr;
 
@@ -320,8 +319,8 @@ static void get_color(const char *var, const char *def_color)
        get_color_slot = var;
        get_color_found = 0;
        parsed_color[0] = '\0';
-       git_config_with_options(git_get_color_config, NULL,
-                               &given_config_source, respect_includes);
+       config_with_options(git_get_color_config, NULL,
+                           &given_config_source, &config_options);
 
        if (!get_color_found && def_color) {
                if (color_parse(def_color, parsed_color) < 0)
@@ -352,8 +351,8 @@ static int get_colorbool(const char *var, int print)
        get_colorbool_found = -1;
        get_diff_color_found = -1;
        get_color_ui_found = -1;
-       git_config_with_options(git_get_colorbool_config, NULL,
-                               &given_config_source, respect_includes);
+       config_with_options(git_get_colorbool_config, NULL,
+                           &given_config_source, &config_options);
 
        if (get_colorbool_found < 0) {
                if (!strcmp(get_colorbool_slot, "color.diff"))
@@ -441,8 +440,8 @@ static int get_urlmatch(const char *var, const char *url)
                show_keys = 1;
        }
 
-       git_config_with_options(urlmatch_config_entry, &config,
-                               &given_config_source, respect_includes);
+       config_with_options(urlmatch_config_entry, &config,
+                           &given_config_source, &config_options);
 
        ret = !values.nr;
 
@@ -496,6 +495,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                usage_with_options(builtin_config_usage, builtin_config_options);
        }
 
+       if (use_local_config && nongit)
+               die(_("--local can only be used inside a git repository"));
+
        if (given_config_source.file &&
                        !strcmp(given_config_source.file, "-")) {
                given_config_source.file = NULL;
@@ -503,7 +505,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
        }
 
        if (use_global_config) {
-               char *user_config = expand_user_path("~/.gitconfig");
+               char *user_config = expand_user_path("~/.gitconfig", 0);
                char *xdg_config = xdg_config_home("config");
 
                if (!user_config)
@@ -516,10 +518,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                        die("$HOME not set");
 
                if (access_or_warn(user_config, R_OK, 0) &&
-                   xdg_config && !access_or_warn(xdg_config, R_OK, 0))
+                   xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
                        given_config_source.file = xdg_config;
-               else
+                       free(user_config);
+               } else {
                        given_config_source.file = user_config;
+                       free(xdg_config);
+               }
        }
        else if (use_system_config)
                given_config_source.file = git_etc_gitconfig();
@@ -528,13 +533,17 @@ int cmd_config(int argc, const char **argv, const char *prefix)
        else if (given_config_source.file) {
                if (!is_absolute_path(given_config_source.file) && prefix)
                        given_config_source.file =
-                               xstrdup(prefix_filename(prefix,
-                                                       strlen(prefix),
-                                                       given_config_source.file));
+                               prefix_filename(prefix, given_config_source.file);
        }
 
-       if (respect_includes == -1)
-               respect_includes = !given_config_source.file;
+       if (respect_includes_opt == -1)
+               config_options.respect_includes = !given_config_source.file;
+       else
+               config_options.respect_includes = respect_includes_opt;
+       if (!nongit) {
+               config_options.commondir = get_git_common_dir();
+               config_options.git_dir = get_git_dir();
+       }
 
        if (end_null) {
                term = '\0';
@@ -579,9 +588,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 
        if (actions == ACTION_LIST) {
                check_argc(argc, 0, 0);
-               if (git_config_with_options(show_all_config, NULL,
-                                           &given_config_source,
-                                           respect_includes) < 0) {
+               if (config_with_options(show_all_config, NULL,
+                                       &given_config_source,
+                                       &config_options) < 0) {
                        if (given_config_source.file)
                                die_errno("unable to read config file '%s'",
                                          given_config_source.file);
@@ -600,11 +609,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                if (given_config_source.blob)
                        die("editing blobs is not supported");
                git_config(git_default_config, NULL);
-               config_file = xstrdup(given_config_source.file ?
-                                     given_config_source.file : git_path("config"));
+               config_file = given_config_source.file ?
+                               xstrdup(given_config_source.file) :
+                               git_pathdup("config");
                if (use_global_config) {
                        int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
-                       if (fd) {
+                       if (fd >= 0) {
                                char *content = default_user_config();
                                write_str_in_full(fd, content);
                                free(content);
@@ -623,8 +633,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                value = normalize_value(argv[0], argv[1]);
                ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
                if (ret == CONFIG_NOTHING_SET)
-                       error("cannot overwrite multiple values with a single value\n"
-                       "       Use a regexp, --add or --replace-all to change %s.", argv[0]);
+                       error(_("cannot overwrite multiple values with a single value\n"
+                       "       Use a regexp, --add or --replace-all to change %s."), argv[0]);
                return ret;
        }
        else if (actions == ACTION_SET_ALL) {