config: read config from a repository object

Teach the config machinery to read config information from a repository object. This involves storing a 'struct config_set' inside the repository object and adding a number of functions (repo_config*) to be able to query a repository's config. The current config API enables lazy-loading of the config. This means that when 'git_config_get_int()' is called, if the_config_set hasn't been populated yet, then it will be populated and properly initialized by reading the necessary config files (system wide .gitconfig, user's home .gitconfig, and the repository's config). To maintain this paradigm, the new API to read from a repository object's config will also perform this lazy-initialization. Since both APIs (git_config_get* and repo_config_get*) have the same semantics we can migrate the default config to be stored within 'the_repository' and just have the 'git_config_get*' family of functions redirect to the 'repo_config_get*' functions. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Jun 22, 2017 at 11:43 UTC 3b256228a66f8587661481ef3e08259864f3ba2a
4 files changed +183 -74
config.c
+142 -74
@@ -7,6 +7,7 @@
7 */
8 #include "cache.h"
9 #include "config.h"
10 +#include "repository.h"
11 #include "lockfile.h"
12 #include "exec_cmd.h"
13 #include "strbuf.h"
@@ -72,13 +73,6 @@ static int core_compression_seen;
73 static int pack_compression_seen;
74 static int zlib_compression_seen;
75
75 -/*
76 - * Default config_set that contains key-value pairs from the usual set of config
77 - * config files (i.e repo specific .git/config, user wide ~/.gitconfig, XDG
78 - * config file and the global /etc/gitconfig)
79 - */
80 -static struct config_set the_config_set;
81 -
76 static int config_file_fgetc(struct config_source *conf)
77 {
78 return getc_unlocked(conf->u.file);
@@ -1605,31 +1599,6 @@ int config_with_options(config_fn_t fn, void *data,
1599 return do_git_config_sequence(opts, fn, data);
1600 }
1601
1608 -static void git_config_raw(config_fn_t fn, void *data)
1609 -{
1610 - struct config_options opts = {0};
1611 -
1612 - opts.respect_includes = 1;
1613 - if (have_git_dir()) {
1614 - opts.commondir = get_git_common_dir();
1615 - opts.git_dir = get_git_dir();
1616 - }
1617 -
1618 - if (config_with_options(fn, data, NULL, &opts) < 0)
1619 - /*
1620 - * config_with_options() normally returns only
1621 - * zero, as most errors are fatal, and
1622 - * non-fatal potential errors are guarded by "if"
1623 - * statements that are entered only when no error is
1624 - * possible.
1625 - *
1626 - * If we ever encounter a non-fatal error, it means
1627 - * something went really wrong and we should stop
1628 - * immediately.
1629 - */
1630 - die(_("unknown error occurred while reading the configuration files"));
1631 -}
1632 -
1602 static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
1603 {
1604 int i, value_index;
@@ -1683,14 +1652,6 @@ void read_early_config(config_fn_t cb, void *data)
1652 strbuf_release(&gitdir);
1653 }
1654
1686 -static void git_config_check_init(void);
1687 -
1688 -void git_config(config_fn_t fn, void *data)
1689 -{
1690 - git_config_check_init();
1691 - configset_iter(&the_config_set, fn, data);
1692 -}
1693 -
1655 static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
1656 {
1657 struct config_set_element k;
@@ -1900,87 +1861,194 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha
1861 return 1;
1862 }
1863
1903 -static void git_config_check_init(void)
1864 +/* Functions use to read configuration from a repository */
1865 +static void repo_read_config(struct repository *repo)
1866 {
1905 - if (the_config_set.hash_initialized)
1867 + struct config_options opts;
1868 +
1869 + opts.respect_includes = 1;
1870 + opts.commondir = repo->commondir;
1871 + opts.git_dir = repo->gitdir;
1872 +
1873 + if (!repo->config)
1874 + repo->config = xcalloc(1, sizeof(struct config_set));
1875 + else
1876 + git_configset_clear(repo->config);
1877 +
1878 + git_configset_init(repo->config);
1879 +
1880 + if (config_with_options(config_set_callback, repo->config, NULL, &opts) < 0)
1881 + /*
1882 + * config_with_options() normally returns only
1883 + * zero, as most errors are fatal, and
1884 + * non-fatal potential errors are guarded by "if"
1885 + * statements that are entered only when no error is
1886 + * possible.
1887 + *
1888 + * If we ever encounter a non-fatal error, it means
1889 + * something went really wrong and we should stop
1890 + * immediately.
1891 + */
1892 + die(_("unknown error occurred while reading the configuration files"));
1893 +}
1894 +
1895 +static void git_config_check_init(struct repository *repo)
1896 +{
1897 + if (repo->config && repo->config->hash_initialized)
1898 return;
1907 - git_configset_init(&the_config_set);
1908 - git_config_raw(config_set_callback, &the_config_set);
1899 + repo_read_config(repo);
1900 }
1901
1911 -void git_config_clear(void)
1902 +static void repo_config_clear(struct repository *repo)
1903 {
1913 - if (!the_config_set.hash_initialized)
1904 + if (!repo->config || !repo->config->hash_initialized)
1905 return;
1915 - git_configset_clear(&the_config_set);
1906 + git_configset_clear(repo->config);
1907 }
1908
1918 -int git_config_get_value(const char *key, const char **value)
1909 +void repo_config(struct repository *repo, config_fn_t fn, void *data)
1910 {
1920 - git_config_check_init();
1921 - return git_configset_get_value(&the_config_set, key, value);
1911 + git_config_check_init(repo);
1912 + configset_iter(repo->config, fn, data);
1913 }
1914
1924 -const struct string_list *git_config_get_value_multi(const char *key)
1915 +int repo_config_get_value(struct repository *repo,
1916 + const char *key, const char **value)
1917 {
1926 - git_config_check_init();
1927 - return git_configset_get_value_multi(&the_config_set, key);
1918 + git_config_check_init(repo);
1919 + return git_configset_get_value(repo->config, key, value);
1920 }
1921
1930 -int git_config_get_string_const(const char *key, const char **dest)
1922 +const struct string_list *repo_config_get_value_multi(struct repository *repo,
1923 + const char *key)
1924 +{
1925 + git_config_check_init(repo);
1926 + return git_configset_get_value_multi(repo->config, key);
1927 +}
1928 +
1929 +int repo_config_get_string_const(struct repository *repo,
1930 + const char *key, const char **dest)
1931 +{
1932 + int ret;
1933 + git_config_check_init(repo);
1934 + ret = git_configset_get_string_const(repo->config, key, dest);
1935 + if (ret < 0)
1936 + git_die_config(key, NULL);
1937 + return ret;
1938 +}
1939 +
1940 +int repo_config_get_string(struct repository *repo,
1941 + const char *key, char **dest)
1942 +{
1943 + git_config_check_init(repo);
1944 + return repo_config_get_string_const(repo, key, (const char **)dest);
1945 +}
1946 +
1947 +int repo_config_get_int(struct repository *repo,
1948 + const char *key, int *dest)
1949 +{
1950 + git_config_check_init(repo);
1951 + return git_configset_get_int(repo->config, key, dest);
1952 +}
1953 +
1954 +int repo_config_get_ulong(struct repository *repo,
1955 + const char *key, unsigned long *dest)
1956 +{
1957 + git_config_check_init(repo);
1958 + return git_configset_get_ulong(repo->config, key, dest);
1959 +}
1960 +
1961 +int repo_config_get_bool(struct repository *repo,
1962 + const char *key, int *dest)
1963 +{
1964 + git_config_check_init(repo);
1965 + return git_configset_get_bool(repo->config, key, dest);
1966 +}
1967 +
1968 +int repo_config_get_bool_or_int(struct repository *repo,
1969 + const char *key, int *is_bool, int *dest)
1970 +{
1971 + git_config_check_init(repo);
1972 + return git_configset_get_bool_or_int(repo->config, key, is_bool, dest);
1973 +}
1974 +
1975 +int repo_config_get_maybe_bool(struct repository *repo,
1976 + const char *key, int *dest)
1977 +{
1978 + git_config_check_init(repo);
1979 + return git_configset_get_maybe_bool(repo->config, key, dest);
1980 +}
1981 +
1982 +int repo_config_get_pathname(struct repository *repo,
1983 + const char *key, const char **dest)
1984 {
1985 int ret;
1933 - git_config_check_init();
1934 - ret = git_configset_get_string_const(&the_config_set, key, dest);
1986 + git_config_check_init(repo);
1987 + ret = git_configset_get_pathname(repo->config, key, dest);
1988 if (ret < 0)
1989 git_die_config(key, NULL);
1990 return ret;
1991 }
1992
1993 +/* Functions used historically to read configuration from 'the_repository' */
1994 +void git_config(config_fn_t fn, void *data)
1995 +{
1996 + repo_config(the_repository, fn, data);
1997 +}
1998 +
1999 +void git_config_clear(void)
2000 +{
2001 + repo_config_clear(the_repository);
2002 +}
2003 +
2004 +int git_config_get_value(const char *key, const char **value)
2005 +{
2006 + return repo_config_get_value(the_repository, key, value);
2007 +}
2008 +
2009 +const struct string_list *git_config_get_value_multi(const char *key)
2010 +{
2011 + return repo_config_get_value_multi(the_repository, key);
2012 +}
2013 +
2014 +int git_config_get_string_const(const char *key, const char **dest)
2015 +{
2016 + return repo_config_get_string_const(the_repository, key, dest);
2017 +}
2018 +
2019 int git_config_get_string(const char *key, char **dest)
2020 {
1942 - git_config_check_init();
1943 - return git_config_get_string_const(key, (const char **)dest);
2021 + return repo_config_get_string(the_repository, key, dest);
2022 }
2023
2024 int git_config_get_int(const char *key, int *dest)
2025 {
1948 - git_config_check_init();
1949 - return git_configset_get_int(&the_config_set, key, dest);
2026 + return repo_config_get_int(the_repository, key, dest);
2027 }
2028
2029 int git_config_get_ulong(const char *key, unsigned long *dest)
2030 {
1954 - git_config_check_init();
1955 - return git_configset_get_ulong(&the_config_set, key, dest);
2031 + return repo_config_get_ulong(the_repository, key, dest);
2032 }
2033
2034 int git_config_get_bool(const char *key, int *dest)
2035 {
1960 - git_config_check_init();
1961 - return git_configset_get_bool(&the_config_set, key, dest);
2036 + return repo_config_get_bool(the_repository, key, dest);
2037 }
2038
2039 int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)
2040 {
1966 - git_config_check_init();
1967 - return git_configset_get_bool_or_int(&the_config_set, key, is_bool, dest);
2041 + return repo_config_get_bool_or_int(the_repository, key, is_bool, dest);
2042 }
2043
2044 int git_config_get_maybe_bool(const char *key, int *dest)
2045 {
1972 - git_config_check_init();
1973 - return git_configset_get_maybe_bool(&the_config_set, key, dest);
2046 + return repo_config_get_maybe_bool(the_repository, key, dest);
2047 }
2048
2049 int git_config_get_pathname(const char *key, const char **dest)
2050 {
1978 - int ret;
1979 - git_config_check_init();
1980 - ret = git_configset_get_pathname(&the_config_set, key, dest);
1981 - if (ret < 0)
1982 - git_die_config(key, NULL);
1983 - return ret;
2051 + return repo_config_get_pathname(the_repository, key, dest);
2052 }
2053
2054 int git_config_get_expiry(const char *key, const char **output)
config.h
+24
@@ -163,6 +163,30 @@ extern int git_configset_get_bool_or_int(struct config_set *cs, const char *key,
163 extern int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
164 extern int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
165
166 +/* Functions for reading a repository's config */
167 +struct repository;
168 +extern void repo_config(struct repository *repo, config_fn_t fn, void *data);
169 +extern int repo_config_get_value(struct repository *repo,
170 + const char *key, const char **value);
171 +extern const struct string_list *repo_config_get_value_multi(struct repository *repo,
172 + const char *key);
173 +extern int repo_config_get_string_const(struct repository *repo,
174 + const char *key, const char **dest);
175 +extern int repo_config_get_string(struct repository *repo,
176 + const char *key, char **dest);
177 +extern int repo_config_get_int(struct repository *repo,
178 + const char *key, int *dest);
179 +extern int repo_config_get_ulong(struct repository *repo,
180 + const char *key, unsigned long *dest);
181 +extern int repo_config_get_bool(struct repository *repo,
182 + const char *key, int *dest);
183 +extern int repo_config_get_bool_or_int(struct repository *repo,
184 + const char *key, int *is_bool, int *dest);
185 +extern int repo_config_get_maybe_bool(struct repository *repo,
186 + const char *key, int *dest);
187 +extern int repo_config_get_pathname(struct repository *repo,
188 + const char *key, const char **dest);
189 +
190 extern int git_config_get_value(const char *key, const char **value);
191 extern const struct string_list *git_config_get_value_multi(const char *key);
192 extern void git_config_clear(void);
repository.c
+7
@@ -1,5 +1,6 @@
1 #include "cache.h"
2 #include "repository.h"
3 +#include "config.h"
4
5 /* The main repository */
6 static struct repository the_repo;
@@ -156,4 +157,10 @@ void repo_clear(struct repository *repo)
157 repo->index_file = NULL;
158 free(repo->worktree);
159 repo->worktree = NULL;
160 +
161 + if (repo->config) {
162 + git_configset_clear(repo->config);
163 + free(repo->config);
164 + repo->config = NULL;
165 + }
166 }
repository.h
+10
@@ -1,6 +1,8 @@
1 #ifndef REPOSITORY_H
2 #define REPOSITORY_H
3
4 +struct config_set;
5 +
6 struct repository {
7 /* Environment */
8 /*
@@ -39,6 +41,14 @@ struct repository {
41 */
42 char *worktree;
43
44 + /* Subsystems */
45 + /*
46 + * Repository's config which contains key-value pairs from the usual
47 + * set of config files (i.e. repo specific .git/config, user wide
48 + * ~/.gitconfig, XDG config file and the global /etc/gitconfig)
49 + */
50 + struct config_set *config;
51 +
52 /* Configurations */
53 /*
54 * Bit used during initialization to indicate if repository state (like