diff --git a/config.c b/config.c index 36484c4794..cbc3eef123 100644 --- a/config.c +++ b/config.c @@ -1943,6 +1943,24 @@ int git_config_key_is_valid(const char *key) return !git_config_parse_key_1(key, NULL, NULL, 1); } +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. @@ -1993,10 +2011,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; @@ -2278,12 +2294,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 */