@@ -1166,14 +1166,32 @@ static int git_config_from_blob_ref(config_fn_t fn,
11661166 return git_config_from_blob_sha1 (fn , name , sha1 , data );
11671167}
11681168
1169+ static const char * etc_gitconfig = ETC_GITCONFIG ;
1170+
11691171const char * git_etc_gitconfig (void )
11701172{
11711173 static const char * system_wide ;
11721174 if (!system_wide )
1173- system_wide = system_path (ETC_GITCONFIG );
1175+ system_wide = system_path (etc_gitconfig );
11741176 return system_wide ;
11751177}
11761178
1179+ static const char * git_inst_gitconfig (void )
1180+ {
1181+ static const char * installation_defaults ;
1182+ if (!installation_defaults ) {
1183+ /*
1184+ * if ETC_GITCONFIG as configured in the Makefile is an absolute path,
1185+ * also load installation-specific defaults (relative to $(prefix))
1186+ */
1187+ if (is_dir_sep (* etc_gitconfig ))
1188+ installation_defaults = system_path (etc_gitconfig + 1 );
1189+ else
1190+ installation_defaults = "" ;
1191+ }
1192+ return * installation_defaults ? installation_defaults : NULL ;
1193+ }
1194+
11771195/*
11781196 * Parse environment variable 'k' as a boolean (in various
11791197 * possible spellings); if missing, use the default value 'def'.
@@ -1201,41 +1219,38 @@ int git_config_system(void)
12011219 return !git_env_bool ("GIT_CONFIG_NOSYSTEM" , 0 );
12021220}
12031221
1222+ static inline int config_early_helper (config_fn_t fn , const char * filename ,
1223+ void * data , unsigned access_flags , int count ) {
1224+ if (!filename || access_or_die (filename , R_OK , access_flags ))
1225+ /* no file: return unchanged */
1226+ return count ;
1227+
1228+ if (git_config_from_file (fn , filename , data ))
1229+ /* error: decrement or start counting errors at -1 */
1230+ return count < 0 ? count - 1 : -1 ;
1231+ else
1232+ /* ok: increment unless we had errors before */
1233+ return count < 0 ? count : count + 1 ;
1234+ }
1235+
12041236int git_config_early (config_fn_t fn , void * data , const char * repo_config )
12051237{
1206- int ret = 0 , found = 0 ;
1207- const char * super_config = git_super_config () ;
1238+ /* count loaded files (> 0) or errors (< 0) */
1239+ int cnt = 0 ;
12081240 char * xdg_config = NULL ;
12091241 char * user_config = NULL ;
12101242
12111243 home_config_paths (& user_config , & xdg_config , "config" );
12121244
1213- if (super_config && git_config_system () &&
1214- !access (super_config , R_OK )) {
1215- ret += git_config_from_file (fn , super_config , data );
1216- found += 1 ;
1245+ if (git_config_system ()) {
1246+ cnt = config_early_helper (fn , git_inst_gitconfig (), data , 0 , cnt );
1247+ cnt = config_early_helper (fn , git_etc_gitconfig (), data , 0 , cnt );
12171248 }
12181249
1219- if (git_config_system () && !access_or_die (git_etc_gitconfig (), R_OK , 0 )) {
1220- ret += git_config_from_file (fn , git_etc_gitconfig (),
1221- data );
1222- found += 1 ;
1223- }
1250+ cnt = config_early_helper (fn , xdg_config , data , ACCESS_EACCES_OK , cnt );
1251+ cnt = config_early_helper (fn , user_config , data , ACCESS_EACCES_OK , cnt );
12241252
1225- if (xdg_config && !access_or_die (xdg_config , R_OK , ACCESS_EACCES_OK )) {
1226- ret += git_config_from_file (fn , xdg_config , data );
1227- found += 1 ;
1228- }
1229-
1230- if (user_config && !access_or_die (user_config , R_OK , ACCESS_EACCES_OK )) {
1231- ret += git_config_from_file (fn , user_config , data );
1232- found += 1 ;
1233- }
1234-
1235- if (repo_config && !access_or_die (repo_config , R_OK , 0 )) {
1236- ret += git_config_from_file (fn , repo_config , data );
1237- found += 1 ;
1238- }
1253+ cnt = config_early_helper (fn , repo_config , data , 0 , cnt );
12391254
12401255 switch (git_config_from_parameters (fn , data )) {
12411256 case -1 : /* error */
@@ -1244,13 +1259,14 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
12441259 case 0 : /* found nothing */
12451260 break ;
12461261 default : /* found at least one item */
1247- found ++ ;
1262+ if (cnt >= 0 )
1263+ cnt ++ ;
12481264 break ;
12491265 }
12501266
12511267 free (xdg_config );
12521268 free (user_config );
1253- return ret == 0 ? found : ret ;
1269+ return cnt ;
12541270}
12551271
12561272int git_config_with_options (config_fn_t fn , void * data ,
@@ -1932,6 +1948,24 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_)
19321948 return - CONFIG_INVALID_KEY ;
19331949}
19341950
1951+
1952+ static int lock_config_file (const char * config_filename ,
1953+ struct lock_file * * result )
1954+ {
1955+ int fd ;
1956+ /* make sure the parent directory exists */
1957+ if (safe_create_leading_directories_const (config_filename )) {
1958+ error ("could not create parent directory of %s" , config_filename );
1959+ return -1 ;
1960+ }
1961+ * result = xcalloc (1 , sizeof (struct lock_file ));
1962+ fd = hold_lock_file_for_update (* result , config_filename , 0 );
1963+ if (fd < 0 )
1964+ error ("could not lock config file %s: %s" , config_filename ,
1965+ strerror (errno ));
1966+ return fd ;
1967+ }
1968+
19351969/*
19361970 * If value==NULL, unset in (remove from) config,
19371971 * if value_regex!=NULL, disregard key/value pairs where value does not match.
@@ -1980,10 +2014,8 @@ int git_config_set_multivar_in_file(const char *config_filename,
19802014 * The lock serves a purpose in addition to locking: the new
19812015 * contents of .git/config will be written into it.
19822016 */
1983- lock = xcalloc (1 , sizeof (struct lock_file ));
1984- fd = hold_lock_file_for_update (lock , config_filename , 0 );
2017+ fd = lock_config_file (config_filename , & lock );
19852018 if (fd < 0 ) {
1986- error ("could not lock config file %s: %s" , config_filename , strerror (errno ));
19872019 free (store .key );
19882020 ret = CONFIG_NO_LOCK ;
19892021 goto out_free ;
@@ -2251,12 +2283,9 @@ int git_config_rename_section_in_file(const char *config_filename,
22512283 if (!config_filename )
22522284 config_filename = filename_buf = git_pathdup ("config" );
22532285
2254- lock = xcalloc (1 , sizeof (struct lock_file ));
2255- out_fd = hold_lock_file_for_update (lock , config_filename , 0 );
2256- if (out_fd < 0 ) {
2257- ret = error ("could not lock config file %s" , config_filename );
2286+ out_fd = lock_config_file (config_filename , & lock );
2287+ if (out_fd < 0 )
22582288 goto out ;
2259- }
22602289
22612290 if (!(config_file = fopen (config_filename , "rb" ))) {
22622291 /* no config file means nothing to rename, no error */
0 commit comments