Skip to content

Commit 78ffbf5

Browse files
kbleesdscho
authored andcommitted
config.c: create missing parent directories when modifying config files
'git config' (--add / --unset etc.) automatically creates missing config files. However, it fails with a misleading error message "could not lock config file" if the parent directory doesn't exist. Also create missing parent directories. This is particularly important when calling git config -f /non/existing/directory/config ... We *must not* create the leading directories when locking a config file. It is the caller's responsibility to ensure that the directory exists, just like it is the caller's responsibility to call `git init` before running repository operations. Point in case: if we simply create all leading directories, calling `git config user.name me` *outside* of a Git worktree will *create* .git/! This fixes #643 and https://groups.google.com/forum/#!topic/git-for-windows/fVRdnDIKVuw [jes: prevented bogus .git/ directories from being created] Signed-off-by: Karsten Blees <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent d3f53cc commit 78ffbf5

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

config.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,20 @@ int git_config_key_is_valid(const char *key)
19521952
return !git_config_parse_key_1(key, NULL, NULL, 1);
19531953
}
19541954

1955+
static int lock_config_file(const char *config_filename,
1956+
struct lock_file **result)
1957+
{
1958+
int fd;
1959+
1960+
*result = xcalloc(1, sizeof(struct lock_file));
1961+
fd = hold_lock_file_for_update(*result, config_filename, 0);
1962+
if (fd < 0)
1963+
error("could not lock config file %s: %s", config_filename,
1964+
strerror(errno));
1965+
1966+
return fd;
1967+
}
1968+
19551969
/*
19561970
* If value==NULL, unset in (remove from) config,
19571971
* if value_regex!=NULL, disregard key/value pairs where value does not match.
@@ -2003,10 +2017,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
20032017
* The lock serves a purpose in addition to locking: the new
20042018
* contents of .git/config will be written into it.
20052019
*/
2006-
lock = xcalloc(1, sizeof(struct lock_file));
2007-
fd = hold_lock_file_for_update(lock, config_filename, 0);
2020+
fd = lock_config_file(config_filename, &lock);
20082021
if (fd < 0) {
2009-
error("could not lock config file %s: %s", config_filename, strerror(errno));
20102022
free(store.key);
20112023
ret = CONFIG_NO_LOCK;
20122024
goto out_free;
@@ -2305,12 +2317,9 @@ int git_config_rename_section_in_file(const char *config_filename,
23052317
if (!config_filename)
23062318
config_filename = filename_buf = git_pathdup("config");
23072319

2308-
lock = xcalloc(1, sizeof(struct lock_file));
2309-
out_fd = hold_lock_file_for_update(lock, config_filename, 0);
2310-
if (out_fd < 0) {
2311-
ret = error("could not lock config file %s", config_filename);
2320+
out_fd = lock_config_file(config_filename, &lock);
2321+
if (out_fd < 0)
23122322
goto out;
2313-
}
23142323

23152324
if (!(config_file = fopen(config_filename, "rb"))) {
23162325
/* no config file means nothing to rename, no error */

0 commit comments

Comments
 (0)