Commit 98c11905ac313df911f81a0652c086ce10048616

Ian Hattendorf 2019-03-20T12:28:45

Correctly write to missing locked global config Opening a default config when ~/.gitconfig doesn't exist, locking it, and attempting to write to it causes an assertion failure. Treat non-existent global config file content as an empty string. (cherry picked from commit e44110dbbfc9d50b883d73fbb6c9e3b53732ec9d)

diff --git a/src/config_file.c b/src/config_file.c
index 7f8dd65..b3a3bda 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1133,7 +1133,7 @@ static int config_write(diskfile_backend *cfg, const char *orig_key, const char 
 	reader.file = &cfg->file;
 
 	if (cfg->locked) {
-		result = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content));
+		result = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content));
 	} else {
 		/* Lock the file */
 		if ((result = git_filebuf_open(
diff --git a/tests/config/global.c b/tests/config/global.c
index 9446d8d..9b9da6f 100644
--- a/tests/config/global.c
+++ b/tests/config/global.c
@@ -43,6 +43,36 @@ void test_config_global__open_global(void)
 	git_config_free(cfg);
 }
 
+void test_config_global__lock_missing_global_config(void)
+{
+	git_config *cfg;
+	git_config_entry *entry;
+	git_transaction *transaction;
+
+	p_unlink("home/.gitconfig"); /* No global config */
+
+	cl_git_pass(git_config_open_default(&cfg));
+	cl_git_pass(git_config_lock(&transaction, cfg));
+	cl_git_pass(git_config_set_string(cfg, "assertion.fail", "boom"));
+	cl_git_pass(git_transaction_commit(transaction));
+	git_transaction_free(transaction);
+
+	/* cfg is updated */
+	cl_git_pass(git_config_get_entry(&entry, cfg, "assertion.fail"));
+	cl_assert_equal_s("boom", entry->value);
+
+	git_config_entry_free(entry);
+	git_config_free(cfg);
+
+	/* We can reread the new value from the global config */
+	cl_git_pass(git_config_open_default(&cfg));
+	cl_git_pass(git_config_get_entry(&entry, cfg, "assertion.fail"));
+	cl_assert_equal_s("boom", entry->value);
+
+	git_config_entry_free(entry);
+	git_config_free(cfg);
+}
+
 void test_config_global__open_xdg(void)
 {
 	git_config *cfg, *xdg, *selected;