From eaa308d37e75cec1caa9a9b2b9e644870f55efc6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 22 Apr 2015 14:47:27 +0100 Subject: [PATCH] Windows: add support for a Windows-wide configuration Between the libgit2 and the Git for Windows project, there has been a discussion how we could share Git configuration to avoid duplication (or worse: skew). Earlier, libgit2 was nice enough to just re-use Git for Windows' C:\Program Files (x86)\Git\etc\gitconfig but with the upcoming Git for Windows 2.x, there would be more paths to search, as we will have 64-bit and 32-bit versions, and the corresponding config files will be in %PROGRAMFILES%\Git\mingw64\etc and ...\mingw32\etc, respectively. Worse: there are portable Git for Windows versions out there which live in totally unrelated directories, still. Therefore we came to a consensus to use `%PROGRAMDATA%\Git\config` as the location for shared Git settings that are of wider interest than just Git for Windows. On XP, there is no %PROGRAMDATA%, therefore we need to use "%ALLUSERSPROFILE%\Application Data\Git\config" in those setups. Of course, the configuration in `%PROGRAMDATA%\Git\config` has the widest reach, therefore it must take the lowest precedence, i.e. Git for Windows can still override settings in its `etc/gitconfig` file. Signed-off-by: Johannes Schindelin --- Documentation/config.txt | 4 +++- Documentation/git-config.txt | 5 +++++ Documentation/git.txt | 3 ++- compat/mingw.c | 19 +++++++++++++++++++ compat/mingw.h | 2 ++ config.c | 5 ++++- git-compat-util.h | 4 ++++ 7 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 35dffd3e52..cd62d45e4f 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -6,7 +6,9 @@ the Git commands' behavior. The `.git/config` file in each repository is used to store the configuration for that repository, and `$HOME/.gitconfig` is used to store a per-user configuration as fallback values for the `.git/config` file. The file `/etc/gitconfig` -can be used to store a system-wide default configuration. +can be used to store a system-wide default configuration. On Windows, +configuration can also be stored in `C:\ProgramData\Git\config`; This +file will be used also by libgit2-based software. The configuration variables are used by both the Git plumbing and the porcelains. The variables are divided into sections, wherein diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 2608ca74ac..352f7392aa 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -246,6 +246,11 @@ $XDG_CONFIG_HOME/git/config:: $GIT_DIR/config:: Repository specific configuration file. +On Windows, as there is no central `/etc/` directory, there is yet another +config file, intended to contain settings for *all* Git-related software +running on the machine. Consequently, this config file takes an even lower +precedence than the `$(prefix)/etc/gitconfig` file. + If no further options are given, all reading options will read all of these files that are available. If the global or the system-wide configuration file are not available they will be ignored. If the repository configuration diff --git a/Documentation/git.txt b/Documentation/git.txt index c3da46dc6a..fe4147ed80 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -988,7 +988,8 @@ for further details. 'GIT_CONFIG_NOSYSTEM':: Whether to skip reading settings from the system-wide - `$(prefix)/etc/gitconfig` file. This environment variable can + `$(prefix)/etc/gitconfig` file (and on Windows, also from the + `%PROGRAMDATA%\Git\config` file). This environment variable can be used along with `$HOME` and `$XDG_CONFIG_HOME` to create a predictable environment for a picky script, or you can set it temporarily to avoid using a buggy `/etc/gitconfig` file while diff --git a/compat/mingw.c b/compat/mingw.c index 17f02b97f1..6cf9d14e38 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2464,3 +2464,22 @@ int uname(struct utsname *buf) "%u", (v >> 16) & 0x7fff); return 0; } + +const char *program_data_config(void) +{ + static struct strbuf path = STRBUF_INIT; + static unsigned initialized; + + if (!initialized) { + const char *env = mingw_getenv("PROGRAMDATA"); + const char *extra = ""; + if (!env) { + env = mingw_getenv("ALLUSERSPROFILE"); + extra = "/Application Data"; + } + if (env) + strbuf_addf(&path, "%s%s/Git/config", env, extra); + initialized = 1; + } + return *path.buf ? path.buf : NULL; +} diff --git a/compat/mingw.h b/compat/mingw.h index 6eed1cce64..f8a2969658 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -420,6 +420,8 @@ static inline char *mingw_find_last_dir_sep(const char *path) int mingw_offset_1st_component(const char *path); #define offset_1st_component mingw_offset_1st_component #define PATH_SEP ';' +extern const char *program_data_config(void); +#define git_program_data_config program_data_config #ifndef __MINGW64_VERSION_MAJOR #define PRIuMAX "I64u" #define PRId64 "I64d" diff --git a/config.c b/config.c index effc3660fd..ef00c41803 100644 --- a/config.c +++ b/config.c @@ -1218,9 +1218,12 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config) char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig"); - if (git_config_system()) + if (git_config_system()) { + config_from_file_gently(fn, git_program_data_config(), data, + 0, &ret, &found); config_from_file_gently(fn, git_etc_gitconfig(), data, 0, &ret, &found); + } config_from_file_gently(fn, xdg_config, data, ACCESS_EACCES_OK, &ret, &found); diff --git a/git-compat-util.h b/git-compat-util.h index 4902d348e9..0deb1c4c33 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -375,6 +375,10 @@ static inline char *git_find_last_dir_sep(const char *path) #define find_last_dir_sep git_find_last_dir_sep #endif +#ifndef git_program_data_config +#define git_program_data_config() NULL +#endif + #if defined(__HP_cc) && (__HP_cc >= 61000) #define NORETURN __attribute__((noreturn)) #define NORETURN_PTR