about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-03-10 11:13:38 -0800
committerJunio C Hamano <gitster@pobox.com>2016-03-10 11:13:38 -0800
commit2d5ff66c134681d846e5102a9a62ec99c2178fe1 (patch)
treebb93748c56954fc084beeae99fccab0fcd5f5cf5
parent9bb71036f3a4cc7fdb11a8bf15e47b986649d234 (diff)
parent3d1806487af395fb33d1de92633e96571b296305 (diff)
downloadgit-svn-2d5ff66c134681d846e5102a9a62ec99c2178fe1.tar.gz
Many codepaths forget to check return value from git_config_set();
the function is made to die() to make sure we do not proceed when
setting a configuration variable failed.

* ps/config-error:
  config: rename git_config_set_or_die to git_config_set
  config: rename git_config_set to git_config_set_gently
  compat: die when unable to set core.precomposeunicode
  sequencer: die on config error when saving replay opts
  init-db: die on config errors when initializing empty repo
  clone: die on config error in cmd_clone
  remote: die on config error when manipulating remotes
  remote: die on config error when setting/adding branches
  remote: die on config error when setting URL
  submodule--helper: die on config error when cloning module
  submodule: die on config error when linking modules
  branch: die on config error when editing branch description
  branch: die on config error when unsetting upstream
  branch: report errors in tracking branch setup
  config: introduce set_or_die wrappers
-rw-r--r--branch.c50
-rw-r--r--branch.h3
-rw-r--r--builtin/branch.c5
-rw-r--r--builtin/clone.c2
-rw-r--r--builtin/config.c28
-rw-r--r--builtin/init-db.c2
-rw-r--r--builtin/remote.c70
-rw-r--r--cache.h14
-rw-r--r--compat/precompose_utf8.c3
-rw-r--r--config.c52
-rw-r--r--submodule.c10
-rwxr-xr-xt/t3200-branch.sh16
-rwxr-xr-xt/t5505-remote.sh9
13 files changed, 159 insertions, 105 deletions
diff --git a/branch.c b/branch.c
index 7ff3f20496..c50ea42172 100644
--- a/branch.c
+++ b/branch.c
@@ -49,7 +49,13 @@ static int should_setup_rebase(const char *origin)
         return 0;
 }
 
-void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
+static const char tracking_advice[] =
+N_("\n"
+"After fixing the error cause you may try to fix up\n"
+"the remote tracking information by invoking\n"
+"\"git branch --set-upstream-to=%s%s%s\".");
+
+int install_branch_config(int flag, const char *local, const char *origin, const char *remote)
 {
         const char *shortname = NULL;
         struct strbuf key = STRBUF_INIT;
@@ -60,20 +66,23 @@ void install_branch_config(int flag, const char *local, const char *origin, cons
             && !origin) {
                 warning(_("Not setting branch %s as its own upstream."),
                         local);
-                return;
+                return 0;
         }
 
         strbuf_addf(&key, "branch.%s.remote", local);
-        git_config_set(key.buf, origin ? origin : ".");
+        if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
+                goto out_err;
 
         strbuf_reset(&key);
         strbuf_addf(&key, "branch.%s.merge", local);
-        git_config_set(key.buf, remote);
+        if (git_config_set_gently(key.buf, remote) < 0)
+                goto out_err;
 
         if (rebasing) {
                 strbuf_reset(&key);
                 strbuf_addf(&key, "branch.%s.rebase", local);
-                git_config_set(key.buf, "true");
+                if (git_config_set_gently(key.buf, "true") < 0)
+                        goto out_err;
         }
         strbuf_release(&key);
 
@@ -102,6 +111,19 @@ void install_branch_config(int flag, const char *local, const char *origin, cons
                                           local, remote);
                 }
         }
+
+        return 0;
+
+out_err:
+        strbuf_release(&key);
+        error(_("Unable to write upstream branch configuration"));
+
+        advise(_(tracking_advice),
+               origin ? origin : "",
+               origin ? "/" : "",
+               shortname ? shortname : remote);
+
+        return -1;
 }
 
 /*
@@ -109,8 +131,8 @@ void install_branch_config(int flag, const char *local, const char *origin, cons
  * to infer the settings for branch.<new_ref>.{remote,merge} from the
  * config.
  */
-static int setup_tracking(const char *new_ref, const char *orig_ref,
-                          enum branch_track track, int quiet)
+static void setup_tracking(const char *new_ref, const char *orig_ref,
+                           enum branch_track track, int quiet)
 {
         struct tracking tracking;
         int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
@@ -118,7 +140,7 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
         memset(&tracking, 0, sizeof(tracking));
         tracking.spec.dst = (char *)orig_ref;
         if (for_each_remote(find_tracked_branch, &tracking))
-                return 1;
+                return;
 
         if (!tracking.matches)
                 switch (track) {
@@ -127,18 +149,18 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
                 case BRANCH_TRACK_OVERRIDE:
                         break;
                 default:
-                        return 1;
+                        return;
                 }
 
         if (tracking.matches > 1)
-                return error(_("Not tracking: ambiguous information for ref %s"),
-                                orig_ref);
+                die(_("Not tracking: ambiguous information for ref %s"),
+                    orig_ref);
 
-        install_branch_config(config_flags, new_ref, tracking.remote,
-                              tracking.src ? tracking.src : orig_ref);
+        if (install_branch_config(config_flags, new_ref, tracking.remote,
+                              tracking.src ? tracking.src : orig_ref) < 0)
+                exit(-1);
 
         free(tracking.src);
-        return 0;
 }
 
 int read_branch_desc(struct strbuf *buf, const char *branch_name)
diff --git a/branch.h b/branch.h
index 58aa45fe72..78ad4387cd 100644
--- a/branch.h
+++ b/branch.h
@@ -43,9 +43,10 @@ void remove_branch_state(void);
 /*
  * Configure local branch "local" as downstream to branch "remote"
  * from remote "origin".  Used by git branch --set-upstream.
+ * Returns 0 on success.
  */
 #define BRANCH_CONFIG_VERBOSE 01
-extern void install_branch_config(int flag, const char *local, const char *origin, const char *remote);
+extern int install_branch_config(int flag, const char *local, const char *origin, const char *remote);
 
 /*
  * Read branch description
diff --git a/builtin/branch.c b/builtin/branch.c
index 3f6c825db1..7b45b6bd6b 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -570,7 +570,6 @@ static const char edit_description[] = "BRANCH_DESCRIPTION";
 
 static int edit_branch_description(const char *branch_name)
 {
-        int status;
         struct strbuf buf = STRBUF_INIT;
         struct strbuf name = STRBUF_INIT;
 
@@ -595,11 +594,11 @@ static int edit_branch_description(const char *branch_name)
         strbuf_stripspace(&buf, 1);
 
         strbuf_addf(&name, "branch.%s.description", branch_name);
-        status = git_config_set(name.buf, buf.len ? buf.buf : NULL);
+        git_config_set(name.buf, buf.len ? buf.buf : NULL);
         strbuf_release(&name);
         strbuf_release(&buf);
 
-        return status;
+        return 0;
 }
 
 int cmd_branch(int argc, const char **argv, const char *prefix)
diff --git a/builtin/clone.c b/builtin/clone.c
index a0b3cd9e56..8a90cad5b5 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -732,7 +732,7 @@ static int checkout(void)
 
 static int write_one_config(const char *key, const char *value, void *data)
 {
-        return git_config_set_multivar(key, value ? value : "true", "^$", 0);
+        return git_config_set_multivar_gently(key, value ? value : "true", "^$", 0);
 }
 
 static void write_config(struct string_list *config)
diff --git a/builtin/config.c b/builtin/config.c
index adc772786a..c26d6e7fdd 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -582,7 +582,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                 check_write();
                 check_argc(argc, 2, 2);
                 value = normalize_value(argv[0], argv[1]);
-                ret = git_config_set_in_file(given_config_source.file, argv[0], value);
+                ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
                 if (ret == CONFIG_NOTHING_SET)
                         error("cannot overwrite multiple values with a single value\n"
                         "       Use a regexp, --add or --replace-all to change %s.", argv[0]);
@@ -592,23 +592,23 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                 check_write();
                 check_argc(argc, 2, 3);
                 value = normalize_value(argv[0], argv[1]);
-                return git_config_set_multivar_in_file(given_config_source.file,
-                                                       argv[0], value, argv[2], 0);
+                return git_config_set_multivar_in_file_gently(given_config_source.file,
+                                                              argv[0], value, argv[2], 0);
         }
         else if (actions == ACTION_ADD) {
                 check_write();
                 check_argc(argc, 2, 2);
                 value = normalize_value(argv[0], argv[1]);
-                return git_config_set_multivar_in_file(given_config_source.file,
-                                                       argv[0], value,
-                                                       CONFIG_REGEX_NONE, 0);
+                return git_config_set_multivar_in_file_gently(given_config_source.file,
+                                                              argv[0], value,
+                                                              CONFIG_REGEX_NONE, 0);
         }
         else if (actions == ACTION_REPLACE_ALL) {
                 check_write();
                 check_argc(argc, 2, 3);
                 value = normalize_value(argv[0], argv[1]);
-                return git_config_set_multivar_in_file(given_config_source.file,
-                                                       argv[0], value, argv[2], 1);
+                return git_config_set_multivar_in_file_gently(given_config_source.file,
+                                                              argv[0], value, argv[2], 1);
         }
         else if (actions == ACTION_GET) {
                 check_argc(argc, 1, 2);
@@ -634,17 +634,17 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                 check_write();
                 check_argc(argc, 1, 2);
                 if (argc == 2)
-                        return git_config_set_multivar_in_file(given_config_source.file,
-                                                               argv[0], NULL, argv[1], 0);
+                        return git_config_set_multivar_in_file_gently(given_config_source.file,
+                                                                      argv[0], NULL, argv[1], 0);
                 else
-                        return git_config_set_in_file(given_config_source.file,
-                                                      argv[0], NULL);
+                        return git_config_set_in_file_gently(given_config_source.file,
+                                                             argv[0], NULL);
         }
         else if (actions == ACTION_UNSET_ALL) {
                 check_write();
                 check_argc(argc, 1, 2);
-                return git_config_set_multivar_in_file(given_config_source.file,
-                                                       argv[0], NULL, argv[1], 1);
+                return git_config_set_multivar_in_file_gently(given_config_source.file,
+                                                              argv[0], NULL, argv[1], 1);
         }
         else if (actions == ACTION_RENAME_SECTION) {
                 int ret;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 07229d60f1..6223b7d46a 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -250,7 +250,7 @@ static int create_default_files(const char *template_path)
                 git_config_set("core.bare", "false");
                 /* allow template config file to override the default */
                 if (log_all_ref_updates == -1)
-                    git_config_set("core.logallrefupdates", "true");
+                        git_config_set("core.logallrefupdates", "true");
                 if (needs_work_tree_config(get_git_dir(), work_tree))
                         git_config_set("core.worktree", work_tree);
         }
diff --git a/builtin/remote.c b/builtin/remote.c
index 6694cf20ef..43136951b5 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -108,8 +108,8 @@ enum {
 #define MIRROR_PUSH 2
 #define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH)
 
-static int add_branch(const char *key, const char *branchname,
-                const char *remotename, int mirror, struct strbuf *tmp)
+static void add_branch(const char *key, const char *branchname,
+                       const char *remotename, int mirror, struct strbuf *tmp)
 {
         strbuf_reset(tmp);
         strbuf_addch(tmp, '+');
@@ -119,7 +119,7 @@ static int add_branch(const char *key, const char *branchname,
         else
                 strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s",
                                 branchname, remotename, branchname);
-        return git_config_set_multivar(key, tmp->buf, "^$", 0);
+        git_config_set_multivar(key, tmp->buf, "^$", 0);
 }
 
 static const char mirror_advice[] =
@@ -197,8 +197,7 @@ static int add(int argc, const char **argv)
                 die(_("'%s' is not a valid remote name"), name);
 
         strbuf_addf(&buf, "remote.%s.url", name);
-        if (git_config_set(buf.buf, url))
-                return 1;
+        git_config_set(buf.buf, url);
 
         if (!mirror || mirror & MIRROR_FETCH) {
                 strbuf_reset(&buf);
@@ -206,25 +205,22 @@ static int add(int argc, const char **argv)
                 if (track.nr == 0)
                         string_list_append(&track, "*");
                 for (i = 0; i < track.nr; i++) {
-                        if (add_branch(buf.buf, track.items[i].string,
-                                       name, mirror, &buf2))
-                                return 1;
+                        add_branch(buf.buf, track.items[i].string,
+                                   name, mirror, &buf2);
                 }
         }
 
         if (mirror & MIRROR_PUSH) {
                 strbuf_reset(&buf);
                 strbuf_addf(&buf, "remote.%s.mirror", name);
-                if (git_config_set(buf.buf, "true"))
-                        return 1;
+                git_config_set(buf.buf, "true");
         }
 
         if (fetch_tags != TAGS_DEFAULT) {
                 strbuf_reset(&buf);
                 strbuf_addf(&buf, "remote.%s.tagopt", name);
-                if (git_config_set(buf.buf,
-                        fetch_tags == TAGS_SET ? "--tags" : "--no-tags"))
-                        return 1;
+                git_config_set(buf.buf,
+                               fetch_tags == TAGS_SET ? "--tags" : "--no-tags");
         }
 
         if (fetch && fetch_remote(name))
@@ -590,25 +586,20 @@ static int migrate_file(struct remote *remote)
 
         strbuf_addf(&buf, "remote.%s.url", remote->name);
         for (i = 0; i < remote->url_nr; i++)
-                if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0))
-                        return error(_("Could not append '%s' to '%s'"),
-                                        remote->url[i], buf.buf);
+                git_config_set_multivar(buf.buf, remote->url[i], "^$", 0);
         strbuf_reset(&buf);
         strbuf_addf(&buf, "remote.%s.push", remote->name);
         for (i = 0; i < remote->push_refspec_nr; i++)
-                if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0))
-                        return error(_("Could not append '%s' to '%s'"),
-                                        remote->push_refspec[i], buf.buf);
+                git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0);
         strbuf_reset(&buf);
         strbuf_addf(&buf, "remote.%s.fetch", remote->name);
         for (i = 0; i < remote->fetch_refspec_nr; i++)
-                if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0))
-                        return error(_("Could not append '%s' to '%s'"),
-                                        remote->fetch_refspec[i], buf.buf);
+                git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0);
         if (remote->origin == REMOTE_REMOTES)
                 unlink_or_warn(git_path("remotes/%s", remote->name));
         else if (remote->origin == REMOTE_BRANCHES)
                 unlink_or_warn(git_path("branches/%s", remote->name));
+
         return 0;
 }
 
@@ -655,8 +646,7 @@ static int mv(int argc, const char **argv)
 
         strbuf_reset(&buf);
         strbuf_addf(&buf, "remote.%s.fetch", rename.new);
-        if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
-                return error(_("Could not remove config section '%s'"), buf.buf);
+        git_config_set_multivar(buf.buf, NULL, NULL, 1);
         strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);
         for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
                 char *ptr;
@@ -676,8 +666,7 @@ static int mv(int argc, const char **argv)
                                   "\tPlease update the configuration manually if necessary."),
                                 buf2.buf);
 
-                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
-                        return error(_("Could not append '%s'"), buf.buf);
+                git_config_set_multivar(buf.buf, buf2.buf, "^$", 0);
         }
 
         read_branches();
@@ -687,9 +676,7 @@ static int mv(int argc, const char **argv)
                 if (info->remote_name && !strcmp(info->remote_name, rename.old)) {
                         strbuf_reset(&buf);
                         strbuf_addf(&buf, "branch.%s.remote", item->string);
-                        if (git_config_set(buf.buf, rename.new)) {
-                                return error(_("Could not set '%s'"), buf.buf);
-                        }
+                        git_config_set(buf.buf, rename.new);
                 }
         }
 
@@ -787,10 +774,7 @@ static int rm(int argc, const char **argv)
                                 strbuf_reset(&buf);
                                 strbuf_addf(&buf, "branch.%s.%s",
                                                 item->string, *k);
-                                if (git_config_set(buf.buf, NULL)) {
-                                        strbuf_release(&buf);
-                                        return -1;
-                                }
+                                git_config_set(buf.buf, NULL);
                         }
                 }
         }
@@ -1409,24 +1393,20 @@ static int update(int argc, const char **argv)
 
 static int remove_all_fetch_refspecs(const char *remote, const char *key)
 {
-        return git_config_set_multivar(key, NULL, NULL, 1);
+        return git_config_set_multivar_gently(key, NULL, NULL, 1);
 }
 
-static int add_branches(struct remote *remote, const char **branches,
-                        const char *key)
+static void add_branches(struct remote *remote, const char **branches,
+                         const char *key)
 {
         const char *remotename = remote->name;
         int mirror = remote->mirror;
         struct strbuf refspec = STRBUF_INIT;
 
         for (; *branches; branches++)
-                if (add_branch(key, *branches, remotename, mirror, &refspec)) {
-                        strbuf_release(&refspec);
-                        return 1;
-                }
+                add_branch(key, *branches, remotename, mirror, &refspec);
 
         strbuf_release(&refspec);
-        return 0;
 }
 
 static int set_remote_branches(const char *remotename, const char **branches,
@@ -1445,10 +1425,7 @@ static int set_remote_branches(const char *remotename, const char **branches,
                 strbuf_release(&key);
                 return 1;
         }
-        if (add_branches(remote, branches, key.buf)) {
-                strbuf_release(&key);
-                return 1;
-        }
+        add_branches(remote, branches, key.buf);
 
         strbuf_release(&key);
         return 0;
@@ -1580,10 +1557,11 @@ static int set_url(int argc, const char **argv)
         if ((!oldurl && !delete_mode) || add_mode) {
                 if (add_mode)
                         git_config_set_multivar(name_buf.buf, newurl,
-                                "^$", 0);
+                                                       "^$", 0);
                 else
                         git_config_set(name_buf.buf, newurl);
                 strbuf_release(&name_buf);
+
                 return 0;
         }
 
diff --git a/cache.h b/cache.h
index 015d53bdff..e2e64d188e 100644
--- a/cache.h
+++ b/cache.h
@@ -1485,7 +1485,7 @@ extern int update_server_info(int);
 /* git_config_parse_key() returns these negated: */
 #define CONFIG_INVALID_KEY 1
 #define CONFIG_NO_SECTION_OR_NAME 2
-/* git_config_set(), git_config_set_multivar() return the above or these: */
+/* git_config_set_gently(), git_config_set_multivar_gently() return the above or these: */
 #define CONFIG_NO_LOCK -1
 #define CONFIG_INVALID_FILE 3
 #define CONFIG_NO_WRITE 4
@@ -1523,12 +1523,16 @@ extern int git_config_bool(const char *, const char *);
 extern int git_config_maybe_bool(const char *, const char *);
 extern int git_config_string(const char **, const char *, const char *);
 extern int git_config_pathname(const char **, const char *, const char *);
-extern int git_config_set_in_file(const char *, const char *, const char *);
-extern int git_config_set(const char *, const char *);
+extern int git_config_set_in_file_gently(const char *, const char *, const char *);
+extern void git_config_set_in_file(const char *, const char *, const char *);
+extern int git_config_set_gently(const char *, const char *);
+extern void git_config_set(const char *, const char *);
 extern int git_config_parse_key(const char *, char **, int *);
 extern int git_config_key_is_valid(const char *key);
-extern int git_config_set_multivar(const char *, const char *, const char *, int);
-extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
+extern int git_config_set_multivar_gently(const char *, const char *, const char *, int);
+extern void git_config_set_multivar(const char *, const char *, const char *, int);
+extern int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, int);
+extern void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
 extern int git_config_rename_section_in_file(const char *, const char *, const char *);
 extern const char *git_etc_gitconfig(void);
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 079070ff1d..dfbe6d8408 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -50,7 +50,8 @@ void probe_utf8_pathname_composition(void)
                 close(output_fd);
                 git_path_buf(&path, "%s", auml_nfd);
                 precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
-                git_config_set("core.precomposeunicode", precomposed_unicode ? "true" : "false");
+                git_config_set("core.precomposeunicode",
+                               precomposed_unicode ? "true" : "false");
                 git_path_buf(&path, "%s", auml_nfc);
                 if (unlink(path.buf))
                         die_errno(_("failed to unlink '%s'"), path.buf);
diff --git a/config.c b/config.c
index 86a5eb2571..325c3eaf9d 100644
--- a/config.c
+++ b/config.c
@@ -1825,15 +1825,26 @@ contline:
         return offset;
 }
 
-int git_config_set_in_file(const char *config_filename,
-                        const char *key, const char *value)
+int git_config_set_in_file_gently(const char *config_filename,
+                                  const char *key, const char *value)
 {
-        return git_config_set_multivar_in_file(config_filename, key, value, NULL, 0);
+        return git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, 0);
 }
 
-int git_config_set(const char *key, const char *value)
+void git_config_set_in_file(const char *config_filename,
+                            const char *key, const char *value)
 {
-        return git_config_set_multivar(key, value, NULL, 0);
+        git_config_set_multivar_in_file(config_filename, key, value, NULL, 0);
+}
+
+int git_config_set_gently(const char *key, const char *value)
+{
+        return git_config_set_multivar_gently(key, value, NULL, 0);
+}
+
+void git_config_set(const char *key, const char *value)
+{
+        git_config_set_multivar(key, value, NULL, 0);
 }
 
 /*
@@ -1950,9 +1961,10 @@ int git_config_key_is_valid(const char *key)
  * - the config file is removed and the lock file rename()d to it.
  *
  */
-int git_config_set_multivar_in_file(const char *config_filename,
-                                const char *key, const char *value,
-                                const char *value_regex, int multi_replace)
+int git_config_set_multivar_in_file_gently(const char *config_filename,
+                                           const char *key, const char *value,
+                                           const char *value_regex,
+                                           int multi_replace)
 {
         int fd = -1, in_fd = -1;
         int ret;
@@ -2179,11 +2191,27 @@ write_err_out:
 
 }
 
-int git_config_set_multivar(const char *key, const char *value,
-                        const char *value_regex, int multi_replace)
+void git_config_set_multivar_in_file(const char *config_filename,
+                                     const char *key, const char *value,
+                                     const char *value_regex, int multi_replace)
+{
+        if (git_config_set_multivar_in_file_gently(config_filename, key, value,
+                                                   value_regex, multi_replace) < 0)
+                die(_("Could not set '%s' to '%s'"), key, value);
+}
+
+int git_config_set_multivar_gently(const char *key, const char *value,
+                                   const char *value_regex, int multi_replace)
+{
+        return git_config_set_multivar_in_file_gently(NULL, key, value, value_regex,
+                                                      multi_replace);
+}
+
+void git_config_set_multivar(const char *key, const char *value,
+                             const char *value_regex, int multi_replace)
 {
-        return git_config_set_multivar_in_file(NULL, key, value, value_regex,
-                                               multi_replace);
+        git_config_set_multivar_in_file(NULL, key, value, value_regex,
+                                        multi_replace);
 }
 
 static int section_name_match (const char *buf, const char *name)
diff --git a/submodule.c b/submodule.c
index 14e76247bf..b58d4ee945 100644
--- a/submodule.c
+++ b/submodule.c
@@ -68,7 +68,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
         strbuf_addstr(&entry, "submodule.");
         strbuf_addstr(&entry, submodule->name);
         strbuf_addstr(&entry, ".path");
-        if (git_config_set_in_file(".gitmodules", entry.buf, newpath) < 0) {
+        if (git_config_set_in_file_gently(".gitmodules", entry.buf, newpath) < 0) {
                 /* Maybe the user already did that, don't error out here */
                 warning(_("Could not update .gitmodules entry %s"), entry.buf);
                 strbuf_release(&entry);
@@ -1034,11 +1034,9 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)
         /* Update core.worktree setting */
         strbuf_reset(&file_name);
         strbuf_addf(&file_name, "%s/config", git_dir);
-        if (git_config_set_in_file(file_name.buf, "core.worktree",
-                                   relative_path(real_work_tree, git_dir,
-                                                 &rel_path)))
-                die(_("Could not set core.worktree in %s"),
-                    file_name.buf);
+        git_config_set_in_file(file_name.buf, "core.worktree",
+                               relative_path(real_work_tree, git_dir,
+                                             &rel_path));
 
         strbuf_release(&file_name);
         strbuf_release(&rel_path);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index cdaf6f64ec..a897248490 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -446,6 +446,13 @@ test_expect_success '--set-upstream-to fails on a non-ref' '
         test_must_fail git branch --set-upstream-to HEAD^{}
 '
 
+test_expect_success '--set-upstream-to fails on locked config' '
+        test_when_finished "rm -f .git/config.lock" &&
+        >.git/config.lock &&
+        git branch locked &&
+        test_must_fail git branch --set-upstream-to locked
+'
+
 test_expect_success 'use --set-upstream-to modify HEAD' '
         test_config branch.master.remote foo &&
         test_config branch.master.merge foo &&
@@ -466,6 +473,13 @@ test_expect_success '--unset-upstream should fail if given a non-existent branch
         test_must_fail git branch --unset-upstream i-dont-exist
 '
 
+test_expect_success '--unset-upstream should fail if config is locked' '
+        test_when_finished "rm -f .git/config.lock" &&
+        git branch --set-upstream-to locked &&
+        >.git/config.lock &&
+        test_must_fail git branch --unset-upstream
+'
+
 test_expect_success 'test --unset-upstream on HEAD' '
         git branch my14 &&
         test_config branch.master.remote foo &&
@@ -579,7 +593,7 @@ test_expect_success 'avoid ambiguous track' '
         git config remote.ambi1.fetch refs/heads/lalala:refs/heads/master &&
         git config remote.ambi2.url lilili &&
         git config remote.ambi2.fetch refs/heads/lilili:refs/heads/master &&
-        git branch all1 master &&
+        test_must_fail git branch all1 master &&
         test -z "$(git config branch.all1.merge)"
 '
 
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index dfaf9d9f68..013e03dee2 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -932,6 +932,15 @@ test_expect_success 'get-url on new remote' '
         echo foo | get_url_test --push --all someremote
 '
 
+test_expect_success 'remote set-url with locked config' '
+        test_when_finished "rm -f .git/config.lock" &&
+        git config --get-all remote.someremote.url >expect &&
+        >.git/config.lock &&
+        test_must_fail git remote set-url someremote baz &&
+        git config --get-all remote.someremote.url >actual &&
+        cmp expect actual
+'
+
 test_expect_success 'remote set-url bar' '
         git remote set-url someremote bar &&
         echo bar >expect &&