From ccfc039f707a3e5b12819834fadd261a1752d27e Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Fri, 22 May 2015 15:20:21 +0200 Subject: [PATCH] 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 ... Signed-off-by: Karsten Blees Signed-off-by: Johannes Schindelin --- config.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/config.c b/config.c index c685463323..d3f85798cf 100644 --- a/config.c +++ b/config.c @@ -1922,6 +1922,24 @@ out_free_ret_1: return -CONFIG_INVALID_KEY; } +static int lock_config_file(const char *config_filename, + struct lock_file **result) +{ + int fd; + + /* make sure the parent directory exists */ + if (safe_create_leading_directories_const(config_filename)) + return error("could not create parent directory of %s", + config_filename); + *result = xcalloc(1, sizeof(struct lock_file)); + fd = hold_lock_file_for_update(*result, config_filename, 0); + if (fd < 0) + error("could not lock config file %s: %s", config_filename, + strerror(errno)); + + return fd; +} + /* * If value==NULL, unset in (remove from) config, * if value_regex!=NULL, disregard key/value pairs where value does not match. @@ -1972,10 +1990,8 @@ int git_config_set_multivar_in_file(const char *config_filename, * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ - lock = xcalloc(1, sizeof(struct lock_file)); - fd = hold_lock_file_for_update(lock, config_filename, 0); + fd = lock_config_file(config_filename, &lock); if (fd < 0) { - error("could not lock config file %s: %s", config_filename, strerror(errno)); free(store.key); ret = CONFIG_NO_LOCK; goto out_free; @@ -2254,12 +2270,9 @@ int git_config_rename_section_in_file(const char *config_filename, if (!config_filename) config_filename = filename_buf = git_pathdup("config"); - lock = xcalloc(1, sizeof(struct lock_file)); - out_fd = hold_lock_file_for_update(lock, config_filename, 0); - if (out_fd < 0) { - ret = error("could not lock config file %s", config_filename); + out_fd = lock_config_file(config_filename, &lock); + if (out_fd < 0) goto out; - } if (!(config_file = fopen(config_filename, "rb"))) { /* no config file means nothing to rename, no error */